Java swing Image always has height and width of -1 - java

I know that the method returns -1 when it couldn't get the width or height of the image, but I hope you can tell me why it can't manage to do that. Here I create a few ImageIcons and save them in an Image Array:
for(int x = 0; x < playerSprites.length; x++){
playerSprites [x] = new ImageIcon("player" + x + ".png").getImage()
}
Later I create an instance of the class which only creates this Array at the moment. When I then want to get the images from the Array in the other class I check their height and width and I always get -1 on both:
public Image nextImage(String name){
Image image = null;
if(name.equals("player")){
if(counter == animationImageManager.getPlayerSprites().length-1){
counter = 0;
}
image = animationImageManager.getPlayerSprites()[counter];
counter++;
}
return image;
}

If image is not found then still it return -1 for height and width.
Try below sample code to reproduce the issue:
System.out.println(new ImageIcon("").getImage().getWidth(null)); // print -1
It's worth reading Java Tutorial on Loading Images Using getResource
May be it's not loading the images properly.
You can try any one based on image location.
// Read from same package
ImageIO.read(getClass().getResourceAsStream("c.png"));
// Read from images folder parallel to src in your project
ImageIO.read(new File("images/c.jpg"));
// Read from src/images folder
ImageIO.read(getClass().getResource("/images/c.png"))
// Read from src/images folder
ImageIO.read(getClass().getResourceAsStream("/images/c.png"))
Read more...

The width/height for Image will return -1 if the image is null. When there's no image.
Suggestions:
use ImageIO.read() which will throw an IOException if something goes wrong with the IO, like the path being wrong.
If the image is a resource for your application, then don't read it as a file, read it as a resource via URL. For instance, if the image is in src/images, then you could do
URL url = getClass().getResource("/images/myimage/png");
BufferedImage image = ImageIO.read(url);
Important thing to note with ImageIcon is when you pass a String to the constructor, it will look for the file in the local file system. It may work when you are developing, but once you deploy the application with the images in the jar, it won't work anymore, with the file path, because it will no longer be valid. You could pass the URL to ImageIcon just the same as above, but like I said, ImageIO allows for more error detection.
Just so you understand what's going on in your current code, by you specifying just the image file name as the path to the ImageIcon, the search will look for the image in the root of the project folder (if you're working in an IDE) because that's the working directory. So if your images aren't there, the images won't be found.
Another thing to note about my second bullet point is how the image is search for. You can see the path I used "/images/myimage/png". What the / in the front does, is bring the search to root of the classpath, which in development view, is the src. The calling class will normally be in some package on the classpath, say com.hello.somepackage.SomeClass. So if SomeClass tries to call the getclass getresource without the /, the search will begin from the location of the class, which is in the package.
The are just some things to consider when using resources/images. But the first couple points should get you going.

Related

JavaFX image pathway issues

I have just figured out how to unzipped a zippedfolder into the folder EBookReader/books from within my program (where EBookReader is my project). Now I have a /books/testbook/1.png (what was unzipped) however no matter what I do I can not get the program to display an image on that pathway.
System.out.println(loadedBook.returnPage());
Image page = new Image(getClass().getResourceAsStream(loadedBook.returnPage()));
ImageView imagePage = new ImageView();
imagePage.setImage(page);
imagePage.setFitWidth(350);
imagePage.setFitHeight(500);
imagePage.setPreserveRatio(true);
imagePage.setSmooth(true);
imagePage.setCache(true);
border.setCenter(imagePage);
loadedBook.returnPage() returns the string "F:\EbookReader\books\testBook\1.png" which just so happens to be the location of the image 1.png and even if I enter the string manually into the image location it still doesn't work. I heard I didn't need the getClass() junk but it doesn't work without that either. The only way I have gotten it to work is if I put the image in directly in F:\EbookReader\src\ebookreader.
EDIT: The error is that the input stream is null!
getResourceAsStream() is expecting a location either relative to the current class, or relative to the classpath. The path you showed certainly is not relative to either of those.
I recommend using the Imageconstructor taking a URL and doing
Image page = new Image(new File(loadedBook.returnPage()).toURI().toString());
You could also do
Image page = new Image(new FileInputStream(new File(loadedBook.returnPage())));

