How can I display a bitmap image in a Java applet?

14,254

Solution 1

Referencing your image through an absolute local file path might not work when you run your applet from a server. Use the ImageIcon (URL location) constructor and Have the URL point to the image resource on the server. Use the JApplet.getCodeBase() to determine where your applet originates and append the file name to it.

public class Form1 extends JApplet {
    Image i;

    public void init() {
        try {
            i = ImageIO.read(new URL(getCodeBase(), "test.bmp"));
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void paint(Graphics g) {
        g.drawImage(i, 0, 0, null);
    }
}

Edit: ImageIO supports BMP and the changed sample works for me.

Edit 2: If it still doesn't display the image, try "../test.bmp" because when you run an applet from lets say Eclipse it has the bin directory as the codebase.

Edit 3: If you put your test.bmp into the jar or on the classpath, you can load it using the same way but replacing

new URL(getCodeBase(), "test.bmp")

with

Form1.class.getResource("test.bmp")

Solution 2

To start with, it's probably a good idea to correctly escape your \ as \\.

Edited to add: You probably want to learn your language's (or library's) equivalent of Path.combine (or File.join) which is a method for taking a list of file path parts and combining them with the platform-appropriate path separator. Or you can write it yourself quickly in Java, as the path separator is documented in File.pathSeparator.

(Off the top of my head, I didn't know that forward slash always works in ImageIcon, but note the other response that indicates this).

Additionally, make sure you are loading a supported file type, such as .png, .gif or .jpg. BMP may be supported in JDK 1.5

Also, if you are running in an Applet context, you may not have access to the path in question due to sandboxing rules. In that case, make it available in the same path as to the HTML file hosting the applet (possibly in the Jar's path, if memory serves me), and use a relative path.

Solution 3

ImageJ is an Open Source application / library that has support for may formats including BMP.

Here is some real code using BMPDecoder from ImageJ:

Here is the license statement.

import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.MemoryImageSource;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class BMPDecoder {
    InputStream is;
    int curPos = 0;

    int bitmapOffset; // starting position of image data

    int width; // image width in pixels
    int height; // image height in pixels
    short bitsPerPixel; // 1, 4, 8, or 24 (no color map)
    int compression; // 0 (none), 1 (8-bit RLE), or 2 (4-bit RLE)
    int actualSizeOfBitmap;
    int scanLineSize;
    int actualColorsUsed;

    byte r[], g[], b[]; // color palette
    int noOfEntries;

    byte[] byteData; // Unpacked data
    int[] intData; // Unpacked data
    boolean topDown;

    private int readInt() throws IOException {
        int b1 = is.read();
        int b2 = is.read();
        int b3 = is.read();
        int b4 = is.read();
        curPos += 4;
        return ((b4 << 24) + (b3 << 16) + (b2 << 8) + (b1 << 0));
    }

    private short readShort() throws IOException {
        int b1 = is.read();
        int b2 = is.read();
        curPos += 2;
        return (short) ((b2 << 8) + b1);
    }

    void getFileHeader() throws IOException, Exception {
        // Actual contents (14 bytes):
        short fileType = 0x4d42;// always "BM"
        int fileSize; // size of file in bytes
        short reserved1 = 0; // always 0
        short reserved2 = 0; // always 0

        fileType = readShort();
        if (fileType != 0x4d42)
            throw new Exception("Not a BMP file"); // wrong file type
        fileSize = readInt();
        reserved1 = readShort();
        reserved2 = readShort();
        bitmapOffset = readInt();
    }

    void getBitmapHeader() throws IOException {

        // Actual contents (40 bytes):
        int size; // size of this header in bytes
        short planes; // no. of color planes: always 1
        int sizeOfBitmap; // size of bitmap in bytes (may be 0: if so,
                            // calculate)
        int horzResolution; // horizontal resolution, pixels/meter (may be 0)
        int vertResolution; // vertical resolution, pixels/meter (may be 0)
        int colorsUsed; // no. of colors in palette (if 0, calculate)
        int colorsImportant; // no. of important colors (appear first in
                                // palette) (0 means all are important)
        int noOfPixels;

        size = readInt();
        width = readInt();
        height = readInt();
        planes = readShort();
        bitsPerPixel = readShort();
        compression = readInt();
        sizeOfBitmap = readInt();
        horzResolution = readInt();
        vertResolution = readInt();
        colorsUsed = readInt();
        colorsImportant = readInt();

        topDown = (height < 0);
        if (topDown)
            height = -height;
        noOfPixels = width * height;

        // Scan line is padded with zeroes to be a multiple of four bytes
        scanLineSize = ((width * bitsPerPixel + 31) / 32) * 4;

        actualSizeOfBitmap = scanLineSize * height;

        if (colorsUsed != 0)
            actualColorsUsed = colorsUsed;
        else
        // a value of 0 means we determine this based on the bits per pixel
        if (bitsPerPixel < 16)
            actualColorsUsed = 1 << bitsPerPixel;
        else
            actualColorsUsed = 0; // no palette
    }

    void getPalette() throws IOException {
        noOfEntries = actualColorsUsed;
        // IJ.write("noOfEntries: " + noOfEntries);
        if (noOfEntries > 0) {
            r = new byte[noOfEntries];
            g = new byte[noOfEntries];
            b = new byte[noOfEntries];

            int reserved;
            for (int i = 0; i < noOfEntries; i++) {
                b[i] = (byte) is.read();
                g[i] = (byte) is.read();
                r[i] = (byte) is.read();
                reserved = is.read();
                curPos += 4;
            }
        }
    }

    void unpack(byte[] rawData, int rawOffset, int bpp, byte[] byteData,
            int byteOffset, int w) throws Exception {
        int j = byteOffset;
        int k = rawOffset;
        byte mask;
        int pixPerByte;

        switch (bpp) {
        case 1:
            mask = (byte) 0x01;
            pixPerByte = 8;
            break;
        case 4:
            mask = (byte) 0x0f;
            pixPerByte = 2;
            break;
        case 8:
            mask = (byte) 0xff;
            pixPerByte = 1;
            break;
        default:
            throw new Exception("Unsupported bits-per-pixel value: " + bpp);
        }

        for (int i = 0;;) {
            int shift = 8 - bpp;
            for (int ii = 0; ii < pixPerByte; ii++) {
                byte br = rawData[k];
                br >>= shift;
                byteData[j] = (byte) (br & mask);
                // System.out.println("Setting byteData[" + j + "]=" +
                // Test.byteToHex(byteData[j]));
                j++;
                i++;
                if (i == w)
                    return;
                shift -= bpp;
            }
            k++;
        }
    }

    void unpack24(byte[] rawData, int rawOffset, int[] intData, int intOffset,
            int w) {
        int j = intOffset;
        int k = rawOffset;
        int mask = 0xff;
        for (int i = 0; i < w; i++) {
            int b0 = (((int) (rawData[k++])) & mask);
            int b1 = (((int) (rawData[k++])) & mask) << 8;
            int b2 = (((int) (rawData[k++])) & mask) << 16;
            intData[j] = 0xff000000 | b0 | b1 | b2;
            j++;
        }
    }

    void unpack32(byte[] rawData, int rawOffset, int[] intData, int intOffset,
            int w) {
        int j = intOffset;
        int k = rawOffset;
        int mask = 0xff;
        for (int i = 0; i < w; i++) {
            int b0 = (((int) (rawData[k++])) & mask);
            int b1 = (((int) (rawData[k++])) & mask) << 8;
            int b2 = (((int) (rawData[k++])) & mask) << 16;
            int b3 = (((int) (rawData[k++])) & mask) << 24; // this gets
                                                            // ignored!
            intData[j] = 0xff000000 | b0 | b1 | b2;
            j++;
        }
    }

    void getPixelData() throws IOException, Exception {
        byte[] rawData; // the raw unpacked data

        // Skip to the start of the bitmap data (if we are not already there)
        long skip = bitmapOffset - curPos;
        if (skip > 0) {
            is.skip(skip);
            curPos += skip;
        }

        int len = scanLineSize;
        if (bitsPerPixel > 8)
            intData = new int[width * height];
        else
            byteData = new byte[width * height];
        rawData = new byte[actualSizeOfBitmap];
        int rawOffset = 0;
        int offset = (height - 1) * width;
        for (int i = height - 1; i >= 0; i--) {
            int n = is.read(rawData, rawOffset, len);
            if (n < len)
                throw new Exception("Scan line ended prematurely after " + n
                        + " bytes");
            if (bitsPerPixel == 24)
                unpack24(rawData, rawOffset, intData, offset, width);
            else if (bitsPerPixel == 32)
                unpack32(rawData, rawOffset, intData, offset, width);
            else
                // 8-bits or less
                unpack(rawData, rawOffset, bitsPerPixel, byteData, offset,
                        width);
            rawOffset += len;
            offset -= width;
        }
    }

    public void read(InputStream is) throws IOException, Exception {
        this.is = is;
        getFileHeader();
        getBitmapHeader();
        if (compression != 0)
            throw new Exception("Compression not supported");
        getPalette();
        getPixelData();
    }

    public MemoryImageSource makeImageSource() {
        ColorModel cm;
        MemoryImageSource mis;

        if (noOfEntries > 0) {
            // There is a color palette; create an IndexColorModel
            cm = new IndexColorModel(bitsPerPixel, noOfEntries, r, g, b);
        } else {
            // There is no palette; use the default RGB color model
            cm = ColorModel.getRGBdefault();
        }

        // Create MemoryImageSource

        if (bitsPerPixel > 8) {
            // use one int per pixel
            mis = new MemoryImageSource(width, height, cm, intData, 0, width);
        } else {
            // use one byte per pixel
            mis = new MemoryImageSource(width, height, cm, byteData, 0, width);
        }

        return mis; // this can be used by Component.createImage()
    }

    public static void main(String[] aqgs) {
        BMPDecoder bd = new BMPDecoder();
        try {
            bd.read(BMPDecoder.class.getResourceAsStream("bmp.bmp"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        JFrame jf = new JFrame();
        JLabel jl = new JLabel();
        ImageIcon ii = new ImageIcon( jl.createImage(bd.makeImageSource()));
        jl.setIcon(ii);
        jf.add(jl);
        jf.pack();
        jf.setVisible(true);
    }
}

Solution 4

Instead of making an ImageIcon that is told to draw itself onto a graphics, try it this way:

public class Form1 extends JApplet {
    Image i;

    public void init(){
        i = getImage("D:\\test.bmp");
    }

    public void paint(Graphics g){
        g.drawImage(i,0,0,this);
    }
}

Also, you may want to try using .png instead of a .bmp file.

Share:
14,254
beyerss
Author by

beyerss

Updated on June 04, 2022

Comments

  • beyerss
    beyerss almost 2 years

    I am having a hard time figuring out how to show an Image (or ImageIcon) in a Java applet. The following is my code. The picture (test.bmp) does exist and is on the D drive but when I run this I get the applet window with nothing in it. Can somebody tell me what I am missing to make the ImageIcon show?

    public class Form1 extends JApplet {
        ImageIcon i;
    
        public void init(){
            i = new ImageIcon("D:\test.bmp");
        }
    
        public void paint(Graphics g){
            i.paintIcon(this, g, 0, 0);
        }
    }
    

    Thanks, Steve.