repainting the image using bufferedimage - java

i am learning to write code in java and recently started to write a game as per my assignment.
i have completed almost entire game but stuck with the animation part of the game.
here is what i have done so far,
this is the class that load the image ti display,
public class dpmImage {
private BufferedImage dpm1;
private BufferedImage setDpm1;
public dpmImage() { //this is a constructor
try {
dpm1= ImageIO.read(new File("dpm1Load.png"));
} catch (IOException e) {
e.printStackTrace();
}
setDpm1 = dpm1;
}
private BufferedImage dpm1ImageGet() {
return setDpm1;
}
}
the following code is from main class (Main.java)
private Graphics cGraphcs;
cGraphcs.drawImage(dpmImageInstance.dpm1ImageGet(), 0, 0, null);
The code is working fine and displays the image.
Now, I am allowed to modify anything in dpmImage class but not allowed to modify anything in Main.java and still make this image animate. So I create an array of BufferedImage in dpmImage class and add a second image in the array as follows,
public class dpmImage {
private BufferedImage [] dpm1 = new BufferedImage[2];
private BufferedImage setDpm1;
public dpmImage() { //this is a constructor
try {
dpm1[0]= ImageIO.read(new File("dpm1Load.png"));
dpm1[1]= ImageIO.read(new File("dpm1Load1.png"));
} catch (IOException e) {
e.printStackTrace();
}
setDpm1 = dpm1[0];
setDpm1 = dpm1[1];
}
private BufferedImage dpm1ImageGet() {
return setDpm1;
}
}
But i couldn't get to animate it from first image to 2nd. Can someone please give me any hints on that ? i am not allowed to change the Main.java class

You always return the same BufferedImage from the dpm1ImageGet method. You need to get the instance from the array. Based on the frequency of the update, you can simply use an index like
private int indexImage = 0;
private BufferedImage dpm1ImageGet() {
indexImage = ( indexImage + 1 ) % dpm1.length; //increment and use % to prevent any ArrayOutOfBoundsException
return dpm1[indexImage];
}
Each call will return the next image. Of course, this depends on when you want to get the other image. It could be anything.

Related

Why is there an error when I try to load an image?

