畢業設計中用到了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()
}
}