www.pudn.com > img_process_java.zip > BMP_display.java.backup
import java.awt.*;
import java.awt.image.*;
import java.io.*;
//This class display a image of Windows BMP format
public class BMP_display
{
public static void main(String args[])throws IOException
{
MainFrame mainFrame = new MainFrame("Image Viewer", 1000, 650);
}
}
//Main frame to put image in
class MainFrame extends Frame
{
int width, height;
Image image;
ImageCanvas imageCanvas;
FileInputStream in;
Insets inset;
public MainFrame(String name, int width, int height)
{
super(name);
setLayout(new BorderLayout());
MenuBar mainmenu = new MenuBar();
Menu fileMenu = new Menu("File", false);
mainmenu.add(fileMenu);
fileMenu.add("Open");
fileMenu.addSeparator();
fileMenu.add("Quit");
setMenuBar(mainmenu);
setSize(width, height);
setVisible(true);
}
public boolean action(Event event, Object obj)
{
if ( event.target instanceof MenuItem )
{
if ( obj.equals("Quit") ) System.exit(0);
if ( obj.equals("Open") )
{
FileDialog fd = new FileDialog(this, "Open Image file", FileDialog.LOAD);
fd.setDirectory(".");
fd.setVisible(true);
String filename;
filename = fd.getDirectory() + fd.getFile();
if ( filename != null )
{
/*ImageFrame image = new ImageFrame(filename);
image.show();*/
display(filename);
}
}
}
return super.action(event, obj);
}
public void display(String filename)
{
BMPReader reader = new BMPReader();
try
{
in = new FileInputStream(filename);
}
catch (IOException e)
{
System.err.println("File:" + filename + "cannot be opened\n" + e.toString() );
System.exit(1);
}
try
{
image = createImage(reader.getBMPImage(in));
}
catch (IOException e)
{
System.err.println("Cannot create image\n" + e.toString() );
System.exit(1);
}
//adjust the image viewer frame to image size
width = image.getWidth(this);
height = image.getHeight(this);
imageCanvas = new ImageCanvas(image);
add("Center", imageCanvas);
//frame size adjustment taking into account the frame border size
inset = this.getInsets();
this.setSize(width + inset.left + inset.right, height + inset.top + inset.bottom);
this.setVisible(true);
}
}
//An alternative to show image in a separate image frame instead of the main frame
/*class ImageFrame extends Frame
{
int width, height;
Image image;
ImageCanvas imageCanvas;
FileInputStream in;
public ImageFrame(String filename)
{
super(filename);
setLayout(new BorderLayout());
//image = Toolkit.getDefaultToolkit().getImage(filename);
BMPReader reader = new BMPReader();
try
{
in = new FileInputStream(filename);
}
catch (IOException e)
{
System.err.println("File:" + filename + "cannot be opened\n" + e.toString() );
System.exit(1);
}
try
{
image = createImage(reader.getBMPImage(in));
}
catch (IOException e)
{
System.err.println("Cannot create image\n" + e.toString() );
System.exit(1);
}
imageCanvas = new ImageCanvas(image);
//width = image.getWidth(this);
//height = image.getHeight(this);
width = 100;
height = 100;
add("North", new Button("Close"));
add("Center", imageCanvas);
resize(width, height);
}
public boolean action(Event event, Object obj)
{
if ( obj.equals("Close") ) dispose();
return super.action(event, obj);
}
}*/
//Cavas for drawing image
class ImageCanvas extends Canvas
{
Image image;
public ImageCanvas(Image img)
{
image = img;
}
public void paint(Graphics g)
{
g.drawImage(image, 0, 0, this);
}
}
// This class provides a public static method that takes an InputStream
// to a Windows .BMP file and converts it into an ImageProducer via
// a MemoryImageSource.
// You can fetch a .BMP through a URL with the following code:
// URL url = new URL( )
// Image img = createImage(BMPReader.getBMPImage(url.openStream()));
class BMPReader extends Object
{
// Constants indicating how the data is stored
public static final int BI_RGB = 0;
public static final int BI_RLE8 = 1;
public static final int BI_RLE4 = 2;
public ImageProducer getBMPImage(InputStream stream)
throws IOException
{
// The DataInputStream allows you to read in 16 and 32 bit numbers
DataInputStream in = new DataInputStream(stream);
// Verify that the header starts with 'BM'
if (in.read() != 'B') {
throw new IOException("Not a .BMP file");
}
if (in.read() != 'M') {
throw new IOException("Not a .BMP file");
}
// Get the total file size
int fileSize = intelInt(in.readInt());
// Skip the 2 16-bit reserved words
in.readUnsignedShort();
in.readUnsignedShort();
int bitmapOffset = intelInt(in.readInt());
int bitmapInfoSize = intelInt(in.readInt());
int width = intelInt(in.readInt());
int height = intelInt(in.readInt());
// Skip the 16-bit bitplane size
in.readUnsignedShort();
int bitCount = intelShort(in.readUnsignedShort());
int compressionType = intelInt(in.readInt());
int imageSize = intelInt(in.readInt());
// Skip pixels per meter
in.readInt();
in.readInt();
int colorsUsed = intelInt(in.readInt());
int colorsImportant = intelInt(in.readInt());
if (colorsUsed != 0) colorsUsed = 1 << bitCount;
int colorTable[] = new int[colorsUsed];
// Read the bitmap's color table
for (int i=0; i < colorsUsed; i++)
{
colorTable[i] = (intelInt(in.readInt()) & 0xffffff) + 0xff000000;
}
// Create space for the pixels
int pixels[] = new int[width * height];
// Read the pixels from the stream based on the compression type
if (compressionType == BI_RGB)
{
if (bitCount == 24)
{
readRGB24(imageSize, width, height, pixels, in);
}
else
{
readRGB(width, height, colorTable, bitCount,
pixels, in);
}
}
else if (compressionType == BI_RLE8)
{
readRLE(width, height, colorTable, bitCount,
pixels, in, imageSize, 8);
}
else if (compressionType == BI_RLE4)
{
readRLE(width, height, colorTable, bitCount,
pixels, in, imageSize, 4);
}
// Create a memory image source from the pixels
return new MemoryImageSource(width, height, pixels, 0,
width);
}
// Reads in pixels in 24-bit format. There is no color table, and the
// pixels are stored in 3-byte pairs. Oddly, all windows bitmaps are
// stored upside-down - the bottom line is stored first.
protected void readRGB24(int imageSize, int width, int height, int pixels[],
DataInputStream in)
throws IOException
{
int pad;
// No Palatte data for 24-bit format but scan lines are
// padded out to even 4-byte boundaries.
pad = (imageSize / height) - 3 * width;
// Start storing at the bottom of the array
for (int h = height-1; h >= 0; h--)
{
int pos = h * width;
for (int w = 0; w < width; w++)
{
// Read in the red, green, and blue components
int blue = in.read();
int green = in.read();
int red = in.read();
// Turn the red, green, and blue values into an RGB color with
// an alpha value of 255 (fully opaque)
pixels[pos++] = 0xff000000 + (red << 16) + (green << 8) + blue;
//pos++;
}
in.skipBytes(pad);
}
}
// readRGB reads in pixels values that are stored uncompressed.
// The bits represent indices into the color table.
protected static void readRGB(int width, int height, int colorTable[],
int bitCount, int pixels[], DataInputStream in)
throws IOException
{
// How many pixels can be stored in a byte?
int pixelsPerByte = 8 / bitCount;
// A bit mask containing the number of bits in a pixel
int bitMask = (1 << bitCount) - 1;
// The shift values that will move each pixel to the far right
int bitShifts[] = new int[pixelsPerByte];
for (int i=0; i < pixelsPerByte; i++)
{
bitShifts[i] = 8 - ((i+1) * bitCount);
}
int whichBit = 0;
// Read in the first byte
int currByte = in.read();
// Start at the bottom of the pixel array and work up
for (int h=height-1; h >= 0; h--)
{
int pos = h * width;
for (int w=0; w < width; w++)
{
// Get the next pixel from the current byte
pixels[pos] = colorTable[(currByte >> bitShifts[whichBit])& bitMask];
pos++;
whichBit++;
// If the current bit position is past the number of pixels in
// a byte, we advance to the next byte
if (whichBit >= pixelsPerByte)
{
whichBit = 0;
currByte = in.read();
}
}
}
}
// readRLE reads run-length encoded data in either RLE4 or RLE8 format.
protected static void readRLE(int width, int height, int colorTable[],
int bitCount, int pixels[], DataInputStream in,
int imageSize, int pixelSize)
throws IOException
{
int x = 0;
int y = height-1;
// You already know how many bytes are in the image, so only go
// through that many.
for (int i=0; i < imageSize; i++)
{
// RLE encoding is defined by two bytes
int byte1 = in.read();
int byte2 = in.read();
i += 2;
// If byte 0 == 0, this is an escape code
if (byte1 == 0)
{
// If escaped, byte 2 == 0 means you are at end of line
if (byte2 == 0)
{
x = 0;
y--;
}
// If escaped, byte 2 == 1 means end of bitmap
else if (byte2 == 1)
{
return;
}
// if escaped, byte 2 == 2 adjusts the current x and y by
// an offset stored in the next two words
else if (byte2 == 2)
{
int xoff = (char) intelShort(
in.readUnsignedShort());
i+= 2;
int yoff = (char) intelShort(
in.readUnsignedShort());
i+= 2;
x += xoff;
y -= yoff;
}
// If escaped, any other value for byte 2 is the number of bytes
// that you should read as pixel values (these pixels are not
// run-length encoded)
else
{
int whichBit = 0;
// Read in the next byte
int currByte = in.read();
i++;
for (int j=0; j < byte2; j++)
{
if (pixelSize == 4)
{
// The pixels are 4-bits, so half the time you shift the current byte
// to the right as the pixel value
if (whichBit == 0)
{
pixels[y*width+x] = colorTable[(currByte >> 4)
& 0xf];
}
else
{
// The rest of the time, you mask out the upper 4 bits, save the pixel
// value, then read in the next byte
pixels[y*width+x] = colorTable[currByte & 0xf];
currByte = in.read();
i++;
}
}
else
{
pixels[y*width+x] = colorTable[currByte];
currByte = in.read();
i++;
}
x++;
if (x >= width)
{
x = 0;
y--;
}
}
// The pixels must be word-aligned, so if you read an uneven number of
// bytes, read and ignore a byte to get aligned again.
if ((byte2 & 1) == 1)
{
in.read();
i++;
}
}
// If the first byte was not 0, it is the number of pixels that
// are encoded by byte 2
}
else
{
for (int j=0; j < byte1; j++) {
if (pixelSize == 4) {
// If j is odd, use the upper 4 bits
if ((j & 1) == 0) {
pixels[y*width+x] = colorTable[(byte2 >> 4) & 0xf];
} else {
pixels[y*width+x+1] = colorTable[byte2 & 0xf];
}
} else {
pixels[y*width+x+1] = colorTable[byte2];
}
x++;
if (x >= width) {
x = 0;
y--;
}
}
}
}
}
// intelShort converts a 16-bit number stored in intel byte order into
// the local host format
protected static int intelShort(int i)
{
return ((i >> 8) & 0xff) + ((i << 8) & 0xff00);
}
// intelInt converts a 32-bit number stored in intel byte order into
// the local host format
protected static int intelInt(int i)
{
return ((i & 0xff) << 24) + ((i & 0xff00) << 8) +
((i & 0xff0000) >> 8) + ((i >> 24) & 0xff);
}
}