JAVA教程之用 Java 保留位图文件
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;
privatebytebfType[]={B,M};
privateintbfSize=0;
privateintbfReserved1=0;
privateintbfReserved2=0;
privateintbfOffBits=BITMAPFILEHEADER_SIZE+BITMAPINFOHEADER_SIZE;
file://---位图信息标头
privatebytebitmapInfoHeader[]=newbyte;
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;
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;
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;
rgb=(byte)(value&0xFF);
rgb=(byte)((value>>8)&0xFF);
rgb=(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;
retValue=(byte)(parValue&0x00FF);
retValue=(byte)((parValue>>8)&0x00FF);
return(retValue);
}
/*
*
*intToDWord将整数转换为双字,前往值
*存储在一个4字节数组中。
*
*/
privatebyte[]intToDWord(intparValue){
byteretValue[]=newbyte;
retValue=(byte)(parValue&0x00FF);
retValue=(byte)((parValue>>8)&0x000000FF);
retValue=(byte)((parValue>>16)&0x000000FF);
retValue=(byte)((parValue>>24)&0x000000FF);
return(retValue);
}
}
小结
这就是所要做的全体事情。我确信您将会发明这个类很有效,由于到JDK1.1.6为止,Java不撑持用任何经常使用的格局保留图象。JDK1.2将撑持创立JPEG图象,但不撑持创立位图。以是这个类仍将弥补JDK1.2中的空缺。
有了这样一个呼声:让java代替C语言成为基本语言。这些足以说明java简单易学的这个优点。其次,java的功能强大,前面我也提到了,EJB3.0的推出使java成为了大型项目的首选。 Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实现了“一次编译、到处执行”的跨平台特性。 一般学编程语言都是从C语开始学的,我也不例外,但还是可能不学过程语言而直接学面向对象语言的,你是刚接触语言,还是从C开始学比较好,基础会很深点,如果你直接学习JAVA也能上手,一般大家在学语言的时候都记一些语言的关键词,常有的包和接口等。再去做逻辑代码的编写,以后的学习过程都是从逻辑代码编写中提升的,所以这方面都是经验积累的。你要开始学习就从 吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧 那么我书也看了,程序也做了,别人问我的问题我都能解决了,是不是就成为高手了呢?当然没那么简单,这只是万里长征走完了第一步。不信?那你出去接一个项目,你知道怎么下手吗,你知道怎么设计吗,你知道怎么组织人员进行开发吗?你现在脑子里除了一些散乱的代码之外,可能再没有别的东西了吧! 接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。 Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台 是一种使网页(Web Page)由静态(Static)转变为动态(Dynamic)的语言 接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。 Jive的资料在很多网站上都有,大家可以找来研究一下。相信你读完代码后,会有脱胎换骨的感觉。遗憾的是Jive从2.5以后就不再无条件的开放源代码,同时有licence限制。不过幸好还有中国一流的Java程序员关注它,外国人不开源了,中国人就不能开源吗?这里向大家推荐一个汉化的Jive版本—J道。Jive(J道版)是由中国Java界大名 鼎鼎的banq在Jive 2.1版本基础上改编而成, 全中文,增加了一些实用功能,如贴图,用户头像和用户资料查询等,而且有一个开发团队在不断升级。你可以访问banq的网站 另外编写和运行Java程序需要JDK(包括JRE),在sun的官方网站上有下载,thinking in java第三版用的JDK版本是1.4,现在流行的版本1.5(sun称作J2SE 5.0,汗),不过听说Bruce的TIJ第四版国外已经出来了,是专门为J2SE 5.0而写的。 多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间,使得程序员不用再为内存管理而担忧。在 Java 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。 在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。 那么我书也看了,程序也做了,别人问我的问题我都能解决了,是不是就成为高手了呢?当然没那么简单,这只是万里长征走完了第一步。不信?那你出去接一个项目,你知道怎么下手吗,你知道怎么设计吗,你知道怎么组织人员进行开发吗?你现在脑子里除了一些散乱的代码之外,可能再没有别的东西了吧! 自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。 在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。 其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。 至于JDBC,就不用我多说了,你如果用java编过存取数据库的程序,就应该很熟悉。还有,如果你要用Java编发送电子邮件的程序,你就得看看Javamail 了。 象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。 是一种将安全性(Security)列为第一优先考虑的语言
页:
[1]