马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
Java的桌面程序开发在java程序员里通常叫swing开发,主要用的swing包里的类开发的,也就是通常说的c/s架构开发用Java保留位图文件
5/23/20019:28:10・Jean-PierreDubé・jdeveloper
--------------------------------------------------------------------------------
12下一页
择要
固然Java供应了几种翻开图象的机制,但保留图象并非它的刚强。这篇技能将报告怎样将图象保留在24位位图文件中。别的,Jean-Pierre还供应了将图象文件写进位图文件所需的全体代码。
这篇技能是"在Java使用程序中加载位图文件的慢慢指南"的增补,那篇技能申明了在Java使用程序中加载位图文件的历程。本月我再供应一篇教程,申明怎样将图象保留在24位位图文件中,个中还包括将图象对象写进位图文件的代码片段。
假如您在MicrosoftWindows情况中事情,那末创立位图文件的功效将为您供应很多便利。比方,在我的上一个项目中,我必需将Java与MicrosoftAccess对接。Java程序同意用户在屏幕上画图。这幅图随后被打印到MicrosoftAccess报表中。因为Java不撑持OLE,我的独一选择就是创立该图的一个位图文件,并关照MicrosoftAccess报表在那边能找到这个位图文件。假如您写过向剪贴板发送图象的使用程序,则这个技能大概对您有效--特别是当您将这个信息传送给另外一个使用程序时。
位图文件的格局
位图文件格局撑持4位RLE(路程长度编码)和8位和24位编码。由于我们只处置24位格局,以是上面我们检察一下该文件的布局。
位图文件分为三个部分。我已将它们列鄙人面。
第1部分:位图文件的标头
标头包括位图文件的范例巨细信息和版面信息。布局以下(摘自C言语布局界说):
typedefstructtagBITMAPFILEHEADER{
UINTbfType;
DWORDbfSize;
UINTbfReserved1;
UINTbfReserved2;
DWORDbfOffBits;
}BITMAPFILEHEADER;
上面是对这个清单中的代码元素的申明:
bfType:指定文件范例,其值一直为BM。
bfSize:指定全部文件的巨细(以字节为单元)。
bfReserved1:保存--必需为0。
bfReserved2:保存--必需为0。
bfOffBits:指定从BitmapFileHeader到图象首部的字节偏移量。
如今您已分明位图标头的用处就是标识位图文件。读取位图文件的每一个程序都利用位图标头来举行文件考证。
第2部分:位图信息标头
随后的标头称为信息标头,个中包括图象自己的属性。
上面申明怎样指定Windows3.0(或更高版本)设备自力位图(DIB)的巨细和色彩格局:
typedefstructtagBITMAPINFOHEADER{
DWORDbiSize;
LONGbiWidth;
LONGbiHeight;
WORDbiPlanes;
WORDbiBitCount;
DWORDbiCompression;
DWORDbiSizeImage;
LONGbiXPelsPerMeter;
LONGbiYPelsPerMeter;
DWORDbiClrUsed;
DWORDbiClrImportant;
}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)和部分图象。各个部分由垂线分开:
00000000004D42B53600020000000000360000|0028
000000002000000107000000E00000000100180000
00000000400000B50000020EC400000EC400000000
0000000060000000000000|FFFFFFFFFFFFFFFFFFFF
0000000100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
*
在,我们入手下手检视代码
如今我们已晓得了24位位图文件的布局,上面就是您等候已久的内容:用来将图象对象写进位图文件的代码。
importjava.awt.*;
importjava.io.*;
importjava.awt.image.*;
publicclassBMPFileextendsComponent{
file://---公有常量
privatefinalstaticintBITMAPFILEHEADER_SIZE=14;
privatefinalstaticintBITMAPINFOHEADER_SIZE=40;
file://---公有变量声明
file://---位图文件标头
privatebytebitmapFileHeader[]=newbyte[14];
privatebytebfType[]={B,M};
privateintbfSize=0;
privateintbfReserved1=0;
privateintbfReserved2=0;
privateintbfOffBits=BITMAPFILEHEADER_SIZE+BITMAPINFOHEADER_SIZE;
file://---位图信息标头
privatebytebitmapInfoHeader[]=newbyte[40];
privateintbiSize=BITMAPINFOHEADER_SIZE;
privateintbiWidth=0;
privateintbiHeight=0;
privateintbiPlanes=1;
privateintbiBitCount=24;
privateintbiCompression=0;
privateintbiSizeImage=0x030000;
privateintbiXPelsPerMeter=0x0;
privateintbiYPelsPerMeter=0x0;
privateintbiClrUsed=0;
privateintbiClrImportant=0;
file://---位图原始数据
privateintbitmap[];
file://---文件部分
privateFileOutputStreamfo;
file://---缺省机关函数
publicBMPFile(){
}
publicvoidsaveBitmap(StringparFilename,ImageparImage,int
parWidth,intparHeight){
try{
fo=newFileOutputStream(parFilename);
save(parImage,parWidth,parHeight);
fo.close();
}
catch(ExceptionsaveEx){
saveEx.printStackTrace();
}
}
/*
*saveMethod是该历程的主办法。该办法
*将挪用convertImage办法以将内存图象转换为
*字节数组;writeBitmapFileHeader办法创立并写进
*位图文件标头;writeBitmapInfoHeader创立
*信息标头;writeBitmap写进图象。
*
*/
privatevoidsave(ImageparImage,intparWidth,intparHeight){
try{
convertImage(parImage,parWidth,parHeight);
writeBitmapFileHeader();
writeBitmapInfoHeader();
writeBitmap();
}
catch(ExceptionsaveEx){
saveEx.printStackTrace();
}
}
/*
*convertImage将内存图象转换为位图格局(BRG)。
*它还盘算位图信息标头所用的某些信息。
*
*/
privatebooleanconvertImage(ImageparImage,intparWidth,intparHeight){
intpad;
bitmap=newint[parWidth*parHeight];
PixelGrabberpg=newPixelGrabber(parImage,0,0,parWidth,parHeight,
bitmap,0,parWidth);
try{
pg.grabPixels();
}
catch(InterruptedExceptione){
e.printStackTrace();
return(false);
}
pad=(4-((parWidth*3)%4))*parHeight;
biSizeImage=((parWidth*parHeight)*3)+pad;
bfSize=biSizeImage+BITMAPFILEHEADER_SIZE+
BITMAPINFOHEADER_SIZE;
biWidth=parWidth;
biHeight=parHeight;
return(true);
}
/*
*writeBitmap将象素捕捉器前往的图象转换为
*所需的格局。请记着:扫描行在位图文件中是
*反向存储的!
*
*每一个扫描行必需补足为4个字节。
*/
privatevoidwriteBitmap(){
intsize;
intvalue;
intj;
inti;
introwCount;
introwIndex;
intlastRowIndex;
intpad;
intpadCount;
bytergb[]=newbyte[3];
size=(biWidth*biHeight)-1;
pad=4-((biWidth*3)%4);
if(pad==4)//<====毛病修改
pad=0;//<====毛病修改
rowCount=1;
padCount=0;
rowIndex=size-biWidth;
lastRowIndex=rowIndex;
try{
for(j=0;j<size;j++){
value=bitmap[rowIndex];
rgb[0]=(byte)(value&0xFF);
rgb[1]=(byte)((value>>8)&0xFF);
rgb[2]=(byte)((value>>16)&0xFF);
fo.write(rgb);
if(rowCount==biWidth){
padCount+=pad;
for(i=1;i<=pad;i++){
fo.write(0x00);
}
rowCount=1;
rowIndex=lastRowIndex-biWidth;
lastRowIndex=rowIndex;
}
else
rowCount++;
rowIndex++;
}
file://---更新文件巨细
bfSize+=padCount-pad;
biSizeImage+=padCount-pad;
}
catch(Exceptionwb){
wb.printStackTrace();
}
}
/*
*writeBitmapFileHeader将位图文件标头写进文件中。
*
*/
privatevoidwriteBitmapFileHeader(){
try{
fo.write(bfType);
fo.write(intToDWord(bfSize));
fo.write(intToWord(bfReserved1));
fo.write(intToWord(bfReserved2));
fo.write(intToDWord(bfOffBits));
}
catch(Exceptionwbfh){
wbfh.printStackTrace();
}
}
/*
*
*writeBitmapInfoHeader将位图信息标头
*写进文件中。
*
*/
privatevoidwriteBitmapInfoHeader(){
try{
fo.write(intToDWord(biSize));
fo.write(intToDWord(biWidth));
fo.write(intToDWord(biHeight));
fo.write(intToWord(biPlanes));
fo.write(intToWord(biBitCount));
fo.write(intToDWord(biCompression));
fo.write(intToDWord(biSizeImage));
fo.write(intToDWord(biXPelsPerMeter));
fo.write(intToDWord(biYPelsPerMeter));
fo.write(intToDWord(biClrUsed));
fo.write(intToDWord(biClrImportant));
}
catch(Exceptionwbih){
wbih.printStackTrace();
}
}
/*
*
*intToWord将整数转换为单字,前往值
*存储在一个双字节数组中。
*
*/
privatebyte[]intToWord(intparValue){
byteretValue[]=newbyte[2];
retValue[0]=(byte)(parValue&0x00FF);
retValue[1]=(byte)((parValue>>8)&0x00FF);
return(retValue);
}
/*
*
*intToDWord将整数转换为双字,前往值
*存储在一个4字节数组中。
*
*/
privatebyte[]intToDWord(intparValue){
byteretValue[]=newbyte[4];
retValue[0]=(byte)(parValue&0x00FF);
retValue[1]=(byte)((parValue>>8)&0x000000FF);
retValue[2]=(byte)((parValue>>16)&0x000000FF);
retValue[3]=(byte)((parValue>>24)&0x000000FF);
return(retValue);
}
}
小结
这就是所要做的全体事情。我确信您将会发明这个类很有效,由于到JDK1.1.6为止,Java不撑持用任何经常使用的格局保留图象。JDK1.2将撑持创立JPEG图象,但不撑持创立位图。以是这个类仍将弥补JDK1.2中的空缺。
有了这样一个呼声:让java代替C语言成为基本语言。这些足以说明java简单易学的这个优点。其次,java的功能强大,前面我也提到了,EJB3.0的推出使java成为了大型项目的首选。 |