Mridang Agarwalla
Mridang Agarwalla

Reputation: 45108

Unable to load image from Jar

I'm trying to load an image from a Jar File. Here's the line:

Image imgTrayIcon = new Image(display, this.getClass().getResourceAsStream("icon.ico"));

I've seen many examples using this method but when I try to do so, I get and error saying that my image is invalid. Here's the stack trace:

 [java] Exception in thread "Thread-0" org.eclipse.swt.SWTException: Invalid image
 [java]     at org.eclipse.swt.SWT.error(SWT.java:4083)
 [java]     at org.eclipse.swt.SWT.error(SWT.java:3998)
 [java]     at org.eclipse.swt.SWT.error(SWT.java:3969)
 [java]     at org.eclipse.swt.internal.image.WinICOFileFormat.loadInfoHeader(WinICOFileFormat.java:200)
 [java]     at org.eclipse.swt.internal.image.WinICOFileFormat.loadIcon(WinICOFileFormat.java:127)
 [java]     at org.eclipse.swt.internal.image.WinICOFileFormat.loadFromByteStream(WinICOFileFormat.java:119)
 [java]     at org.eclipse.swt.internal.image.FileFormat.loadFromStream(FileFormat.java:48)
 [java]     at org.eclipse.swt.internal.image.FileFormat.load(FileFormat.java:84)
 [java]     at org.eclipse.swt.graphics.ImageLoader.load(ImageLoader.java:130)
 [java]     at org.eclipse.swt.graphics.ImageDataLoader.load(ImageDataLoader.java:22)
 [java]     at org.eclipse.swt.graphics.ImageData.<init>(ImageData.java:331)
 [java]     at org.eclipse.swt.graphics.Image.<init>(Image.java:545)
 [java]     at SysTray.run(Unknown Source)

The icon I'm using is definitely valid. I've checked this using icon tools. I've also tried placing the icon in the same directory as my code (not Jar-ing it) and using it like this:

Image imgTrayIcon = new Image(display, "icon.ico");

This works just fine, but when I try to put it in the Jar, it doesn't. I can't seem to figure out why this is happening. I've uncompressed my Jar to check whether the file was added to the Jar and it seems to be there. My jar doesn't has any complex folder structure. All the files and resources are in the same level of tree.

Any ideas on what's wrong here? Thanks


Here's some sample code to replicate the issue:

Example.java

import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;

class Example {

    public static void main(String[] args) {
        Display display = Display.getDefault();
        Image imgTrayIcon = new Image(display, Example.class.getClassLoader().getResourceAsStream("icon.ico"));
    }

}

Commands:

javac -cp "SWT.jar" Example.java
jar cf Example.jar *.class *.ico
java -cp "Example.jar;SWT.jar" Example

Upvotes: 3

Views: 5771

Answers (4)

Matthew Cline
Matthew Cline

Reputation: 2376

  1. Have you tried putting the file in the same directory as the class file, without Jaring it, and using getResourceAsStream() to load it?
  2. Have you tried getting a checksum of the stream using java.security.DigestInputStream while inside and outside of the Jar, to see if the file actually differs in any way between the two environments?

Upvotes: 0

Favonius
Favonius

Reputation: 13984

Seems like you are working on multi-threaded application. From the stack-trace Exception in thread "Thread-0" org.eclipse.swt.SWTException: Invalid image it appears that you are loading the image in a non-ui thread and trying to use that in some UI element. See this.

Within a UI thread the below code works fine. (The icon file is inside the test package)

package test;

import java.io.InputStream;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class IconTest 
{
    public static void main(String[] args)
    {
        final Display display = new Display();

        Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
        shell.setSize(200, 200);
        shell.setLocation(20, 20);

        InputStream stream = IconTest.class.getResourceAsStream("/test/icon.ico"); 

        Image imgTrayIcon = new Image(display, stream);

        shell.setImage(imgTrayIcon);

        shell.open();
        while (!shell.isDisposed()) {
                if (!display.readAndDispatch())
                        display.sleep();
        }

        if(imgTrayIcon != null)
            imgTrayIcon.dispose();

        display.dispose();
    }
}

Upvotes: 3

kjp
kjp

Reputation: 3116

Try these - this.getClass().getClassLoader().getResourceAsStream("icon.ico") OR this.getClass().getClassLoader().getResourceAsStream("package_or_full_path_to_image/icon.ico" ) OR Name_of_THIS_CLASS.class.getClassLoader().getResourceAsStream("icon.ico")

Upvotes: 0

Hemant Metalia
Hemant Metalia

Reputation: 30688

ImageIcon image = (new ImageIcon(getClass().getResource("yourpackage/mypackage/image.gif")));

In general, you can retrieve an InputStream in the following way:

InputStream is = this.getClass().getClassLoader()    .getResourceAsStream("yourpackage/mypackage/myfile.xml");

It will run inside or outside the jar.

refer http://www.jugpadova.it/articles/2006/02/05/accessing-a-resource-within-a-jar

also refer http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html

Upvotes: 0

Related Questions