關於BMP圖像的處理

  畢業設計中用到了BMP位圖的處理,因爲有現成的BMP圖片,處理下就可以使用了,可是處理過程中碰到了點問題。

把整個圖片讀入之後,除掉FileHeader和InfoHeader,剩餘的用整型數組存放。然後使用MemoryImageSource類的創建圖片方法創建圖片。因爲圖片是三張連着的,需要均勻切成三張使用,所以從一張圖片裏創建了三張,但是對於有的圖片好使,有的就不行,圖片中間老是有空白的均勻分佈的豎條,我就不知道是爲什麼了。請問有誰對這個有研究嗎?

獲取BMP圖片的方法:

	public static Image[] getBMPImages(String name, int count) {
		Image[] images = new Image[count];
		BMPLoader loader = new BMPLoader();
		int width = 0;
		int height= 0;
		int[] value = null;
		try {
			loader.read(new FileInputStream(new File("skin/" + name + ".bmp")));
		} 
                               catch (Exception e) {
			
		}
		width = loader.getWidthPixels();
		height= loader.getHeightPixels();
		value = loader.getIntData();
		
		for(int i = 0; i<count; i++) {
			MemoryImageSource source = new MemoryImageSource(width/count, height, value, i * width/count, width);
			images[i] = Toolkit.getDefaultToolkit().createImage(source);
		}	
		return images;

 BMPLoader.java:

package util;

/**
 * This class implements a BMP Loader.
 *
 *-----------------------------------------------------------------------
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *----------------------------------------------------------------------
 */

import java.awt.*;
import java.awt.image.*;
import java.io.*;

/**
 * BMP文件的解碼器
 */
public class BMPLoader
{
	private InputStream is;
	private int curPos = 0;

	private int bitmapOffset;		// 實際圖像數據的開始位置

	private int width;				// 圖像的寬像素
	private int height;				// 圖像的高像素
	private short bitsPerPixel;		// 1, 4, 8, or 24 (no color map)
	private int compression;		// 0 (none), 1 (8-bit RLE), or 2 (4-bit RLE)
	private int actualSizeOfBitmap; //位圖的實際尺寸
	private int scanLineSize;		
	private int actualColorsUsed;

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

	private byte[] byteData;		// Unpacked data
	private int[] intData;			// Unpacked data

	public BMPLoader()
	{
	}
	
	public int getWidthPixels() {//獲取圖像的寬度
		return width;
	}
	public int getHeightPixels() {//獲取圖像的高度
		return height;
	}
	public int[] getIntData() {//獲取圖像所有像素值,存入整型數組
		return intData;
	}
	public byte[] getByteData() {
		return byteData;
	}

    public Image getBMPImage(InputStream stream) throws Exception
    {
		read(stream);
		return Toolkit.getDefaultToolkit().createImage(getImageSource());
	}

	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 += 4;
		return (short)((b2 << 8) + b1);
	}


	void getFileHeader()  throws IOException, Exception {
		// 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 {

		// 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)
		boolean topDown;
		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);
		noOfPixels = width * height;

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

		if (sizeOfBitmap != 0)
			actualSizeOfBitmap = sizeOfBitmap;
		else
			// a value of 0 doesn't mean zero - it means we have to calculate it
			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[] 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 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");
		}

		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 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 > 8) {
				// Unpack and create one int per pixel
				unpack(rawData, rawOffset, intData, offset, width);
			}
			else {
				// Unpack and create one byte per pixel
				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(" BMP Compression not supported");
		getPalette();
		getPixelData();
	}


	public MemoryImageSource getImageSource() {
		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()
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章