How can I display a bitmap image in a Java applet?
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.
beyerss
Updated on June 04, 2022Comments
-
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.