要将BufferedImage实例保存为BMP文件,就需要知道BMP文件的格式,可以参考我转载的文章:《BMP文件格式》。
下面是我的将BufferedImage实例保存为24位色BMP文件的实现。
首先是BMP文件相关的两个头结构:BMPFileHeader和BMPInfoHeader。
/**//*
* Created on 2005-6-21
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package org.lotus.image.codec.bmp;
/**//**
* <p> Title: BMP文件的头结构</p>
*
* <p> Description: BMP文件的头结构固定是14个字节,其定义如下:</p>
* <p>
* byte[2] bfType; 指定文件类型,必须是0x424D,即字符串“BM”,也就是说所有.bmp文件的头两个字节都是“BM“
* byte[4] bfSize; 指定文件大小,包括这14个字节
* byte[2] bfReserved1; 保留字
* byte[2] bfReserved2; 保留字
* byte[4] bfOffBits; 为从文件头到实际的位图数据的偏移字节数
* </p>
*
* <p> Copyright: Copyright (c) 2005</p>
*
* <p> Company: 21Lotus</p>
*
* @author George Hill
* @version 1.0
*/
class BMPFileHeader {
// Header data
private byte[] data = new byte[14];
public byte[] getData() {
return this.data;
}
// BMP file size
private int size;
public int getSize() {
return this.size;
}
private int offset;
public int getOffset() {
return this.offset;
}
BMPFileHeader(int size, int offset) {
this.size = size;
this.offset = offset;
data[0] = 'B';
data[1] = 'M';
int value = size;
data[2] = (byte) value;
value = value >>> 8;
data[3] = (byte) value;
value = value >>> 8;
data[4] = (byte) value;
value = value >>> 8;
data[5] = (byte) value;
value = offset;
data[10] = (byte) value;
value = value >>> 8;
data[11] = (byte) value;
value = value >>> 8;
data[12] = (byte) value;
value = value >>> 8;
data[13] = (byte) value;
}
}
/**//*
* Created on 2005-6-21
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package org.lotus.image.codec.bmp;
/**//**
* <p>Title: BMP文件内容的头结构</p>
*
* <p>Description: BMP文件内容的头结构固定是40个字节,其定义如下:</p>
* <p>
* byte[4] biSize; 指定这个结构的长度,为40
* byte[4] biWidth; 指定图象的宽度,单位是象素
* byte[4] biHeight; 指定图象的高度,单位是象素
* byte[2] biPlanes; 必须是1,不用考虑
* byte[2] biBitCount; 指定表示颜色时要用到的位数,常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图)
* byte[4] biCompression; 指定位图是否压缩
* byte[4] biSizeImage; 指定实际的位图数据占用的字节数
* byte[4] biXPelsPerMeter; 指定目标设备的水平分辨率,单位是每米的象素个数
* byte[4] biYPelsPerMeter; 指定目标设备的垂直分辨率,单位是每米的象素个数
* byte[4] biClrUsed; 指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为2biBitCount
* byte[4] biClrImportant; 指定本图象中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的
* </p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: 21Lotus</p>
*
* @author George Hill
* @version 1.0
*/
class BMPInfoHeader {
private byte[] data = new byte[40];
public byte[] getData() {
return this.data;
}
private int width;
public int getWidth() {
return this.width;
}
private int height;
public int getHeight() {
return this.height;
}
public int bitCount;
public int getBitCount() {
return this.bitCount;
}
public BMPInfoHeader(int width, int height, int bitCount) {
this.width = width;
this.height = height;
this.bitCount = bitCount;
data[0] = 40;
int value = width;
data[4] = (byte) value;
value = value >>> 8;
data[5] = (byte) value;
value = value >>> 8;
data[6] = (byte) value;
value = value >>> 8;
data[7] = (byte) value;
value = height;
data[8] = (byte) value;
value = value >>> 8;
data[9] = (byte) value;
value = value >>> 8;
data[10] = (byte) value;
value = value >>> 8;
data[11] = (byte) value;
data[12] = 1;
data[14] = (byte) bitCount;
value = width * height * 3;
if (width % 4 != 0)
value += (width % 4) * height;
data[20] = (byte) value;
value = value >>> 8;
data[21] = (byte) value;
value = value >>> 8;
data[22] = (byte) value;
value = value >>> 8;
data[23] = (byte) value;
}
}
仿照com.sun.image.codec.jpeg.JPEGImageEncoder写的接口类BMPEncoder。
/**//*
* Created on 2005-6-21
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package org.lotus.image.codec.bmp;
import java.awt.image.*;
import java.io.IOException;
/**//**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: 21Lotus</p>
*
* @author George Hill
* @version 1.0
*/
public interface BMPEncoder {
public void encode(BufferedImage bi) throws IOException;
public static final int BIT_COUNT_BLACKWHITE = 1;
public static final int BIT_COUNT_16COLORS = 4;
public static final int BIT_COUNT_256COLORS = 8;
public static final int BIT_COUNT_TRUECOLORS = 24;
}
BMPEncoder接口的实现BMPEncoderImpl。
/**//*
* Created on 2005-6-21
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package org.lotus.image.codec.bmp;
import java.awt.image.*;
import java.io.*;
/**//**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: 21Lotus</p>
*
* @author George Hill
* @version 1.0
*/
class BMPEncoderImpl implements BMPEncoder {
private OutputStream out;
public BMPEncoderImpl(OutputStream out) {
this.out = out;
}
public void encode(BufferedImage bi) throws IOException {
int width = bi.getWidth();
int height = bi.getHeight();
boolean needBlank = (width % 4 != 0);
int size = width * height * 3;
if (needBlank) {
size += (width % 4) * height;
}
BMPFileHeader fileHeader = new BMPFileHeader(size, 54);
BMPInfoHeader infoHeader = new BMPInfoHeader(width, height, BIT_COUNT_TRUECOLORS);
byte[] rgbs = new byte[3];
byte[] blank = new byte[width %