So, I have made a class called TileDrawer.java, which is supposed to load in a BufferedImage with the following code:
BufferedImage spriteSheet = null;
public void initSpriteSheet() {
try {
this.spriteSheet = ImageIO.read(new File("resources\\spritesheet.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
but when I try to run the method after initializing the object, it gives me this error:
javax.imageio.IIOException: Can't read input file!
This is my current full code for the TileDrawer class:
package mainGame;
//imports
public class TileDrawer {
BufferedImage spriteSheet = null;
public void initSpriteSheet() {
try {
this.spriteSheet = ImageIO.read(new File("resources\\spritesheet.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
//irrelevant methods were here
}
and I also have this class, called GamePanel with the following code:
package mainGame;
//imports
public class GamePanel extends JPanel implements Runnable {
Thread gameThread;
TileDrawer tileDrawer = new TileDrawer();
//vars
public GamePanel() {} //game panel
public void startGameThread() {
tileDrawer.initSpriteSheet(); // <--- here
gameThread = new Thread(this);
gameThread.start();
}
#Override
public void run() {
//stuff to make a functioning loop
while (gameThread != null) {
//more loop stuff
if (delta >= 1) { //delta is only used to cap the framerate
update();
repaint();
//even more loop stuff
}
}
}
public void update() {
//update stuff here
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
//drawing stuff goes here
g2.dispose();
}
}
Some background info:
I am using Debian Linux
The directory looks like this:
MyGame
|------build
| |------(Compiled java files)
|------src
| |------Main.java (irrelevant)
| |------GamePanel.java
| |------TileDrawer.java
| |------resources
| | |------spriteSheet.png
I am not using an IDE to compile my code, I am simply using these commands:
cd /home/{my username}/MyGame/
javac -d ./build src/Main.java src/GamePanel.java src/TileDrawer.java
cd build
java mainGame.Main
All of these things I tried, but none of them worked when I tried to implement them:
changing the file path into singular normal slashes
changing the file path into singular normal slashes and putting one at the front
using a normal Image file instead of a BufferedImage
putting the image file into the same directory as the java file
Any help on how to fix my problem would be greatly appreciated.
Thanks everyone for all the help! If anyone sees this in the future, here is what I changed to make it work.
First, I moved the resource folder out of the src folder and into the root folder so it could be accessed (thanks to Jorge Campos for that).
Then, I loaded in the image as a resource instead of a file, and I fixed the capitalization error. (thanks to Hovercraft Full Of Eels and
67af7af3-67f3-48bf-98c5-d9155c for that, respectively).
In the URL, I changed the \\'s into /'s, and added one in front of it.
In total, I changed this:
this.spriteSheet = ImageIO.read(new File("resources\\spritesheet.png"));
Into this:
this.spriteSheet = ImageIO.read(getClass().getResourceAsStream("/resources/spriteSheet.png"));
and I moved the resources folder into the root folder.
Once again, thank you all for your help!
note: the 'this.' in the above code examples in unnecessary, but it works either way.

Losing AWT DrawingSurface when Canvas is hidden

I am writing 3d rendering module for an AWT/Swing application.
To provide good FPS, I can't draw using Swing/AWT methods and graphics. Instead, I obtain the Drawing Surface from the Canvas element, and then render directly to it. Something like this:
public class Window {
private Component canvas;
private JAWTDrawingSurface ds;
public static final JAWT awt;
static {
awt = JAWT.calloc();
awt.version(JAWT_VERSION_1_4);
if (!JAWT_GetAWT(awt))
throw new AssertionError("GetAWT failed");
}
public void lock() throws AWTException {
int lock = JAWT_DrawingSurface_Lock(ds, ds.Lock());
if ((lock & JAWT_LOCK_ERROR) != 0)
throw new AWTException("JAWT_DrawingSurface_Lock() failed");
}
public void unlock() throws AWTException {
JAWT_DrawingSurface_Unlock(ds, ds.Unlock());
}
public void Init2()
{
this.ds = JAWT_GetDrawingSurface(canvas, awt.GetDrawingSurface());
try
{
lock();
// Create GL Capabilities
unlock();
}
}
It works fine when I call it the first time.
But when I hide the canvas for any reason (for example minimizing window or displaying another panel instead of Canvas), the ds variable remains the same, but it doesn't work after that.
Basically, even if I make sure I call the variable only when it is visible and on top - any call using ds will throw an exception. For example lock() function stops working.
I'm wondering why's that?
Also I tried to basically obtain a new DS if I minimize and then maximize the window again, but this also doesn't work - the new DS address is returned as it should, but I can't use that new object just as I couldn't use the original one.
There's probably something stupid I'm missing here, but I can't figure out what.
Please help me sort this out. Thank you!
The solution:
When the Canvas is hidden, call eglMakeCurrent(eglDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT) to unbind the current context.
When you need to start drawing again, you need to do something like this:
public void Reinit()
{
System.err.println("Context Reinit()");
this.ds = JAWT_GetDrawingSurface(canvas, awt.GetDrawingSurface());
try
{
lock();
try
{
JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo());
JAWTX11DrawingSurfaceInfo dsiWin = JAWTX11DrawingSurfaceInfo.create(dsi.platformInfo());
this.display = dsiWin.display();
this.drawable = dsiWin.drawable();
eglDisplay = eglGetDisplay(display);
surface = eglCreateWindowSurface(eglDisplay,fbConfigs.get(0),drawable,(int[])null);
eglMakeCurrent(eglDisplay,surface,surface,context);
GLES.setCapabilities(glesCaps);
JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo());
}
finally
{
unlock();
System.err.printf("Unlock \n");
}
}
catch (Exception e)
{
System.err.println("JAWT Failed" + e.getMessage());
}
}
As You can see, I re-create the display and surface, but I use the previously created context for rendering, without needing to re-create it.

How to remove cursor from a Map (Bukkit)

I'm currently developing a plugin which only renders an image to a map like this:
public class MapRendererTest extends MapRenderer {
private Image image;
public MapRendererTest(File file) {
try {
this.image = ImageIO.read(file);
}
catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void render(MapView mapView, MapCanvas mapCanvas, Player player) {
mapCanvas.drawImage(0, 0, image);
}
}
everything works fine, but there is this little thing in the red circle that I want to remove but I don't know how.
Things I already tried
Setting an emtpy MapCursorCollection
MapView.setWorld to a world where no-one is playing.
Creating MapCursorCollection with a invisible cursor
It would be amazing if someone could help me with that.
Thanks in advance
To get rid of the cursor, you have to remove all the other map renderers or at least the CraftMapRanderer.
In order to do this, you have to do the following:
#EventHandler
public void onMapInitialized(MapInitializeEvent e) {
e.getMap().removeRenderer(e.getMap().getRenderers().get(0));
e.getMap().addRenderer(new MapRendererTest(new File(Main.getInstance().getDataFolder() + "/image.png")));
}
This only works of course if there is no other custom map renderer assigned to this map, so the only registered is the CraftMapRenderer.
If you have multiple MapRenderers you could loop through the list and remove them.

Memory leak in javacv

I'm trying to make a program that takes a picture from a webcam, and afterwards resizes it, converts it to HSV, and makes some thresholding on it, to find a specific color. After this is done, I use the thresholded image to find contours, and print the x,y coords of the different contours. This is repeated over and over, to make the processing from the webcam realtime.
It all works quite well, except for the fact that I am using up about 100 mb of RAM every 2 second it runs.
So far I have discovered that if I use a static picture, instead of the live images from the webcam, I can minimize the memory leak significantly, although still there is memory being consumed.
Below my code is:
public class Application {
private CaptureImage ci;
private ImageUtils iu;
private CanvasFrame canvasContours;
IplImage grabbedFrame;
IplImage resizedFrame;
IplImage thresholdedFrame;
IplImage clonedImage;
public Application(){
ci = new CaptureImage();
iu = new ImageUtils();
canvasContours = new CanvasFrame("contours");
}
public void frameProcessing(){
grabbedFrame = ci.grabImage();
//below call used for testing purposes
//grabbedFrame = (IplImage) opencv_highgui.cvLoadImage("testingImage.jpg");
//cloning image due to highgui guidelines.
clonedImage = opencv_core.cvCloneImage(grabbedFrame);
resizedFrame = iu.resizeImage(clonedImage);
opencv_core.cvReleaseImage(clonedImage);
thresholdedFrame = iu.thresholdImage(resizedFrame);
IplImage contoursFrame = iu.findContours(thresholdedFrame, resizedFrame);
canvasContours.showImage(contoursFrame);
}
}
The grabImage is just the standard frameGrabber from javacv, which looks like this:
public class CaptureImage {
private final OpenCVFrameGrabber grabber;
private IplImage img = null;
public CaptureImage(){
// 0-default camera, 1 - next...so on
grabber = new OpenCVFrameGrabber(0);
try {
grabber.start();
} catch (Exception e) {
System.err.print("Failed to initialize camera");
e.printStackTrace();
}
}
public IplImage grabImage(){
try {
//A grabbed image from Logitech webcam is in following resolution: 1200x800px
img = grabber.grab();
} catch (Exception e) {
e.printStackTrace();
}
return img;
}
I appreciate any help you can give me, and if you need any more information, please just ask!
/Jesper
From your heap dump, the used memory is all byte and int arrays that are referenced from native code. Looking at your code I see that you only call cvReleaseImage for the cloned image and not for the original image.

How can I use the return statement from one method in another?

I want to call the return statement tempimage in load_picture by passing it to showWindow, but I'm not sure how. heres a snippet of my code. edit:
i guess what I'm trying to say is, I'm not exactly sure what to do with the hardcoded "picture1.gif". I understand that I need to call a method to load the image, but I'm not too sure what to put in place of it.
:
package project3;
import java.util.Scanner;
import javax.swing.;
import java.awt.;
import java.net.*;
public class Project3 {
//initializing global
static Project3 theobject = new Project3();
final static int MIN_NUMBER=1;
final static int MAX_NUMBER=8;
static int image_number=1;
static Image theimage;
// This routine will load an image into memory, non-static requires an object
// It expects the name of the image file name and a JFrame passed to it
// It will assume an Internet conection is available
// It can only be called AFTER the program object has been created
// It will return a type Image variable, call it like this: theimage = object.load_picture("picture1.gif", frame);
// (hard code 'picture1.gif' only when testing - USE a method or variable for 'real' call)
// This code requires you to do an 'import java.awt.*' and an 'import java.net.*'
// Note: this method is using parameter and return type for input/output
// This routine will load an image into memory, non-static requires an object
// It expects the name of the image file name and a JFrame passed to it
// It will assume an Internet conection is available
// It can only be called AFTER the program object has been created
// It will return a type Image variable, call it like this: theimage = object.load_picture("picture1.gif", frame);
// (hard code 'picture1.gif' only when testing - USE a method or variable for 'real' call)
// This code requires you to do an 'import java.awt.*' and an 'import java.net.*'
// Note: this method is using parameter and return type for input/output
public Image load_picture(String imagefile, JFrame theframe)
{
Image tempimage;
// Create a MediaTracker to inform us when the image has
// been completely loaded.
MediaTracker tracker;
tracker = new MediaTracker(theframe);
// getImage() returns immediately. The image is not
// actually loaded until it is first used. We use a
// MediaTracker to make sure the image is loaded
// before we try to display it.
String startURL;
if (imagefile.startsWith("http"))
startURL = "";
else
startURL = "http://www.canyons.edu/departments/comp_sci/ferguson/cs111/images/";
URL myURL=null;
try
{
myURL = new URL(startURL + imagefile);
}
catch(MalformedURLException e) {
System.out.println("Error caught " + e.toString());
}
//tempimage = getImage(myURL); // JApplet version
tempimage = Toolkit.getDefaultToolkit().getImage(myURL); // stand alone program version
// Add the image to the MediaTracker so that we can wait for it
tracker.addImage(tempimage, 0);
try { tracker.waitForID(0); }
catch ( InterruptedException err) { System.err.println(err); }
return tempimage;
}
// This class/method uses a global variable that MUST be set before calling/using
// note: You can not call the paint routine directly, it is called when frame/window is shown
// look up the repaint() routine in the book
// Review Listings 8.5 and 8.6
//
public static class MyPanel extends JPanel {
public void paintComponent (Graphics g) {
JPanel panel= new JPanel();
int xpos,ypos;
super.paintComponent(g);
// set the xpos and ypos before you display the image
xpos = 300; // you pick the position
ypos = 200; // you pick the position
if (theimage != null) {
g.drawImage(theimage,xpos,ypos,this);
// note: theimage global variable must be set BEFORE paint is called
}
}
}
public static void showWindow( String filename ) {
// create, size and show a GUI window frame, you may need to click on taskbar to see window
//display the filename in the title of the window frame, otherwise the window will be blank (for now)
JFrame frame1= new JFrame();
theimage = theobject.load_picture("picture1.gif", frame1);
//"picture1.gif" is hardcoded, I want to call this using a method
frame1.setTitle(filename);
frame1.setSize(440,302);
frame1.setLocation(400,302);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setVisible(true);
}
Any help is appreciated. Thanks
The value that is returned by the load_picture method can be sent directly to the showWindow method, or you can assign it to a variable:
String filename = "your/filename";
JFrame theFrame = new JFrame();
Project3 project = new Project3();
MyPanel.showWindow(project.load_picture(filename, theFrame);
From within the showWindow method, just call the load_picture method as follows:
Image tempImage = load_picture(filename, frame1);
From here you can do anything you like with the tempImage object.

Categories

Resources