Java技巧:用Java保存位图文件
2008-01-05 18:52:12 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁诡垎鍐f寖闂佺娅曢幑鍥灳閺冨牆绀冩い蹇庣娴滈箖鏌ㄥ┑鍡欏嚬缂併劎绮妵鍕箳鐎n亞浠鹃梺闈涙搐鐎氫即鐛崶顒夋晬婵絾瀵ч幑鍥蓟閻斿摜鐟归柛顭戝枛椤牆顪冮妶搴′簼缂侇喗鎸搁悾鐑藉础閻愬秵妫冮崺鈧い鎺戝瀹撲礁鈹戦悩鎻掝伀缁惧彞绮欓弻娑氫沪閹规劕顥濋梺閫炲苯澧伴柟铏崌閿濈偛鈹戠€n€晠鏌嶆潪鎷屽厡闁汇倕鎳愮槐鎾存媴閸撴彃鍓卞銈嗗灦閻熲晛鐣烽妷褉鍋撻敐搴℃灍闁绘挻娲橀妵鍕箛闂堟稐绨肩紓浣藉煐濮樸劎妲愰幘璇茬闁冲搫鍊婚ˇ鏉库攽椤旂》宸ユい顓炲槻閻g兘骞掗幋鏃€鐎婚梺瑙勬儗閸樺€熲叺婵犵數濮烽弫鍛婃叏椤撱垹纾婚柟鍓х帛閳锋垶銇勯幒鍡椾壕缂備礁顦遍弫濠氱嵁閸℃稒鍊烽柛婵嗗椤旀劕鈹戦悜鍥╃У闁告挻鐟︽穱濠囨嚃閳哄啰锛滈梺褰掑亰閸欏骸鈻撳⿰鍫熺厸閻忕偟纭堕崑鎾诲箛娴e憡鍊梺纭呭亹鐞涖儵鍩€椤掑啫鐨洪柡浣圭墪閳规垿鎮欓弶鎴犱桓闂佸湱枪閹芥粎鍒掗弮鍫熷仺缂佸顕抽敃鍌涚厱闁哄洢鍔岄悘鐘绘煕閹般劌浜惧┑锛勫亼閸婃牠宕濋敃鈧…鍧楀焵椤掍胶绠剧€光偓婵犱線鍋楀┑顔硷龚濞咃絿妲愰幒鎳崇喓鎷犻懠鑸垫毐闂傚倷鑳舵灙婵炲鍏樺顐ゆ嫚瀹割喖娈ㄦ繝鐢靛У绾板秹寮查幓鎺濈唵閻犺櫣灏ㄥ銉р偓瑙勬尭濡繂顫忛搹鍦<婵☆垰鎼~宥囩磽娴i鍔嶉柟绋垮暱閻g兘骞嬮敃鈧粻濠氭偣閸パ冪骇鐎规挸绉撮—鍐Χ閸℃ê闉嶇紓浣割儐閸ㄥ墎绮嬪澶嬪€锋い鎺嶇瀵灝鈹戦埥鍡楃仯闁告鍕洸濡わ絽鍟崐鍨叏濡厧浜鹃悗姘炬嫹

