www.pudn.com > img_process_java.zip > BMP_display.java


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); 
    } 
}//End of Class BMP_display 
 
//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); 
	} 
 
}//End of Class MainFrame 
 
//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); 
	} 
}//End of Class ImageCanvas 
 
 
// 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); 
    } 
}//End of BMPReader