Search code examples
javaimageswingembedded-resource

Loading a jpeg image within a jar


I know that this question had been answered too many times but I couldn't fix it no matter solution I tried.
I want to use a jpeg image as background but I can't resolve it no matter I tried.

Below is my final package structure :

images/  
-- bg.jpeg  
org/     
-- Main.java  (used for test)

Code

public class Main {
BufferedImage img;
public static void main(String[] args) {
    Main main = new Main();
    main.load();
}
public void load(){
    try {
            ClassLoader cl = this.getClass().getClassLoader();
            System.out.println("CL:"+cl);
            InputStream url = getClass().getClassLoader().getResourceAsStream("/images/bg.jpg");
            System.out.println("URL:"+url);
            this.img = ImageIO.read(url); // Null argument exception
    } catch (IOException ex) {
        Logger.getLogger(BoardView.class.getName()).log(Level.SEVERE, null, ex);
    }
}}  

Output

CL:sun.misc.Launcher$AppClassLoader@15663a2   
URL:null   
Exception in thread "main" java.lang.IllegalArgumentException: input == null!   
    at javax.imageio.ImageIO.read(ImageIO.java:1348)   
    at org.Main.load(Main.java:32)   
    at org.Main.main(Main.java:24)

I am using JDK7 and Maven project.


Solution

  • You're image path is somewhat correct...

    But...

    When using getClassLoader(), you don't use the extra / in front of images.

    getClass().getClassLoader().getResourceAsStream("images/bg.jpg");
    

    enter image description here

    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class Main {
    
        BufferedImage img;
    
        public static void main(String[] args) {
            Main main = new Main();
            main.load();
        }
    
        public void load() {
            try {
                ClassLoader cl = this.getClass().getClassLoader();
                System.out.println("CL:" + cl);
                InputStream url = getClass().getClassLoader().getResourceAsStream("resources/stackoverflow5.png");
                System.out.println("URL:" + url);
                this.img = ImageIO.read(url); // Null argument exception
                JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img)), "No ClassLoader", JOptionPane.PLAIN_MESSAGE);
            } catch (IOException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    

    If you _don't use the getClassLoader(), then you do need it

    getClass().getResourceAsStream("/images/bg.jpg");
    

    enter image description here

    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class Main {
    
        BufferedImage img;
    
        public static void main(String[] args) {
            Main main = new Main();
            main.load();
        }
    
        public void load() {
            try {
                ClassLoader cl = this.getClass().getClassLoader();
                System.out.println("CL:" + cl);
                InputStream url = getClass().getClass().getResourceAsStream("/resources/stackoverflow5.png");
                System.out.println("URL:" + url);
                this.img = ImageIO.read(url); // Null argument exception
                JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img)), "With ClassLoader", JOptionPane.PLAIN_MESSAGE);
            } catch (IOException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    

    Why?...

    As simply as can possibly be state here

    • When you use .getClass().getResource(fileName) it considers the location of the fileName is the same location of the of the calling class.
    • When you use .getClass().getClassLoader().getResource(fileName) it considers the location of the fileName from the root

    Note: My file structure is similar to your

    ProjectRoot
             resources
                    stackoverflow5.png
             mypackage
                    Main.java