Referencing Pictures from resource folder in a Jar - java

I can't help it but think I've missed just the Thread to answer my question but I've been looking for a long time now and can't seem to find the help I need.
My problem is quite simple:
I've created a game (or rather I'm in the process of it) and I'm trying to add sprites (png files for the enemies and such) to it. Loading them in the IDE works just fine but when I create a jar file and try to open it, it simply says "A Java Exception has occurred". Further investigation revealed the problem is that it can't find the files I told it to load.
Through the threads I've read I gathered this much:
It's either that I'm not loading the images properly, meaning that I don't use the proper code for it, or
my MANIFEST.mf does not contain a "Class-Path" (meaning that the arguments are blank, which in fact they are)
Finding other code didn't work out for me. People suggested to use a ClassLoader which I could't manage to get working. Trying it out gave me nullpointer exceptions.
Trying to look into the latter didn't do much help, because I couldn't find any helping information, or I'm just not understanding anything.
package platformer.resources;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.*;
public class ImageLoader
{
static String spritePath = "src/platformer/resources/";
public static BufferedImage loadImage(String path)
{
BufferedImage img = null;
try{img= ImageIO.read(new File(spritePath+path));
}catch(IOException e){System.out.println("Couldn't load File: "+spritePath+path);}
return img;
}
public static BufferedImage flipImage(BufferedImage bufferedImage)
{
AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
tx.translate(-bufferedImage.getWidth(null), 0);
AffineTransformOp op = new AffineTransformOp(tx,
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null);
return bufferedImage;
}
}
This is the code I used so far.
Other classes would use "loadImage" or "flipImage" and in the IDE it works fine but as a .jar it fails to find the .png.
For example the class "platformer/entities/walker.class" would try to open the "Idle.png". In order to do that it uses the "loadImage("/entities/enemy/walker/Idle.png")" method. Note that in the method the actual path would end up being "src/platformer/resources/entities/enemy/walker/Idle.png".
Again, I'm terribly sorry if this has already been answered but I appreciate your help nonetheless.
Michael

When your files are inside a jar they can only be taken out as a resource stream so you will want to use something like:
ImageLoader.class.getResourceAsStream("nameoffile").
This is because a jar is actually a zipped up directory structure and files are not really files they are hidden amongst a compressed zip formatting as binary.

Related

Cannot inherit from final

I have a java image analysis program and am trying to get it to run on android. It starts like this (working on standard java):
import java.awt.image.BufferedImage;
public MaskImage(BufferedImage srcImage) {
super(srcImage.getWidth(), srcImage.getHeight(), srcImage.getType());
this.srcImage = srcImage;
this.height = srcImage.getHeight();
this.width = srcImage.getWidth();
}
When I try to get it working on android studio however I change bufferedimage to Bitmap, but still run into a couple of problems:
I cannot extend Bitmap in the same way I could BufferedImage
super(srcImage.getWidth(), srcImage.getHeight(), srcImage.getType());
this line runs into multiple issues, Says:
expected Parameters; actual: Arguments;
Thanks For any Help!
As you already know, Bitmap is final. By the very definition of final classes in Java, this means you cannot subclass it.
You will need to find an alternate strategy for accomplishing whatever you are trying to accomplish. Perhaps creating a class that wraps a Bitmap is one solution.

Loading image from source folder returned as null