How to set up Eclipse project to load an image so that it also runs from the command line

I've built a Java application that loads an image at runtime. The location of the image is fixed relative to the project.
I would like to be able to run the program from both within Eclipse and the command line and for it to load the image correctly. However, I can only do one or the other but not both. This seems like such a trivial thing to want to do but I can't find out how to do it.
The project is set up so that it creates a bin directory for the output and puts the image in a resources sub-folder. This is fine when running from the command line as I can write my code to look in that sub folder for the file.
But when I run the program from within eclipse the current working directory is different.
What am I missing?
TIA
Update - adding some code
This is what I had originally:
BufferedImage awtImage = ImageIO.read(new File(System.getProperty("user.dir") + "/resources/image-name.png"));
Following the advice in the comments I am trying to use getResourceAsStream but I don't know what to pass to the File constructor.
InputStream temp = MyClass.class.getResourceAsStream("resources/image-name.png");
BufferedImage awtImage = ImageIO.read(new File(???));
The resource is being found because temp is not null.
I think there's 2 solutions.
1) you specify an absolute path
2) your image is in the classpath so you could load it via :
YouClass.class.getResourceAsStream("YourImg.png");
The working directory, if that's really what you mean, is not a great place to load an image from. It appears that you have an image that you would distribute with your finished program so that the program could use it. In that case, I suggest that you use Class.getResourceAsStream(), and put the image in the directory with (or near) that class.
EDIT:
Here is code I used in one of my programs for a similar purpose:
ImageIcon expandedIcon = null;
// ...
expandedIcon = new ImageIcon(TreeIcon.class.getResource("images/Expanded.png"));
The ImageIcon class is part of Swing; I don't know if you're using that, but this should serve to show you the idea. The getResource() method takes a URL; again, you might need something a little different. But this shows the pathname relative to the path of the class on which the method is called, so if TreeIcon is in x/y/z/icons, the PNG file needs to be in x/y/z/icons/images, wherever that is on that computer.
TreeIcon is a class of mine, and its internals will not help you, so I'm not posting them. All it's doing here is providing a location for the PNG file I'm loading into an ImageIcon instance.
In addition to working on a disk with a directory structure, this also works in a jar file (which is a common way to distribute a java program or library). The jar file is just a zip file, and each file in the jar/zip file has its directory associated with it, so the image can be in the jar in the correct directory just as the java classes are in their directories.
getResourceAsStream() returns a stream; if you want to use that byte stream to load as an image, find a class that converts an stream to something your image class can use as a constructor or in a load method and hook them up. This is a common thing to have to figure out with Java i/o, unfortunately there is no cookbook way to do it across all images and situations, so we can't just tell you what it is.
EDIT 2:
As from the comment, try:
ImageIO.read(new File(MyClass.class.getResource("resources/image-name.png");
I set up my Eclipse projects like this.
The input directory is added to the classpath (JavaBuildPath in Eclipse).
Finally, you access the image and / or text files like this.
private BufferedImage getIconImage() {
try {
return ImageIO.read(getClass().getResourceAsStream(
"/StockMarket.png"));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}

GImage can't find my image

I was trying the acm library and when I tried to use the GImage it can't find my image. I tried putting it everywhere and still it can't find it. Where does GImage look for an image(please be specific) thank you
I was also having the same problem. I used the full-path and it worked, e.g.:
GImage img = new GImage("/Users/abc/java/programming/abc.jpg");
add(img);
Also, I just noticed that if you are using Eclipse, you can keep the image inside bin sub-directory and then you can use filename:
GImage img = new GImage("abc.jpg");
add(img);
For the above to work, your image should be at: /Users/abc/java/programming/bin/abc.jpg"
According to the docs. it specifically consists of the following steps:
Check to see if an image with that name has already been defined. If so, return that image.
Check to see if there is a resource available with that name whose contents can be read as an Image. If so, read the image from the resource file.
Load the image from a file with the specified name, relative to the application directory or the applet code base.

Cannot find the image in the java dynamic web project

I have the following problem:
I created the servlet which should draw a dynamic graph. During the drawing process it should fetch the picture from another directory and to draw it upon another image. Everything should work fine:
try {
BufferedImage temp = ImageIO.read(new File("image/arrow.png"));
tempIm = temp.getScaledInstance(55, 55, Image.SCALE_SMOOTH);
} catch (IOException e) {
e.printStackTrace();
}
But it prints the following:
SEVERE: javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1275)
at CertificateDraw.doGet(CertificateDraw.java:36)
I tried to change the path of the File object in all possible ways it just gives the same problem even though the part of the image is still sent to the browser. So the problem is with the ImageIO.read part - how can I find why it does not load the image?!
I am working in Eclipse - servlet is in the src folder. The image is in "image" folder under the rot directory "WebContent".
Relative paths in java.io.File are relative to the current working directory (CWD). This is the folder which is currently opened when the command is given to start the Java runtime environment (in your case, the webserver). When starting the server in Eclipse, this is usually the /bin folder of the project. You can figure this by printing new File(".").getAbsolutePath().
But you shouldn't be relying on relative paths in File at all. The CWD is not controllable from inside the code.
As it's in the webcontent folder already, just get it by ServletContext#getResourceAsStream() instead.
InputStream input = getServletContext().getResourceAsStream("/image/arrow.png");
BufferedImage image = ImageIO.read(input);
// ...
Note that the getServletContext() is inherited from the GenericServlet class which the HttpServlet extends from, so you don't need to provide the method yourself.

What is the correct path for Toolkit.getImage()?

I need to upload an image file and generate a thumbnail for the uploaded file in my JSF webapplication. The original image is stored on the server in /home/myname/tomcat/webapps/uploads, while the thumbnail is stored in /home/myname/tomcat/webapps/uploads/thumbs. I'm using the thumbnail generator class I copied from philreeve.com.
I have successfully uploaded the file with help from BalusC. But using Toolkit.getImage(), I can't access the image.
I used the uploaded file's absolute path, like so:
inFilename = file.getAbsolutePath();
The relevant code from the thumbnail generator is:
public static String createThumbnail(String inFilename, String outFilename, int largestDimension) {
...
Image inImage = Toolkit.getDefaultToolkit().getImage(inFilename);
if (inImage.getWidth(null) == -1 || inImage.getHeight(null) == -1) {
return "Error loading file: \"" + new File(inFilename).getAbsolutePath() + "\"";
}
...
}
Since I am already using the absolute path, I don't understand why it is not working. I have also used the following values for inFilename, but I always get the "Error loading file...".
/home/myname/tomcat/webapps/uploads/filename.ext
/uploads/filename.ext
But I did check the directory, and the image is there. (I uploaded using /home/myname/tomcat/webapps/uploads/filename.ext, and it works.) What is the correct path for the image in that directory? Thank you.
Update
I got the code to work by using:
Image inImage = ImageIO.read(new File(inFilename));
I still don't understand why Toolkit.getImage() does not work though.
Are you sure it's a JPEG file? Use an image viewer to make sure nothing bad happened to the file during upload (or that it was an image to begin with).
Also, use new File(inFilename).exists() to make sure the path is correct. I also suggest to print new File(inFilename).getAbsolutePath() in error messages because relative paths can hurt you.
That said, the rest of the code looks correct.
The problem is that Toolkit.getImage() does not return the image immediately. The issue is well-described in this bug report, a relevant extract of which is here:
This is not a bug. The submitter is not properly using the asynchronous
Image API correctly. He assumes that getImage loads all of the image's bits
into memory. However, it is well documented that the actual loading of
bits does not take place until a call to Component.prepareImage or
Graphics.drawImage. In addition, these two functions return before the
Image is fully loaded. Developers are required to install an ImageObserver
to listen for notification that the Image has been fully loaded. Once they
receive this notification, they can repaint the Image.
I found that the answer to this question works well:
Image image = new ImageIcon(this.getClass().getResource("/images/bell-icon16.png")).getImage();

Categories