views:

2196

answers:

6

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.

+5  A: 

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.

JasonTrue
I think we have a winner. If he'd named his file "imagetest.bmp" it would have been obvious what the problem was.
Michael Myers
+1 this is probably the issue. The only reason you aren't getting a compiler error is because "\t" is a valid escape sequence for the tab character.
Eric Petroelje
Which gets us to the second lesson: Check if init (opening the file) was successful.
schnaader
I tried changing this and it still didn't work. Any other ideas?
Now that you've corrected this, does it work with an equivalent .jpg or .gif file? Is ImageIcon null after loading?
JasonTrue
-1, this is not an answer but a comment. Should go in the comments section. http://bit.ly/MohSi
OscarRyz
How is this not an answer? He's mentioning two potential problems (bad escape character and possible invalid image type) and how to fix them.
Beska
A: 

From the Java Docs:

When specifying a path, use the Internet-standard forward-slash ("/") as a separator

schnaader
+4  A: 

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")
kd304
+1  A: 

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.

Matt Poush
A: 

bmp files are not supprted in java.

You should probably consider unsing other formats such as .png, .gif or .jpg

If you really HAVE to do it, here's an article from Java World that explains how to read the bit map file and interpret it.

Java Tip 43: How to read 8- and 24-bit Microsoft Windows bitmaps in Java applications from JavaWorld

I've never tried though

OscarRyz
BMP is not supported in Swing/ImageIcon. ImageIO however is happy to read it (ref: http://forums.sun.com/thread.jspa?threadID=666189)
kd304
+1  A: 

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);
    }
}
Clint