说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

如何用java编写BMP的显示程序???

编辑:说三道四文库 发布时间:2017-03-25 10:19
HTML文档下载 WORD文档下载 PDF文档下载
前提:尽量不使用JNI,不使用vj编写
请指教!
可以 阿 你要不要 阿 ??
给分的阿 !!
我可以给你 代码 
星期一给你
谢谢两位
请告诉我大概的方法,譬如用到什么类库和API
当然,附源程序更好
mail to :wdfriend@263.net
谢了先
ava 技巧 43:如何在 Java 应用程序中读取 8 位和 24 位 Microsoft Windows 位图
在 Java 应用程序中加载位图文件的逐步指南

作者:Jeff West 和 John D. Mitchell
摘要
目前,标准的 getImage() 方法仅支持 GIF 和 JPEG 图像。尽管存在用于读取 PNG(可移植网络图形)格式的 Java 例程,但我们还没听说过有用于读取 Microsoft Windows 位图图像的阅读程序。Jeff West 撰写的这篇技巧提供了加载 Windows 位图图像的代码。Java 的当前发行版并不正式支持在 Java 应用程序中读取 Microsoft Windows 位图文件。但别担心,我们有办法解决这个问题!这篇技巧将说明如何完成这一任务 -- 我们首先说明读取 Microsoft Windows 文件格式的基本步骤。Windows DIB(设备独立的位图)文件格式比较简单。与纯位图格式不同,DIB 格式保留着用于在内存中存储图像的明确信息。问题是图像格式的变体如此之多(1 位、4 位、8 位和 16 位,以及其他格式)。本篇 Java 技巧中提供的解决方案只处理 8 位和 24 位两种格式。这两种格式代表了最常见的变体。不管是哪种 Windows DIB 子类型,这种文件格式总是由 14 位文件头和 40 位信息头组成。这两个标头精确包含有关文件的存储内容和存储次序的信息。有关标头中每一项的确切含义,请参考 Microsoft Software Development Kit (SDK)。文件其余部分的内容随信息头中数据的不同而不同。我们看一下本文要处理的两种子类型。24 位格式很简单:RGB(红-绿-蓝)颜色值(3 个字节,并按 BGR 排序)紧接在信息头之后。但是,每个扫描行都被补足到 4 个字节。按照说明文档(请参阅 Microsoft SDK)的说法,这种“补足”是为了优化 Windows 位图绘图 API。同时,底部的扫描行是文件中的第一项内容 -- 因此相对普通的图形坐标系统(其矢量方向的正向分别为向下和向右)而言,必须从后向前读取图像。8 位子类型由于在信息头和象素数据之间插入调色板信息而复杂化。因此,每个象素条目只是进入 24 位 RGB 颜色的调色板数组的一个 8 位索引。在象素信息中,每个扫描行同样被补足到 4 个字节。请注意,本文提供的位图图像加载方法不支持对压缩位图图像进行解压缩。实际上,这个例程甚至不寻求这种可能性!如果遇到压缩 Windows DIB 文件,该例程肯定会产生异常。Windows SDK 中有对压缩 Windows DIB 格式的说明。至于性能,在运行 Microsoft Windows 95 的 486-DX2-66MHz 系统上,该例程读取 24 位 640 x 480 的文件(大约 920 千字节)所需的时间不超过 10 秒。使用 BufferedInputStream 而不是 FileInputStream 可明显提高性能。以下例程读取两种文件格式中的任一种,并生成一个 Image 图像。以下代码并未包含全面的错误和异常处理,以避免使该例程更加复杂。您总可用 Windows Paint 程序对不支持的 Windows DIB 子类型进行转换。    /**
 loadbitmap() 方法由 Windows C 代码转换而来。
 只能读取未压缩的 24 位和 8 位图像。已在
 Windows 95 上用 Microsoft Paint 保存的图像
对它进行了测试。如果图像不是 24 位或 8 位图像,
 该程序拒绝进行任何尝试。我猜测如果先用 1100,
 然后用 0011 对字节执行掩码操作,则也可将 4 位
 图像包括在内。我实际上对这些图像不感兴趣。
 如果尝试读取压缩图像,该例程可能失败,并产生
 一个 IOException 异常。如果变量 ncompression
 不为 0,则表示已经过压缩。

 参数:
     sdir 和 sfile 是 FileDialog 的
     getDirectory() 和 getFile() 方法的结果。

 返回值:
     Image 对象,切记要检查 (Image)null !!!!

    */
    public Image loadbitmap (String sdir, String sfile)
 {
 Image image;
 System.out.println("loading:"+sdir+sfile);
 try
     {
     FileInputStream fs=new FileInputStream(sdir+sfile);
     int bflen=14; // 14 字节 BITMAPFILEHEADER
     byte bf[]=new byte[bflen];
     fs.read(bf,0,bflen);
     int bilen=40; // 40 字节 BITMAPINFOHEADER
     byte bi[]=new byte[bilen];
     fs.read(bi,0,bilen);

     // 解释数据。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nsize = (((int)bf[5]&0xff)<<24)
&nbsp;&nbsp;| (((int)bf[4]&0xff)<<16)
&nbsp;&nbsp;| (((int)bf[3]&0xff)<<8)
&nbsp;&nbsp;| (int)bf[2]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("File type is :"+(char)bf[0]+(char)bf[1]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Size of file is :"+nsize);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nbisize = (((int)bi[3]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[2]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[1]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[0]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Size of bitmapinfoheader is :"+nbisize);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nwidth = (((int)bi[7]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[6]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[5]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[4]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Width is :"+nwidth);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nheight = (((int)bi[11]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[10]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[9]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[8]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Height is :"+nheight);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nplanes = (((int)bi[13]&0xff)<<8) | (int)bi[12]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Planes is :"+nplanes);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nbitcount = (((int)bi[15]&0xff)<<8) | (int)bi[14]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("BitCount is :"+nbitcount);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 查找表明压缩的非零值
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int ncompression = (((int)bi[19])<<24)
&nbsp;&nbsp;| (((int)bi[18])<<16)
&nbsp;&nbsp;| (((int)bi[17])<<8)
&nbsp;&nbsp;| (int)bi[16];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Compression is :"+ncompression);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nsizeimage = (((int)bi[23]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[22]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[21]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[20]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("SizeImage is :"+nsizeimage);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nxpm = (((int)bi[27]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[26]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[25]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[24]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("X-Pixels per meter is :"+nxpm);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nypm = (((int)bi[31]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[30]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[29]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[28]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Y-Pixels per meter is :"+nypm);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nclrused = (((int)bi[35]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[34]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[33]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[32]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Colors used are :"+nclrused);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nclrimp = (((int)bi[39]&0xff)<<24)
&nbsp;&nbsp;| (((int)bi[38]&0xff)<<16)
&nbsp;&nbsp;| (((int)bi[37]&0xff)<<8)
&nbsp;&nbsp;| (int)bi[36]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Colors important are :"+nclrimp);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (nbitcount==24)
&nbsp;&nbsp;{
&nbsp;&nbsp;// 24 位格式不包含调色板数据,但扫描行被补足到
&nbsp;&nbsp;// 4 个字节。
&nbsp;&nbsp;int npad = (nsizeimage / nheight) - nwidth * 3;
&nbsp;&nbsp;int ndata[] = new int [nheight * nwidth];
&nbsp;&nbsp;byte brgb[] = new byte [( nwidth + npad) * 3 * nheight];
&nbsp;&nbsp;fs.read (brgb, 0, (nwidth + npad) * 3 * nheight);
&nbsp;&nbsp;int nindex = 0;
&nbsp;&nbsp;for (int j = 0; j < nheight; j++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i < nwidth; i++)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;ndata [nwidth * (nheight - j - 1) + i] =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(255&0xff)<<24
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (((int)brgb[nindex+2]&0xff)<<16)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (((int)brgb[nindex+1]&0xff)<<8)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (int)brgb[nindex]&0xff;
&nbsp;&nbsp;&nbsp;// System.out.println("Encoded Color at ("
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+i+","+j+")is:"+nrgb+" (R,G,B)= ("
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+((int)(brgb[2]) & 0xff)+","
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+((int)brgb[1]&0xff)+","
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+((int)brgb[0]&0xff)+")");
&nbsp;&nbsp;&nbsp;nindex += 3;
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nindex += npad;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;image = createImage
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( new MemoryImageSource (nwidth, nheight,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ndata, 0, nwidth));
&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (nbitcount == 8)
&nbsp;&nbsp;{
&nbsp;&nbsp;// 必须确定颜色数。如果 clrsused 参数大于 0,
&nbsp;&nbsp;// 则颜色数由它决定。如果它等于 0,则根据
&nbsp;&nbsp;// bitsperpixel 计算颜色数。
&nbsp;&nbsp;int nNumColors = 0;
&nbsp;&nbsp;if (nclrused > 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nNumColors = nclrused;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nNumColors = (1&0xff)<<nbitcount;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;System.out.println("The number of Colors is"+nNumColors);

&nbsp;&nbsp;// 某些位图不计算 sizeimage 域,请找出
&nbsp;&nbsp;// 这些情况并对它们进行修正。
&nbsp;&nbsp;if (nsizeimage == 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nsizeimage = ((((nwidth*nbitcount)+31) & ~31 ) >> 3);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nsizeimage *= nheight;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("nsizeimage (backup) is"+nsizeimage);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;// 读取调色板颜色。
&nbsp;&nbsp;int npalette[] = new int [nNumColors];
&nbsp;&nbsp;byte bpalette[] = new byte [nNumColors*4];
&nbsp;&nbsp;fs.read (bpalette, 0, nNumColors*4);
&nbsp;&nbsp;int nindex8 = 0;
&nbsp;&nbsp;for (int n = 0; n < nNumColors; n++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;npalette[n] = (255&0xff)<<24
&nbsp;&nbsp;&nbsp;| (((int)bpalette[nindex8+2]&0xff)<<16)
&nbsp;&nbsp;&nbsp;| (((int)bpalette[nindex8+1]&0xff)<<8)
&nbsp;&nbsp;&nbsp;| (int)bpalette[nindex8]&0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// System.out.println ("Palette Color "+n
&nbsp;&nbsp;&nbsp;+" is:"+npalette[n]+" (res,R,G,B)= ("
&nbsp;&nbsp;&nbsp;+((int)(bpalette[nindex8+3]) & 0xff)+","
&nbsp;&nbsp;&nbsp;+((int)(bpalette[nindex8+2]) & 0xff)+","
&nbsp;&nbsp;&nbsp;+((int)bpalette[nindex8+1]&0xff)+","
&nbsp;&nbsp;&nbsp;+((int)bpalette[nindex8]&0xff)+")");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nindex8 += 4;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;// 读取图像数据(实际上是调色板的索引)
&nbsp;&nbsp;// 扫描行仍被补足到 4 个字节。
&nbsp;&nbsp;int npad8 = (nsizeimage / nheight) - nwidth;
&nbsp;&nbsp;System.out.println("nPad is:"+npad8);

&nbsp;&nbsp;int ndata8[] = new int [nwidth*nheight];
&nbsp;&nbsp;byte bdata[] = new byte [(nwidth+npad8)*nheight];
&nbsp;&nbsp;fs.read (bdata, 0, (nwidth+npad8)*nheight);
&nbsp;&nbsp;nindex8 = 0;
&nbsp;&nbsp;for (int j8 = 0; j8 < nheight; j8++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int i8 = 0; i8 < nwidth; i8++)
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;ndata8 [nwidth*(nheight-j8-1)+i8] =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;npalette [((int)bdata[nindex8]&0xff)];
&nbsp;&nbsp;&nbsp;nindex8++;
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nindex8 += npad8;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;image = createImage
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( new MemoryImageSource (nwidth, nheight,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ndata8, 0, nwidth));
&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;{
&nbsp;&nbsp;System.out.println ("Not a 24-bit or 8-bit Windows Bitmap, aborting...");
&nbsp;&nbsp;image = (Image)null;
&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs.close();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return image;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;catch (Exception e)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Caught exception in loadbitmap!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;return (Image) null;
&nbsp;}
您已掌握了读取位图文件的技巧。很容易对此方法进行扩展,使它能够读取单色和 16 色(4 位)格式。
 
  
Java 技巧 43:如何在 Java 应用程序中读取 8 位和 24 位 Microsoft Windows 位图
在 Java 应用程序中加载位图文件的逐步指南

作者:Jeff West 和 John D. Mitchell

摘要
目前,标准的 getImage() 方法仅支持 GIF 和 JPEG 图像。尽管存在用于读取 PNG(可移植网络图形)格式的 Java 例程,但我们还没听说过有用于读取 Microsoft Windows 位图图像的阅读程序。Jeff West 撰写的这篇技巧提供了加载 Windows 位图图像的代码。 
Java 的当前发行版并不正式支持在 Java 应用程序中读取 Microsoft Windows 位图文件。但别担心,我们有办法解决这个问题!这篇技巧将说明如何完成这一任务 -- 我们首先说明读取 Microsoft Windows 文件格式的基本步骤。 
Windows DIB(设备独立的位图)文件格式比较简单。与纯位图格式不同,DIB 格式保留着用于在内存中存储图像的明确信息。问题是图像格式的变体如此之多(1 位、4 位、8 位和 16 位,以及其他格式)。本篇 Java 技巧中提供的解决方案只处理 8 位和 24 位两种格式。这两种格式代表了最常见的变体。 

不管是哪种 Windows DIB 子类型,这种文件格式总是由 14 位文件头和 40 位信息头组成。这两个标头精确包含有关文件的存储内容和存储次序的信息。有关标头中每一项的确切含义,请参考 Microsoft Software Development Kit (SDK)。文件其余部分的内容随信息头中数据的不同而不同。 

我们看一下本文要处理的两种子类型。24 位格式很简单:RGB(红-绿-蓝)颜色值(3 个字节,并按 BGR 排序)紧接在信息头之后。但是,每个扫描行都被补足到 4 个字节。按照说明文档(请参阅 Microsoft SDK)的说法,这种“补足”是为了优化 Windows 位图绘图 API。同时,底部的扫描行是文件中的第一项内容 -- 因此相对普通的图形坐标系统(其矢量方向的正向分别为向下和向右)而言,必须从后向前读取图像。 

8 位子类型由于在信息头和象素数据之间插入调色板信息而复杂化。因此,每个象素条目只是进入 24 位 RGB 颜色的调色板数组的一个 8 位索引。在象素信息中,每个扫描行同样被补足到 4 个字节。 

请注意,本文提供的位图图像加载方法不支持对压缩位图图像进行解压缩。实际上,这个例程甚至不寻求这种可能性!如果遇到压缩 Windows DIB 文件,该例程肯定会产生异常。Windows SDK 中有对压缩 Windows DIB 格式的说明。 

至于性能,在运行 Microsoft Windows 95 的 486-DX2-66MHz 系统上,该例程读取 24 位 640 x 480 的文件(大约 920 千字节)所需的时间不超过 10 秒。使用 BufferedInputStream 而不是 FileInputStream 可明显提高性能。 

以下例程读取两种文件格式中的任一种,并生成一个 Image 图像。以下代码并未包含全面的错误和异常处理,以避免使该例程更加复杂。您总可用 Windows Paint 程序对不支持的 Windows DIB 子类型进行转换。 

    /**
 loadbitmap() 方法由 Windows C 代码转换而来。
 只能读取未压缩的 24 位和 8 位图像。已在
 Windows 95 上用 Microsoft Paint 保存的图像
对它进行了测试。如果图像不是 24 位或 8 位图像,
 该程序拒绝进行任何尝试。我猜测如果先用 1100,
 然后用 0011 对字节执行掩码操作,则也可将 4 位
 图像包括在内。我实际上对这些图像不感兴趣。
 如果尝试读取压缩图像,该例程可能失败,并产生
 一个 IOException 异常。如果变量 ncompression 
 不为 0,则表示已经过压缩。

 参数:
     sdir 和 sfile 是 FileDialog 的
     getDirectory() 和 getFile() 方法的结果。

 返回值:
     Image 对象,切记要检查 (Image)null !!!!

    */
    public Image loadbitmap (String sdir, String sfile)
 {
 Image image;
 System.out.println("loading:"+sdir+sfile);
 try
     {
     FileInputStream fs=new FileInputStream(sdir+sfile);
     int bflen=14; // 14 字节 BITMAPFILEHEADER
     byte bf[]=new byte[bflen];
     fs.read(bf,0,bflen);
     int bilen=40; // 40 字节 BITMAPINFOHEADER
     byte bi[]=new byte[bilen];
     fs.read(bi,0,bilen);

     // 解释数据。
     int nsize = (((int)bf[5]&0xff)<<24) 
  | (((int)bf[4]&0xff)<<16)
  | (((int)bf[3]&0xff)<<8)
  | (int)bf[2]&0xff;
     System.out.println("File type is :"+(char)bf[0]+(char)bf[1]);
     System.out.println("Size of file is :"+nsize);

     int nbisize = (((int)bi[3]&0xff)<<24)
  | (((int)bi[2]&0xff)<<16)
  | (((int)bi[1]&0xff)<<8)
  | (int)bi[0]&0xff;
     System.out.println("Size of bitmapinfoheader is :"+nbisize);

     int nwidth = (((int)bi[7]&0xff)<<24)
  | (((int)bi[6]&0xff)<<16)
  | (((int)bi[5]&0xff)<<8)
  | (int)bi[4]&0xff;
     System.out.println("Width is :"+nwidth);

     int nheight = (((int)bi[11]&0xff)<<24)
  | (((int)bi[10]&0xff)<<16)
  | (((int)bi[9]&0xff)<<8)
  | (int)bi[8]&0xff;
     System.out.println("Height is :"+nheight);

     int nplanes = (((int)bi[13]&0xff)<<8) | (int)bi[12]&0xff;
     System.out.println("Planes is :"+nplanes);

     int nbitcount = (((int)bi[15]&0xff)<<8) | (int)bi[14]&0xff;
     System.out.println("BitCount is :"+nbitcount);

     // 查找表明压缩的非零值
     int ncompression = (((int)bi[19])<<24)
  | (((int)bi[18])<<16)
  | (((int)bi[17])<<8)
  | (int)bi[16];
     System.out.println("Compression is :"+ncompression);

     int nsizeimage = (((int)bi[23]&0xff)<<24)
  | (((int)bi[22]&0xff)<<16)
  | (((int)bi[21]&0xff)<<8)
  | (int)bi[20]&0xff;
     System.out.println("SizeImage is :"+nsizeimage);

     int nxpm = (((int)bi[27]&0xff)<<24)
  | (((int)bi[26]&0xff)<<16)
  | (((int)bi[25]&0xff)<<8)
  | (int)bi[24]&0xff;
     System.out.println("X-Pixels per meter is :"+nxpm);

     int nypm = (((int)bi[31]&0xff)<<24)
  | (((int)bi[30]&0xff)<<16)
  | (((int)bi[29]&0xff)<<8)
  | (int)bi[28]&0xff;
     System.out.println("Y-Pixels per meter is :"+nypm);

     int nclrused = (((int)bi[35]&0xff)<<24)
  | (((int)bi[34]&0xff)<<16)
  | (((int)bi[33]&0xff)<<8)
  | (int)bi[32]&0xff;
     System.out.println("Colors used are :"+nclrused);

     int nclrimp = (((int)bi[39]&0xff)<<24)
  | (((int)bi[38]&0xff)<<16)
  | (((int)bi[37]&0xff)<<8)
  | (int)bi[36]&0xff;
     System.out.println("Colors important are :"+nclrimp);

     if (nbitcount==24)
  {
  // 24 位格式不包含调色板数据,但扫描行被补足到
  // 4 个字节。
  int npad = (nsizeimage / nheight) - nwidth * 3;
  int ndata[] = new int [nheight * nwidth];
  byte brgb[] = new byte [( nwidth + npad) * 3 * nheight];
  fs.read (brgb, 0, (nwidth + npad) * 3 * nheight);
  int nindex = 0;
  for (int j = 0; j < nheight; j++)
      {
      for (int i = 0; i < nwidth; i++)
   {
   ndata [nwidth * (nheight - j - 1) + i] =
       (255&0xff)<<24
       | (((int)brgb[nindex+2]&0xff)<<16)
       | (((int)brgb[nindex+1]&0xff)<<8)
       | (int)brgb[nindex]&0xff;
   // System.out.println("Encoded Color at ("
       +i+","+j+")is:"+nrgb+" (R,G,B)= ("
       +((int)(brgb[2]) & 0xff)+","
       +((int)brgb[1]&0xff)+","
       +((int)brgb[0]&0xff)+")");
   nindex += 3;
   }
      nindex += npad;
      }

  image = createImage
      ( new MemoryImageSource (nwidth, nheight,
          ndata, 0, nwidth));
  }
     else if (nbitcount == 8)
  {
  // 必须确定颜色数。如果 clrsused 参数大于 0,
  // 则颜色数由它决定。如果它等于 0,则根据
  // bitsperpixel 计算颜色数。
  int nNumColors = 0;
  if (nclrused > 0)
      {
      nNumColors = nclrused;
      }
  else
      {
      nNumColors = (1&0xff)<<nbitcount;
      }
  System.out.println("The number of Colors is"+nNumColors);

  // 某些位图不计算 sizeimage 域,请找出
  // 这些情况并对它们进行修正。
  if (nsizeimage == 0)
      {
      nsizeimage = ((((nwidth*nbitcount)+31) & ~31 ) >> 3);
      nsizeimage *= nheight;
      System.out.println("nsizeimage (backup) is"+nsizeimage);
      }

  // 读取调色板颜色。
  int npalette[] = new int [nNumColors];
  byte bpalette[] = new byte [nNumColors*4];
  fs.read (bpalette, 0, nNumColors*4);
  int nindex8 = 0;
  for (int n = 0; n < nNumColors; n++)
      {
      npalette[n] = (255&0xff)<<24
   | (((int)bpalette[nindex8+2]&0xff)<<16)
   | (((int)bpalette[nindex8+1]&0xff)<<8)
   | (int)bpalette[nindex8]&0xff;
      // System.out.println ("Palette Color "+n
   +" is:"+npalette[n]+" (res,R,G,B)= ("
   +((int)(bpalette[nindex8+3]) & 0xff)+","
   +((int)(bpalette[nindex8+2]) & 0xff)+","
   +((int)bpalette[nindex8+1]&0xff)+","
   +((int)bpalette[nindex8]&0xff)+")");
      nindex8 += 4;
      }

  // 读取图像数据(实际上是调色板的索引)
  // 扫描行仍被补足到 4 个字节。
  int npad8 = (nsizeimage / nheight) - nwidth;
  System.out.println("nPad is:"+npad8);

  int ndata8[] = new int [nwidth*nheight];
  byte bdata[] = new byte [(nwidth+npad8)*nheight];
  fs.read (bdata, 0, (nwidth+npad8)*nheight);
  nindex8 = 0;
  for (int j8 = 0; j8 < nheight; j8++)
      {
      for (int i8 = 0; i8 < nwidth; i8++)
   {
   ndata8 [nwidth*(nheight-j8-1)+i8] =
       npalette [((int)bdata[nindex8]&0xff)];
   nindex8++;
   }
      nindex8 += npad8;
      }

  image = createImage
      ( new MemoryImageSource (nwidth, nheight,
          ndata8, 0, nwidth));
  }
     else
  {
  System.out.println ("Not a 24-bit or 8-bit Windows Bitmap, aborting...");
  image = (Image)null;
  }

     fs.close();
     return image;
     }
 catch (Exception e)
     {
     System.out.println("Caught exception in loadbitmap!");
     }
 return (Image) null;
 }


您已掌握了读取位图文件的技巧。很容易对此方法进行扩展,使它能够读取单色和 16 色(4 位)格式。 

作者简介
Jeff West 是加州圣地亚哥市的一名工程学研究生。在研究燃烧和火焰扩张的闲暇之余,他沉迷于 Java。  

 
2014优秀微信开发商评选上线 首批旅游汽车电商房产等行业应用出炉(表) 让梦想照进现实——宝马百度编程马拉松闭幕 IXDC大会:移动交互设计精髓——用户体验 想辨析“马航”等事件真伪,有很多技术和工具可以使用 两倍于IBM的基础设施投资,Google大力发展云服务 听云平台发布移动应用性能黑洞报告 微信开发者大会陶瑾:如何玩转微信支付功能的原理和开发 560亿PV+7.3亿用户,Reddit是如何做到的? 打造安全界的希波克拉底誓言文化 极客的春天来了! Mozilla COO宫力:老牌操作系统如何助力新一代智能电视 App提高用户留存率新招:应用性能监测 韩国手游市场规模超万亿 2014中韩手游项目对接会开幕在即 SanDisk发展之路:专注SSD、推新产品线 AMD发展线路图曝光,欲造500+平方毫米GPU 全球移动开发者:IAP降温,企业应用成待掘金矿 Vuforia 2014 视觉大奖赛:寻找最炫酷AR增强现实应用,迈向巅峰! MapReduce谢幕,谁将成为最终的接棒者? 变身音乐控制器!开源JavaScript库NexusUI 从112台服务器到Q2 50亿基础设施开销,谷歌只用了15年 【技术文章】微信公众平台开发教程新手解惑40则 Qualcomm承诺投入1.5亿美元 扶持中国初创企业 物联网多了把“新板凳” 联想推三款智能硬件 .NET技术+25台服务器怎样支撑世界第54大网站 基调网络发布听云平台:“听”懂App性能 《近匠》豌豆荚李大海:用搜索敲开手机娱乐平台之门 微信开发HTML5轻游戏中的几个坑 【微信大会】企业号、支付功能、智能客服与LBS、电商开发解析 【CTO俱乐部走进海尔】活动图文直播进行中 燃料电池商业化,数据中心或将永不断电? 广告教父的哲学:值得F2P游戏借鉴的8条经验 UC李云:基于Chromium的浏览器如何打造更好体验 FastReoprt 要!要!要!要!要!要!要!要! 《C++ Primer》 中文版怎么还不出啊! 重庆高程报名时间 怎样用NMFTP象网络蚂蚁那样自动获得下载文件的地址 特酷的串口通讯调试工具,有其它工具... 有没有win32版的mysql JDBC驱动? 郁闷!菜鸟的“关于数据库订购与发布的问题” :( 如何使子类的属性不可见 我想画曲线,类似log曲线的样子,不知道vc里面怎样才能方便的实现,有源码最好 特酷的串口通讯调试工具,有其它工具... 请问如何用电话线将各分公司连网,并实现数据上传功能,以保证总公司的数据汇总,CSDN的高手到那里去了,我已经第二次提了,没有一个人回 请指教! 特酷的串口通讯调试工具,有其它工具... 菜得不得了的 问题,从SQL SERVER中导入一个表(如表名QK)到ORACLE后,不知表名变成什么? 怎样看到PowerBuilder User’s Guide使用手冊。Application Techniques使用手冊呀? 一直想看古天乐的《创世纪》,请哪位提供一下网上哪里有它下载或在线看网址,不甚感激! 为什么一执行文件ss.txt得内容就清空了??? 中文问题 特酷的串口通讯调试工具,有其它工具... sos sos 求,向access2000中写数据的asp代码?和用asp连接access有几种方法? 如何保存xml的网页,谢谢! 如何声明一个变量,可在整个程序内调用,并其生命周期和程序一样长??? 请推荐一本数据结构的书,最好是大学教材,c++描叙,写了 求助:vc++ 6.0中,用向导生成了一个windows程序, 我又新加了一个工具条,怎样让它和以前的工具条在同一行上? 请问VIA VT82C686A芯片的主板最大支持的CPU是多少?? 怎样看vb中控件的代码?如:from,command... 大家帮我看看这段代码哪里错了???? 在jbuilder6下如何存取中文数据库,内码的转换如何实现?高手请进,100分奉上 请问如何在dbgrid控件中 第3列=第2列×第1列 有什么方法可以获得页面信息 菜鸟请教一个复杂结构类型结构体成员变量初始化赋值出错的问题。 CDC实现图片运动问题,请大家多多帮忙?如何擦掉已经画出的图片 那里有Delphi函数表?API的个人理解,希望修正!(新人学习在过程中的问题) exchange的路由器问题 WinFax的烦事。 请问IsProxyClass函数在哪找 请问怎么才能实现将一个datawindow中的某一列拖放到另外一个同样的datawindw中 有报考今年3月份高教自考《计算机及应用》专业的朋友吗? 我要找C!各位帮忙! 为什么在MS_DOS下运行MySQL提示"This program cannot be run in DOS mode"? 关于 Execute 为什么在VS.net beta2开发的东西,在安装正式版后运行不了 请问 有谁知道《c++ primer》那里可以下载?? 怎么不能删除啊???????? 同居愉快! 请问:dos环境下c语言中有没有多线程?如果没有那么飞机游戏中不同的飞机同时运动怎么办. php的安装问题!!!! 为什么我安装PB8后只显示支持INFORMIX V9。0而不支持V7。0 等物质的量的镁和足量的O2 CO2 N2反应 哪个生成的固体质量最多还有:等物质的量的O2 CO2 N2和足量的镁反应 哪个生成固体质量最多 描述家乡的天气和人们正在做什么的英语作文用,感谢收看中央电视台的《环游中国》节目开头要2篇. 声现象,初中物理一个人在窗前用望远镜观察到远处建筑架上工人以每秒1次的频率敲打钢钉,他听到打击声恰好与看到击锤的动作一致,当工人停止击锤后,他又听到了2次锤击声,工人离观察者的 农华101怎么样 有没有初中生关于保护校园环境的英语作文 喜马拉雅山脉是什么板块和什么板块碰撞挤压形成? 打哈欠时,耳骨膜不能正常振动,所以此时不太容易听清周围的声音, 靠空气柱振动发声的弦乐器有什么? 喜马拉雅山是哪俩个版块挤压形成的 为什么打哈欠的时候会听不清声音 初二物理问题 空气柱四个玻璃杯,里面都有高度不同的水(从大到小ABCD排),用细棒敲打杯子,能发出1、2、3、4四个音阶,对应的杯子?如果是往里面吹气呢?敲打与什么有关?吹气又与什么有关 解释鲁迅《雪》中的词语1、【朔方】的雪花在纷飞之后,群却永远如粉,如沙.2、他也就【目光灼灼】地嘴唇通红地坐在雪地里.3、晴天又来【消逝】他皮肤. 为什么打哈欠时会听不见声音 小学三年级科学 如何比较水和油的轻重?水和油谁轻谁重? 鲁迅《雪》 第一段阅读 (最好有讲解,“江南的雪”有什么特点?你能看出 描写江南雪景的句子中倾注作者怎 样的情感? 青藏高原号称什么? 一个声源在震动,但 人听不到声音,关于产生这种现象的可能原因,有哪几种认真回答给悬赏 作文家乡的环境怎么写 号称世界屋脊的是什么 镁在二氧化碳中燃烧是氧化反应吗? 家乡的环境的作文 青藏高原号称"世界屋脊 女同学说话的声音“尖细”,是指女同学发出的声音的____高,这是因为女生说话时声带振动比较____的缘故物理 喜马拉雅山不断( ),是由于( )和( )板块挤压形成 青藏高原号称什么哦 物质的量为0.10mol的镁条在只含有二氧化碳和氧气的混合气体的容器中燃烧(产物不含碳酸镁)反应后容器内固体的质量不可能为A3.2 B4.0 C4.2 D4.6答案是D哦 有人认为只有静止或做匀速直线运动的物体才具有惯性,做变速运动的物体不具有惯性,这种看法对吗? 一篇关于保护地球环境的英语作文! 下列各组混合物的物质的量均为a mol,组内物质按任意比例混合,完全燃烧时消耗O2的物质的量不变的是( ).A.甲烷、甲醇、甲醛    B.乙炔、苯、1,3-丁二烯C.丙烯、2-丁烯 D.乙醇、乙 喜马拉雅山是由( )挤压形成的 怎样保护地球的英语作文 请观察黄土高原生态建设示意图,将措施与对应地貌类型连接起来,并说出生态建设的好处.建挡土坝,护坡被等.缓坡地(山顶地带)营造灌木丛,种植山杏等.陡坡地(山腰地带)建梯田,种植山 惯性可以保持物体做加速直线运动的状态么?做匀加速直线运动的物体,撤掉外力后的瞬间因为惯性不是可以继续做加速直线运动吗?为什么说惯性是物体保持匀速直线运动或静止状态的性质,而 H2S可在空气中燃烧.假设空气中N2和O2之比为4:1其他成分不计.将1L升H2S气体和a升空气混合点燃,若反应前后气体温度 不变(20摄氏度,1标准大气压).当a取值不同时,燃烧后气体的总体积为多少 关于科学的小课题研究,比如说什么东西对人体的危害有多么大,不要什么报告或意义,只要题目和准备什么材料, 喜马拉雅山脉是由 A印度洋板块与亚欧板块碰撞形成? 王力防盗门怎么样 初中科学研究课题研究方案例子 喜马拉雅山脉的形成因为()A.非洲板块与亚欧板块漂移分离B.亚欧板块与印度洋板块碰撞挤压C.亚欧板块与印度洋板块漂移分离 王力防盗门好吗 如何制定小课题研究方案 为什么印度洋板块与亚欧板块碰撞,形成的喜马拉雅山脉以北是高原呢碰撞后形成喜马拉雅山脉,山脉南部是平原,北部却是海拔超过5000米的青藏高原呢 外界传来的声波引起( )振动,然后通过听觉神经把信号传给( )如题 各位谁有保护校园环境的英语作文那!还要是关于保护校园环境的 喜马拉雅山脉是亚欧板块和印度洋板块碰撞形成的,但是又说是两个大陆板块碰撞形成的,那印度洋板块不是大洋板块吗?另一个问题,为什么北大西洋暖流不是终年受到西风控制的? 声音主要是通过( )将声音传到听觉神经2.声音是通过( )传到鼓膜的 保护校园环境 英语作文 十万火急In school no matter we go ,we can see anyone wastes the seriously.Such as paper ,bottle,food,water and so on.If you go to the wc use the water clear your hand,don't close the tap;leave the classroom never t 保护家乡的环境750字作文 急15号下午3点前 声音通过什么什么也能传到听觉神经引起听觉科学中把声音的这种导方式叫做什么 怎样保护我们的校园环境?英语作文300字 初中物理的声现象声音的振动频率决定了______A声音的传播远近B声音的高低为什么写A错了,声音的振幅才是响度 人通过什么的振动来发声的,人能自己的说话声是通过传到听觉神经的 请设计一个实验证明声波能使空气振动 一个人在窗前用望远镜观察到远处建筑架上工人以每秒1次的频率敲打钢钉,他听到打击声恰好与看到击锤的动作一致,当工人停止击锤后,他又听到了2次锤击声,工人离观察者的距离约为_______米 什么被称为世界屋脊 外科医生可以利用超声波振动除去人体内的结石,这说明声波可以传递(). 1如何证明桌子发声时也在震动?2北京到上海的距离是1000km.假设声音在空气中能够传到那么远,声音从北京传到上海要多长时间?火车从北京到上海要多长时间?大型喷气式客机呢?自己查所需数 被称为“世界屋脊”的是_______ 初中科学小课题研究题目,求个灵感啊,在线等 急救~谁能告诉我用物理的知识说明生活中的声现象(说一种声现象)可以不可以说点新鲜的~
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