Hello I have a problem with importing an image from my resources folder. I have looked all over google (or so I think) and I have no idea what I am doing wrong.
All help is appreciated thanks
Here is the picture of my java project:
Here is my Game Code:
public Game(){
handler = new Handler();
this.addKeyListener(new KeyInput(handler));
new Window(WIDTH, HEIGHT, "Testing", this);
BufferedImageLoader loader = new BufferedImageLoader();
level = loader.loadImage("/level.png");
hud = new HUD();
spawn = new Spawn(handler, hud);
r = new Random();
walls = new WallsMap(handler);
cam = new Camera(0, 0);
walls.render();
handler.addObject(new Player(WIDTH/2-32, HEIGHT/2-32, ID.Player, handler));
}
Finally here is my BufferedImageLoader class:
public class BufferedImageLoader {
private BufferedImage image;
public BufferedImage loadImage(String path){
try {
image = ImageIO.read(getClass().getClassLoader().getResourceAsStream(path));
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
}
To solve your particular problem, either of these two options should work so that the resource can be properly located:
Remove the call to getClassLoader() from your loadImage method so that the call is just getClass().getResourceAsStream(path) -OR-
Remove the slash from "/level.png" so that your call to loadImage looks like loader.loadImage("level.png")
However, in general, I agree with mastercork889, that it is better practice to organize your resources into packages as well.
EDIT:
In response to mastercork889's comment saying that my answer should be AND instead of OR, I thought I should elaborate on why it is indeed exclusive OR. I would have just commented, but I'm still too new to stack overflow to be allowed to comment, and this is quite a bit of information anyway :)
Removing the call to getClassLoader() works because then you're using the getResourceAsStream() method from the Class class, which does extra work before delegation to the getResourceAsStream() method from the ClassLoader class.
From the Java API:
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Since your resource isn't in a package, and is at the top level of a source folder (it looks like res is an "Eclipse Source Folder"), the level.png portion following the slash will adequately identify the location of the resource in an absolute way.
OR
Removing the slash from "/level.png" also works because then when the object's class loader (which should be the system class loader) looks for the resource, it will attempt to resolve your resource in an absolute way. The special handling of the slash at the beginning is behavior that is specific to the getResourceAsStream() method in Class, not ClassLoader.
The reason that AND won't work, is because if you call the getResourceAsStream() method from Class and remove the slash, then it will attempt to locate the resource in the same package that the associated class is located in. If you choose to go with the AND option, then you would need to move level.png into the com.plat.gfx package.
As a final point, I have built a small test program that followed the same format as your example, and once I followed one of the two suggestions, it worked for me.
The subtleties of resources, classes, and class loaders can be quite tricky. Good luck with your project!
Don't worry about putting images in a specific folder. Instead put them also in the src folder under a specific package: com.plat.res
I find that putting images in a specific package makes the package hierarchy look much more efficient, and less spaghetti-like.
Also a note on package conventions: domain-extension.domain.main-program.etc. My package hierarchy looks like this:
com.brennytizer.jumg
com.brennytizer.jumg.res
com.brennytizer.jumg.engine
com.brennytizer.jumg.level
com.brennytizer.jumg.level.maps
If you don't have a domain, write in what you think your domain would be (if you were to buy it in the future), or just use your (backwards) name:
My name is Jarod Brennfleck, writing program foobar, my package would be: brennfleck.jarod.foobar.
Once in there use the ImageIO class: ImageIO.read(Game.class.getResourceAsStream("/com/plat/res/leve.png"));

How to make a resource loader that will work with Slick2D

so i have made a 2D game using slick however the only resource loader that i have ever made is for plain java and it went like this :
import java.awt.Image;
import java.awt.Toolkit;
public class ResourceLoader {
static ResourceLoader rl = new ResourceLoader();
public static Image getImage(String fileName){
return Toolkit.getDefaultToolkit().getImage(rl.getClass().getResource("images/" + fileName));
}
}
Slick, of course, has a different image type (org.newdawn.slick.Image) for which this Resource Loader Class will not work and so i do not know how, for when i export my project , to load resources. I have searched online but haven't found many detailed results and so i ask is there any way to load resources so when i export the project as a run able jar file it will still load them.
thanks for any helpful answers in advance - josh
Not sure if you've seen it but here's one way of doing this. Explains deferred loading:
http://slick.cokeandcode.com/wiki/doku.php?id=resource_manager_tutorial
You might want to check out the other tutorials by Spiegel if you're starting out with Slick2D. I've found them very useful

google.zxing barcode generator in iReport

I want put a barcode in my page and can preview it. The barcode generator is google.zxing and my reporting tool is iReport.
But i dont know, how to configure Image Expression and Expression Class of an image in iReport.
The two key ideas are first to write a bit of Java code to create the relevant image and then to design the report to reference this code appropriately. Perhaps the simplest way to generate the image is in a scriptlet like this:
package com.jaspersoft.alliances.mdahlman;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
import net.sf.jasperreports.engine.JRScriptletException;
public class QRCodeScriptlet extends JRDefaultScriptlet {
public void afterDetailEval() throws JRScriptletException {
QRCodeWriter writer = new QRCodeWriter();
BitMatrix matrix = null;
try {
matrix = writer.encode(getFieldValue("barcode_text").toString(), BarcodeFormat.QR_CODE, 256, 256);
this.setVariableValue("BarCodeImage", MatrixToImageWriter.toBufferedImage(matrix) );
} catch (WriterException e) {
e.printStackTrace();
}
}
}
That's full of hard-coded ugliness, but the key ideas are all shown. Then you need to define the report like this:
Sample query: select 'some text' as barcode_text
I included this only to reinforce the point that my scriptlet hard-codes the field name barcode_text. (This is bad.)
Variable: BarCodeImage of type java.awt.image.BufferedImage with calculation System.
This name is hard-coded in the scriptlet too. (This is equally bad.)
Add to iReport's classpath:
The compiled scriptlet .jar file
core.jar (from ZXing)
javase.jar (from ZXing)
Add an Image element to the report with Expression $V{BarCodeImage}.
The result is a happy happy QR-code in your generated JasperReport:
I recall a sample that I have seen which does things much more cleanly. It actually included a nice plug-in so you could easily install this functionality into iReport with minimal effort. If I can track that down, then I'll update this post. But until then this at least covers all of the critical points.
The image expression should return any subclass of java.awt.Image. The easiest way to achieve this is to use your own helper class to generate the Image. You can create a static method that generates a barcode from a Stringand call that method from IReport.
In the case of ZXing I don't know the method to use, but I can tell what I use as ImageExpression using the Barbecue library.
net.sourceforge.barbecue.BarcodeImageHandler.getImage(
MyBarcodeGenerator.getFromString($F{field})
MyBarcodeGenerator class contains the method getFromString(...) that returns a net.sourceforge.barbecue.Barcode in my case a net.sourceforge.barbecue.linear.code39.Code39Barcode
The Expression Class is ignored.
--Edited:
To encode an Image in zxing you should use MatrixToImageWriter
The following code will encode a QRCode into a BufferedImage which you can use in the Image Expression field:
MatrixToImageWriter.toBufferedImage(new QRCodeWriter().encode("BARCODE CONTENT", BarcodeFormat.QR_CODE, 400 /*Width*/, 400/*Height*/));

JavaCV: cvLoadImage returns null no matter what I pass it

I'm on OS X 10.7.1. I've downloaded the latest JavaCV binaries, and built OpenCV from a current subversion checkout. The cvLoadImage() function returns null, no matter what I pass it. I have verified that I am passing it a valid path to a valid jpg image. Other JavaCV functions seem to return reasonable values, but since I can't load images, I can't really check.
I think I may have an error somewhere, but I'm not familiar with how JavaCV reports errors, so I can't check.
EDIT: I can verify that the overall JavaCV installation is valid and functioning, in that if I use Java's ImageIO to load an image, it works and I can subsequently operate on the loaded image, and save an image out (again, through ImageIO). SSCE follows:
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.image.BufferedImage;
import com.googlecode.javacv.cpp.*;
import com.googlecode.javacpp.Loader;
class ImgLoadTest {
public static void main(String[] args) {
//comment out EITHER the BufferedImage bit OR the cvLoadImage portion.
//works
BufferedImage img = ImageIO.read(new File(args[0]));
IplImage origImg = IplImage.createFrom(img);
//returns null
//IplImage origImg = cvLoadImage(args[0]);
System.out.println("origImg is" + origImg);
}
}
Since I can make it work via ImageIO, I'm not overly concerned about this bug anymore, but solving it may be of use to others working with JavaCV.
OpenCV only works well with ASCII filenames. If you have i18n characters in the path, it may very well choke. Also, at the moment, JavaCV maps all String objects to UTF-8, and it does not seem like Mac OS X uses UTF-8 by default.
So, if i18n is important to your application, keep on using ImageIO...

Categories