I'm working on a game, and I've stumbled across a fews ways to load an image into my program. There are two common ways:
The first (No class folder needed):
ImageIcon ii = new ImageIcon("image.png");
Image i = ii.getImage();
When using this method, you simply add a folder to your Project Folder (In Eclipse) and DO NOT have to make it an external class folder.
The second option (Class folder needed):
Image i = ImageIO.read(ImageLoader.class.getResource("image.png"));
You can only load images this way if you made a resource folder (typically called 'res') and added it as an external class folder to your project.
My question is why would you use the second option instead of the first? From my limited experience, it seems like the first option works just the same as the second, just without having to turn the folder you're adding it to into an external class folder.
The first option doesn't work if you package your application as a jar. The second option works in both cases, as an exploded application in an ide or on the hard drive and packaged in a jar file.
new ImageIcon("image.png"); assumes that the image is stored on the file system (in your case, in the current working directory), which raises up some issues - as the working directory isn't always the same location that the jar is stored.
ImageIO.read(ImageLoader.class.getResource("image.png")) embeds the image within the Jar file which resolves the issues associated with the first method as the image is where ever the Jar file is.
It also simplifies installation, as you only need to track the jar files and not all the other "external" files.
ImageIcon doesn't report the reasons it fails. It loads the images in a separate thread, which make diagnosing issues difficult.
ImageIO loads the image in the current thread (and returns a fully realised image) but will also generate a IOException if the image fails to load for some reason, making a much better way to load images in general. It also supports (or has the capacity to support) a wider range of images.
In general, using ImageIO and embedded images is simpler and easier to work with and is generally the recommended approach for fixed resources
Related
I don't quite understand how creation of a Swing application really works.
I have created a simple application that gets a background image from a path.
ImageIcon imageIcon = new ImageIcon("C:\\Java\\ApplicationName\\out\\Resourses\\backGround.jpg");
Image image = imageIcon.getImage(); // Создание картинки из него
Image temp = image.getScaledInstance(500,500,Image.SCALE_SMOOTH);
imageIcon = new ImageIcon(temp);
g2d.drawImage(temp,0,0,null);
It works, so I decided to make a JAR file independent from changes in the Java folder (like deleting this image) and put images in src - images ( package ). I don't know if it is possible though.
I started to get background image like this.
ImageIcon imageIcon = new ImageIcon(this.getClass().getResource("/images/backGround.jpg"));
The program works perfectly in IntelliJ IDEA but if I extract it to JAR file I get a blank background screen. Why is that?
And can I have my entire application including images in a single JAR file? One that is not dependent on other folders?
You can certainly put the image and the code in a single jar file. The image is not loading either because it's not in the jar file, or because it's not at the path /images/backGround.jpg inside the jar.
One helpful thing about jar files that you may not know: they are in .zip format, so you can use any zip tool to see what is inside the jar (temporarily renaming the jar file to .zip might make this easier). IF the image is not there, fix your jar build (you didn't say how you are making it, so not sure what you need to change). If the image is there but under a different path, then fix the jar build to put it in the right place, or change the path you are reading it from.
Yes definitely you can include your entire application into single jar file i.e. Runnable jar file. But i would suggest you not to include your image inside the jar file, instead pass that image path to an Property file and use that property file in your code for image path. So that even if next time you need to change the image you just change the path in your property file and you dont have to export your entire project again.
I am gettting a nullpointer excetion when i run the applet in browser, while its working fine through appletviewer.
titleicon=new ImageIcon(this.getClass().getClassLoader().getResource("image.jpg"));
img=new JLabel(titleicon)
File locations: Both .class file and image file are in same folder.
C:\project\game.class
C:\project\image.jpg
I tried differennt variations below, none is working in browser but all are fine with appletviewer:
titleicon=new ImageIcon(this.getClass().getResource("image.jpg"));
titleicon=new ImageIcon(getClass().getClassLoader().getResource("image.jpg"));
With a file location of
C:\project\game.class
C:\project\image.jpg
Class.getResource will never work, as this searches the classpath for the required resources.
The use of getResource assumes that the resources are embedded and are relative to the class path.
Without more details, it's difficult to make an accurate suggestion, but I would suggest that you get the images jared without your application code, this way, it will be easier to find.
If you're not using an IDE capable of Jaring your classes and resources, then you will need to have a look at Packaging Programs in JAR Files
Remember, Class#getResource is capable of doing a relative lookup. If the images are not stored in the same package as the class which is loading them, then you need to use an absolute path instead...
So I have 2 class folders one is res the other is lib. My res folder has two other sub folders one with images the other with sounds. My lib folder has 4 other jar files and a native folder. It all works within eclipse but when I try to export it as a runnable jar it does not work. I won't won't recognize anything.
I am to call my images I am using ImageIO.read(new File(imagePath)); For the sound I am using the external libraries I mentioned earlier to load and play them.
I am to call my images I am using ImageIO.read(new File(imagePath))
Contrary to your title, this is not an Eclipse problem - it's simply a bug in your code, because your code assumes that the image is stored as a file in the file system, when it's not.
You don't have a file for the image, so you shouldn't use new File. You should instead use Class.getResource or ClassLoader.getResource - or the getResourceAsStream equivalents. That way, it will load the resource from whatever context the class itself is loaded, which is appropriate for jar files. So for example, you might have:
Image image = ImageIO.read(MyClass.getResource("foo.png"));
... where foo.png is effectively in the same package structure as the class. Alternatively:
Image image = ImageIO.read(MyClass.getResource("/images/foo/bar.png"));
where images is a folder within the root directory of one of your jar files loaded by the same ClassLoader. (We don't have enough information to give you complete code here, but that should be enough to get you going.)
I am making an application that searches the screen for a specific image. I read the picture (file) I am scanning for and convert it to a buffered image, then to an int[] so I can process it faster. I also use the robot class to take a screenshot and convert to an int[].
While running code in Eclipse and having the files in the source folder, I don't have any problems. But after exporting my code to a runnable jar file, my scanning methods no longer work. I think it might have something to do with compression because my pictures need to be exactly how they were taken.
The only success I have had with a "finished format" is by exporting the jar normally, and using a folder in the same directory called images to hold the files. Using this code:
File img = new File(System.getProperty("user.dir") + File.separator + "images" + File.separator + "Close.bmp");
When running directly from eclipse I can simply do this:
File img = new File(src/Close.bmp);
Any suggestions? Maybe some tips/settings on exporting jars?
You have various options:
probably the easiest is to put the image in the classpath, i.e. deploy it with your class files, probably within a jar file. The drawback is that you can't replace the image (as long as you don't want your user to fiddle with the classpath)
place it relative to the user.dir as you have done, in this case you need to understand what the user.dir actually is: The working directory from which your application got started. It will differ depending on how you start it.
another option is to use a path relative to user.home which is your home directory.
I have a relatively basic java program which uses a system tray icon. The path I was using while writing the code is as follows "../images/logo.png". However, when I compile it into a jar file, the image does not show up in the system tray. Instead, if I change the path to "./images/logo.png", then the image shows up in the system tray when it's in the jar file form, but not while I'm testing.
It's not a major issue. However, I am curious to know why this inconsistency occurs.
When you package your program into a .jar file, your build is most likely copying the image into the same directory as the .jar file. However, when debugging in your ide, your image file lies one directory below.
Another possibility is that you are simply setting your Working Directly differently in the two scenarios.
Incidentally, you might be interested in embedding the image in your jar file, see:
https://stackoverflow.com/a/1096491/24954
This answer depends on two things. If the image file is embedded or not.
Embedded Resource
Once you have Jar'ed your application and the images are emebbed inside the application, normal file access methods will no longer work.
Trying to do something like...
new ImageIcon("../images/logo.png");
or
new File("../images/logo.png");
Won't work. This is because the resource is no longer a file within the context of the file system (it's actually a Zip entry in the Jar).
Instead, you need to use Class#getResource which will return a URL to the embedded resource.
new ImageIcon(getClass().getResource("../images/logo.png"));
Will work better. In general though, it is recommended to use an absolute path to the resources new ImageIcon(getClass().getResource("/images/logo.png")); as it's generally more difficult to break (IMHO)
External Resource
The path to the image is relative to the execution point of the application.
In development, you may have had to move up a directory (out of the src folder presumably) to find the image resource. This will mean that you will need to store you Jar file in a folder that would require it step up one level before it could find the image resource.
If you can, it's generally better to embedded the resource within the Jar where possible. It makes it easier to deploy as you reduce the number of files you need to package and makes it (a little) harder for the user to mess with it ;)