hy,
I've a little probleme with a graphics. I've an image witch I resize like this :
Image BigImage = img.getScaledInstance(115, 154, java.awt.Image.SCALE_SMOOTH);
and I tried ti draw it on a graphic:
g2.drawImage(BigImage, 0, 0, null);
it's unfortunately not working.
it only work if i add ImageIcon te = new ImageIcon(BigImage);
Image BigImage = img.getScaledInstance(115, 154, java.awt.Image.SCALE_SMOOTH);
ImageIcon te = new ImageIcon(BigImage);
g2.drawImage(BigImage, 0, 0, null);
Do you have any idea why? Have you another way to do it?
I can't say right now why your code doesn't work, but you can directly draw a scaled instance of the image using this drawImage method. It worked for me.
The documenttion for Image.getScaledInstance() states in part..
The new Image object may be loaded asynchronously even if the original source image has already been loaded completely.
(My emphasis)
One way to correct the problem is to add the image to a MediaTracker to ensure it is loaded before rendering. But most importantly, do not do any of this from within the paint()/paintComponent() method, which is what I suspect given the code snippet. The instantiation of the ImageIcon was probably slowing down the execution just enough for the image to load.
Another tip I will offer is that you will get better help sooner if you post an SSCCE. This is particularly useful for image based examples, since if you'd hot-linked to an image available on the net, we could've seen just how big the image was that was being rescaled. ;)
Related
I am creating a Java game, and in this, I have a plane that can be moved around by the user, however if the plane hits any of the sides, it should explode - meaning there should be an explosion at that location. I used links such as: Why gif animation doesn't animate when using it in paintComponent()? and other ones to find out how to animate a gif, however, my code doesn't work.
Here is the relevant code:
ImageIcon ii = new ImageIcon(this.getClass().getResource("explosion.gif"));
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(ii.getImage(), planeX, planeY, this);
System.out.println("drawn");
Although "drawn" is being printed out on the console, the explosion gif doesn't load. I checked the file name and it was correct. However, I did use the same gif somewhere else in my code and it worked there, so is there something that prevents having a gif being used twice in Java?
Here is my entire paintComponent() method:
super.paintComponent(g);
setFocusable(true);
requestFocus();
background = new ImageIcon("bg.png").getImage();
g.drawImage(background, -6, 0, 700, 700, null); //background of JPanel
if (!hit) g.drawImage(plane, planeX, planeY, planeLen, planeHei, null); //only draw plane if not exploded
else if (count == 0)
{
ImageIcon ii = new ImageIcon(this.getClass().getResource("explosion.gif"));
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(ii.getImage(), planeX, planeY, this); //doesn't work
System.out.println("drawn"); //printed
}
title = new ImageIcon("title.png").getImage(); //transparent, is drawn
g.drawImage(title, -9, 20, 700, 218, null);
title2 = new ImageIcon("title2.png").getImage(); //transparent, is drawn
g.drawImage(title2, 10, 245, 670, 20, null);
I have checked title and title2 and they are transparent, meaning that the explosion should be seen. I even tried it below those two images, and the explosion still is not visible. I am using JButtons and KeyListeners on this panel as well.
Please let me know if I should add anything else, and thank you in advance!
You should always pass this as the final argument to drawImage in a painting method. If an image has multiple frames, or the image is loaded in the background, this tells the component to paint itself again as more of the image becomes available.
Painting of components happens frequently. It is controlled by the system, not just by code calling the component’s repaint methods. In fact, it’s common for painting to happen many times per second. Many system events beyond a programmer’s control can trigger painting, such as a user moving a window, or another window moving, or even the user moving the mouse.
For this reason, painting should not perform slow operations like loading files. Move the loading of your images out of your painting method, and into the class’s constructor. Store the Image objects in private fields, where paintComponent can use them again and again without reloading them for every painting run.
Since the timing of painting is beyond your control, it is important that you never change the state of a component in a painting method. Move setFocusable and requestFocus out of your paintComponent method. Those calls should be in the code that builds your component and adds it to a window.
Finally, be aware that loading images from files will not work if you ever package your application in a .jar file. A .jar file is a single compressed archive; the entries in it are not files anymore, they’re just sequences of bytes inside the archive. Loading all files using getResource will address this, since getResource looks in every .jar file in the classpath.
Never mind, I had to make a duplicate of "explosion.gif". It works fine now!
However, please let me know if there is another way of doing this, much faster AND efficiently. Thanks!
I have an application that plots images on a JPanel. I want to dispose of the GUI altogether, so that the application is called from code only, with no user interface, and so that the images are saved to a gif file only.
I have experimented with code from this question, and it seems to work fine when I call the save gif code from within the old GUI. However, the save gif code is not seeming to work when I remove the GUI, and I am wondering if that might be because the JPanel it is trying to print has not actually made it to a GUI container like a JFrame, etc.
The reason I am not posting code is that it is too verbose, an I am just asking for a simple, boilerplate answer.
I have experimented with writeablerasters for other applications. But that would require a major recoding project for this application, which paints by using the graphics.drawLine() method. Can anyone suggest a code-efficient way to take contents of a "phantom" JPanel, get it into a BufferedImage, and then save it as a gif without ever putting the JPanel in a GUI?
Since your application draws on a JPanel then it just needs a Graphics object. You can use one from a BufferedImage which then you will save to file. Example code:
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
// Pass this graphics object to your application to perform the drawing
g.setColor(Color.red);
g.drawRoundRect(10, 10, 20, 20, 5, 5);
// save it to disk
ImageIO.write(image, "png", new File("test.png"));
This is difficult to answer without any example code, however.
If the component you are trying to render is not displayed on the screen, it is likely that it has not being laid out.
Before painting, you should make sure you size the component.
componentToBePainted.setSize(componentToBePainted.getPreferredSize());
You should also be using print or printAll over paint. When not attached to a native peer, paint can cause issue
Could someone explain why this line of code isn't working. No errors are given. It simply doesn't resize the image.
image = ImageIO.read(file);
image.getScaledInstance(ImageDisplayBox.getWidth(), ImageDisplayBox.getHeight());
ImageDisplayBox.setIcon(new ImageIcon(image));
I've looked at the other answers on Stackoverflow and noticed a lot of people using the .getScaledInstance method.
I (think) it might be the fact that I have it as .setIcon - Although I'm not the best with Java.
The image is printed but displays only the top left of the image due to size.
You're ignoring the returned value. You want:
image = image.getScaledInstance(ImageDisplayBox.getWidth(),
ImageDisplayBox.getHeight(), 5);
Or maybe to make things clearer:
Image scaled = image.getScaledInstance(ImageDisplayBox.getWidth(),
ImageDisplayBox.getHeight(), 5);
ImageDisplayBox.setIcon(new ImageIcon(scaled));
From the docs:
Creates a scaled version of this image. A new Image object is returned which will render the image at the specified width and height by default. The new Image object may be loaded asynchronously even if the original source image has already been loaded completely.
Note that that doesn't say anything about changing the existing image. It just creates a new image with the given size.
Yes
This should work
Image scaled =image.getScaledInstance(ImageDisplayBox.getWidth(),
ImageDisplayBox.getHeight(), 5);
ImageDisplayBox.setIcon(new ImageIcon(scaled));
I've encountered a problem. My image is too big so it enlarges the corresponding JMenuItem. I don't want to develop bicycles like
ImageIcon image = new ImageIcon(new ImageIcon("/home/template/img.jpg")
.getImage().getScaledInstance(32, 32, Image.SCALE_DEFAULT));
Is there any other way to accomplish that?
If you don't want to scale the image in code (I presume that's what you mean in the question?), why not just make the source image that size to start with? The simplest solution is sometimes the best!
Also, getScaledInstance() is generally a bad idea. This explains why and gives better options for resizing the image. If you're using the image elsewhere, then it's worth reading up on that article and scaling it using a better technique (such as graphics.drawImage()). But if you're just using it in the menu, then resizing the source image is probably the best thing to do.
If you are going to resize:
BufferedImage image = ImageIO.read("img.jpg");
BufferedImage ret = new BufferedImage(32,32,BufferedImage.TYPE_RGB);
ret.getGraphics().drawImage(image,0,0,32,32,null);
Something like that should give you the image, you can then create your ImageIcon using ret.
i'm trying to create a program that generates images for use as multi-screen backgrounds, i'm doing this targeted at windows (in my case, 7 so that basically i can get images to change without seeing the same image on two different screens)
in my program, i read multiple image input files and compile them into a single output image that is the total size of the desktop (including black areas not seen on screens)
my question is, what class/methods are good for cropping/resizing/pasting into a new image in java because i'm coming across so many image manipulation classes and they all seem to do one tiny thing.
i will not be modifying any of the images beyond resize or crop and putting it into a certain position in the new (initially blank) image.
code can be made available as i plan to release it at some later point for whoever may like/need it.
thank you in advance, if this question has been answered, my apologies but i DID have a look around.
I do not know if this is the best method, but it is quite easy:
// load an image
Image image = javax.imageio.ImageIO.read(new File("someimage.png");
// resize it
image = image.getScaledInstance(100, 100, Image.SCALE_SMOOTH);
// create a new image to render to
BufferedImage newimg = new BufferedImage(200,100,BufferedImage.TYPE_INT_ARGB);
// get graphics to draw..
Graphics2D graphics =newimg.createGraphics();
//draw the other image on it
graphics.drawImage(image,0,0,null);
graphics.drawImage(image,100,0,null);
graphics.fillOval(20,20,40,40); //making it a bit ugly ;)
//export the new image
ImageIO.write(newimg,"png",new File("output.png"));
//done!
For simplicity I dropped all checks, exception handling, etc.