核心提示:假如您在 Microsoft Windows 环境中工作,那么创建位图文件的功能将为您提供许多方便,Java技巧:用Java保存位图文件,例如,在我的上一个项目中,?? 它还计算位图信息标头所用的某些信息,????/?private boolean convertImage (Image parImage, int p
假如您在 Microsoft Windows 环境中工作,那么创建位图文件的功能将为您提供许多方便。例如,在我的上一个项目中,我必须将 java 与 Microsoft access 对接。Java 程序答应用户在屏幕上绘图。这幅图随后被打印到 Microsoft Access 报表中。由于 Java 不支持 OLE,我的唯一选择就是创建该图的一个位图文件,并通知 Microsoft Access 报表在何处能找到这个位图文件。假如您写过向剪贴板发送图像的应用程序,则这个技巧可能对您有用 -- 尤其是当您将这个信息传递给另一个应用程序时。
位图文件的格式
位图文件格式支持 4 位 RLE(行程长度编码)以及 8 位和 24 位编码。因为我们只处理 24 位格式,所以下面我们查看一下该文件的结构。
位图文件分为三个部分。我已将它们列在下面。
第 1 部分:位图文件的标头
标头包含位图文件的类型大小信息和版面信息。结构如下(摘自 C 语言结构定义):
typedef strUCt tagBITMAPFILEHEADER {
??INT bfType;
??Word bfSize;
??INT bfReserved1;
??INT bfReserved2;
??WORD bfOffBits;
}BITMAPFILEHEADER;
下面是对这个清单中的代码元素的说明:
bfType:指定文件类型,其值始终为 BM。
bfSize:指定整个文件的大小(以字节为单位)。
bfReserved1:保留 -- 必须为 0。
bfReserved2:保留 -- 必须为 0。
bfOffBits:指定从 BitmapFileHeader 到图像首部的字节偏移量。
现在您已经明白位图标头的用途就是标识位图文件。读取位图文件的每个程序都使用位图标头来进行文件验证。
第 2 部分:位图信息标头
随后的标头称为信息标头,其中包含图像本身的属性。
下面说明如何指定 Windows 3.0(或更高版本)设备独立位图 (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:指定目标设备的位面数。这个成员变量的值必须为 1。
biBitCount:指定每个象素的位数。 其值必须为 1、4、8 或 24。
biCompression:指定压缩位图的压缩类型。在 24 位格式中,该变量被设置为 0。
biSizeImage:指定图像的大小(以字节为单位)。假如位图的格式是 BI_RGB,则将此成员变量设置为 0 是有效的。
biXPelsPerMeter:为位图指定目标设备的水平分辨率(以“象素/米”为单位)。应用程序可用该值从最符合当前设备特征的资源群组中选择一个位图。
biYPelsPerMeter:为位图指定目标设备的垂直分辨率(以“象素/米”为单位)。
biClrUsed:指定位图实际所用的颜色表中的颜色索引数。假如 biBitCount 设为 24,则 biClrUsed 指定用来优化 Windows 调色板性能的参考颜色表。
biClrImportant:指定对位图的显示有重要影响的颜色索引数。假如此值为 0,则所有颜色都很重要。
现在已定义了创建图像所需的全部信息。
第 3 部分:图像
在 24 位格式中,图像中的每个象素都由存储为 BRG 的三字节 RGB 序列表示。每个扫描行都被补足到 4 位。为了使这个过程稍复杂一点,图像是自底而上存储的,即第一个扫描行是图像中的最后一个扫描行。下图显示了标头 (BITMAPHEADER) 和 (BITMAPINFOHEADER) 以及部分图像。各个部分由垂线分隔:
0000000000 4D42 B536 0002 0000 0000 0036 0000 0028
0000000020 0000 0107 0000 00E0 0000 0001 0018 0000
0000000040 0000 B500 0002 0EC4 0000 0EC4 0000 0000
0000000060 0000 0000 0000 FFFF FFFF FFFF FFFF FFFF
0000000100 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
*
现在,我们开始检视代码
现在我们已经知道了 24 位位图文件的结构,下面就是您期待已久的内容:用来将图像对象写入位图文件的代码。
import java.awt.*;
import java.io.*;
import java.awt.image.*;
public class BMPFile extends Component {
?//--- 私有常量
?private final static int BITMAPFILEHEADER_SIZE = 14;
?private final static int BITMAPINFOHEADER_SIZE = 40;
?//--- 私有变量声明
?//--- 位图文件标头
?private byte bitmapFileHeader [] = new byte [14];
?private byte bfType [] = {'B', 'M'};
?private int bfSize = 0;
?private int bfReserved1 = 0;
?private int bfReserved2 = 0;
?private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;
?//--- 位图信息标头
?private byte bitmapInfoHeader [] = new byte [40];
?private int biSize = BITMAPINFOHEADER_SIZE;
?private int biWidth = 0;
?private int biHeight = 0;
?private int biPlanes = 1;
?private int biBitCount = 24;
?private int biCompression = 0;
?private int biSizeImage = 0x030000;
?private int biXPelsPerMeter = 0x0;
?private int biYPelsPerMeter = 0x0;
?private int biClrUsed = 0;
?private int biClrImportant = 0;
?//--- 位图原始数据
?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);
????fo.close ();
???
???atch (Exception saveEx) {
????saveEx.printStackTrace ();
???
?}
?/*
?? 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) {
????saveEx.printStackTrace ();
???
?}
?/*
?? convertImage 将内存图像转换为位图格式 (BRG)。
?? 它还计算位图信息标头所用的某些信息。
??
??/
?private boolean convertImage (Image parImage, int parWidth, int parHeight) {
???nt pad;
???itmap = new int [parWidth * parHeight];
???ixelGrabber pg = new PixelGrabber (parImage, 0, 0, parWidth, parHeight,
?????????????????????itmap, 0, parWidth);
???ry {
????pg.grabPixels ();
???
???atch (InterruptedException e) {
????e.printStackTrace ();
????return (false);
???
???ad = (4 - ((parWidth * 3) % 4)) * parHeight;
???iSizeImage = ((parWidth * parHeight) * 3) + pad;
???fSize = biSizeImage + BITMAPFILEHEADER_SIZE +
BITMAPINFOHEADER_SIZE;
???iWidth = parWidth;
???iHeight = parHeight;
???eturn (true);
?}
?/*
?? writeBitmap 将象素捕捉器返回的图像转换为
?? 所需的格式。请记住:扫描行在位图文件中是
?? 反向存储的!
??
?? 每个扫描行必须补足为 4 个字节。
??/
?private void writeBitmap () {
???int size;
???int value;
???int j;
???int i;
???int rowCount;
???int rowIndex;
???int lastRowIndex;
更多精彩
赞助商链接