如果您在 Microsoft Windows 环境中工作那么创建位图文件的功能将为您提供许多方便例如在我的上一个项目中我必须将 Java 与 Microsoft Access 对接Java 程序允许用户在屏幕上绘图这幅图随后被打印到 Microsoft Access 报表中由于 Java 不支持 OLE我的唯一选择就是创建该图的一个位图文件并通知 Microsoft Access 报表在何处能找到这个位图文件如果您写过向剪贴板发送图像的应用程序则这个技巧可能对您有用 尤其是当您将这个信息传递给另一个应用程序时
位图文件的格式
位图文件格式支持 位 RLE(行程长度编码)以及 位和 位编码因为我们只处理 位格式所以下面我们查看一下该文件的结构
位图文件分为三个部分我已将它们列在下面
第 部分位图文件的标头
标头包含位图文件的类型大小信息和版面信息结构如下(摘自 C 语言结构定义)
typedef struct tagBITMAPFILEHEADER {
牋燯INT bfType;
牋燚WORD bfSize;
牋燯INT bfReserved;
牋燯INT bfReserved;
牋燚WORD bfOffBits;
}BITMAPFILEHEADER;
下面是对这个清单中的代码元素的说明
bfType指定文件类型其值始终为 BM
bfSize指定整个文件的大小(以字节为单位)
bfReserved保留 必须为
bfReserved保留 必须为
bfOffBits指定从 BitmapFileHeader 到图像首部的字节偏移量
现在您已经明白位图标头的用途就是标识位图文件读取位图文件的每个程序都使用位图标头来进行文件验证
第 部分位图信息标头
随后的标头称为信息标头其中包含图像本身的属性
下面说明如何指定 Windows (或更高版本)设备独立位图 (DIB) 的大小和颜色格式:
typedef struct tagBITMAPINFOHEADER {
牋牋DWORD biSize;
牋牋LONG biWidth;
牋牋LONG biHeight;
牋牋WORD biPlanes;
牋牋WORD biBitCount;
牋牋DWORD biCompression;
牋牋DWORD biSizeImage;
牋牋LONG biXPelsPerMeter;
牋牋LONG biYPelsPerMeter;
牋牋DWORD biClrUsed;
牋牋DWORD biClrImportant;
} BITMAPINFOHEADER;
以上代码清单的每个元素说明如下
biSize指定 BITMAPINFOHEADER 结构所需的字节数
biWidth指定位图的宽度(以象素为单位)
biHeight指定位图的高度(以象素为单位)
biPlanes指定目标设备的位面数这个成员变量的值必须为
biBitCount指定每个象素的位数 其值必须为 或
biCompression指定压缩位图的压缩类型在 位格式中该变量被设置为
biSizeImage指定图像的大小(以字节为单位)如果位图的格式是 BI_RGB则将此成员变量设置为 是有效的
biXPelsPerMeter为位图指定目标设备的水平分辨率(以象素/米为单位)应用程序可用该值从最符合当前设备特征的资源群组中选择一个位图
biYPelsPerMeter为位图指定目标设备的垂直分辨率(以象素/米为单位)
biClrUsed指定位图实际所用的颜色表中的颜色索引数如果 biBitCount 设为 则 biClrUsed 指定用来优化 Windows 调色板性能的参考颜色表
biClrImportant指定对位图的显示有重要影响的颜色索引数如果此值为 则所有颜色都很重要
现在已定义了创建图像所需的全部信息
第 部分图像
在 位格式中图像中的每个象素都由存储为 BRG 的三字节 RGB 序列表示每个扫描行都被补足到 位为了使这个过程稍复杂一点图像是自底而上存储的即第一个扫描行是图像中的最后一个扫描行下图显示了标头 (BITMAPHEADER) 和 (BITMAPINFOHEADER) 以及部分图像各个部分由垂线分隔
D B |
E
B EC EC
| FFFF FFFF FFFF FFFF FFFF
FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
*
现在我们开始检视代码
现在我们已经知道了 位位图文件的结构下面就是您期待已久的内容用来将图像对象写入位图文件的代码
import javaawt*;
import javaio*;
import javaawtimage*;
public class BMPFile extends Component {
牋// 私有常量
牋private final static int BITMAPFILEHEADER_SIZE = ;
牋private final static int BITMAPINFOHEADER_SIZE = ;
牋// 私有变量声明
牋// 位图文件标头
牋private byte bitmapFileHeader [] = new byte [];
牋private byte bfType [] = {B M};
牋private int bfSize = ;
牋private int bfReserved = ;
牋private int bfReserved = ;
牋private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;
牋// 位图信息标头
牋private byte bitmapInfoHeader [] = new byte [];
牋private int biSize = BITMAPINFOHEADER_SIZE;
牋private int biWidth = ;
牋private int biHeight = ;
牋private int biPlanes = ;
牋private int biBitCount = ;
牋private int biCompression = ;
牋private int biSizeImage = x;
牋private int biXPelsPerMeter = x;
牋private int biYPelsPerMeter = x;
牋private int biClrUsed = ;
牋private int biClrImportant = ;
牋// 位图原始数据
牋private int bitmap [];
牋// 文件部分
牋private FileOutputStream fo;
牋// 缺省构造函数
牋public BMPFile() {
牋}
牋public void saveBitmap (String parFilename Image parImage int
parWidth int parHeight) {
牋牋炉ry {
牋牋牋牋fo = new FileOutputStream (parFilename);
牋牋牋牋save (parImage parWidth parHeight);
牋牋牋牋foclose ();
牋牋爙
牋牋焘atch (Exception saveEx) {
牋牋牋牋saveExprintStackTrace ();
牋牋爙
牋}
牋/*
牋? saveMethod 是该进程的主方法该方法
牋? 将调用 convertImage 方法以将内存图像转换为
牋? 字节数组writeBitmapFileHeader 方法创建并写入
牋? 位图文件标头writeBitmapInfoHeader 创建
牋? 信息标头writeBitmap 写入图像
牋?
牋?/
牋private void save (Image parImage int parWidth int parHeight) {
牋牋炉ry {
牋牋牋牋convertImage (parImage parWidth parHeight);
牋牋牋牋writeBitmapFileHeader ();
牋牋牋牋writeBitmapInfoHeader ();
牋牋牋牋writeBitmap ();
牋牋爙
牋牋焘atch (Exception saveEx) {
牋牋牋牋saveExprintStackTrace ();
牋牋爙
牋}
牋/*
牋? convertImage 将内存图像转换为位图格式 (BRG)
牋? 它还计算位图信息标头所用的某些信息
牋?
牋?/
牋private boolean convertImage (Image parImage int parWidth int parHeight) {
牋牋爄nt pad;
牋牋燽itmap = new int [parWidth * parHeight];
牋牋燩ixelGrabber pg = new PixelGrabber (parImage parWidth parHeight
牋牋牋牋牋牋牋牋牋牋牋牋牋牋牋牋牋牋牋牋燽itmap parWidth);
牋牋炉ry {
牋牋牋牋pggrabPixels ();
牋牋爙
牋牋焘atch (InterruptedException e) {
牋牋牋牋eprintStackTrace ();
牋牋牋牋return (false);
牋牋爙
牋牋爌ad = ( ((parWidth * ) % )) * parHeight;
牋牋燽iSizeImage = ((parWidth * parHeight) * ) + pad;
牋牋燽fSize = biSizeImage + BITMAPFILEHEADER_SIZE +
BITMAPINFOHEADER_SIZE;
牋牋燽iWidth = parWidth;
牋牋燽iHeight = parHeight;
牋牋爎eturn (true);
牋}
牋/*
牋? writeBitmap 将象素捕获器返回的图像转换为
牋? 所需的格式请记住扫描行在位图文件中是
牋? 反向存储的!
牋?
牋? 每个扫描行必须补足为 个字节
牋?/
牋private void writeBitmap () {
牋牋牋int size;
牋牋牋int value;
牋牋牋int j;
牋牋牋int i;
牋牋牋int rowCount;
牋牋牋int rowIndex;
牋牋牋int lastRowIndex;