分享

[JAVA]读取BMP图像,

 jtll521 2011-06-16
http://www./thread-845-1-1.html
1 程序功能
1.1 读取24位的bmp格式的图像
1.2 对图像进行过滤,只显示RGB中的一个通道以及显示成灰度图像
1.3 将图像保存为JPG格式的图像

2 实现过程
2.1 读取BMP格式的图像
2.1.1 图像信息类
由于BMP格式的图像前54个字节都是用来存储图像信息,包括图像宽度、高度、大小等等,因此可以构建图像信息类来读取并存储图像的信息。


  1. public class ImageHead
  2. {
  3. private int width;
  4. private int height;
  5. private int bitcount;
  6. private int size;

  7. public ImageHead(FileInputStream stream)
  8. {
  9. try
  10. {
  11. byte bh[] = new byte[bfhead];
  12. byte bi[] = new byte[bfinfo];

  13. stream.read(bh, 0, bfhead);
  14. stream.read(bi, 0, bfinfo);
  15. //图像宽度
  16. width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
  17. | ( ( (int) bi[6] & 0xff) << 16)
  18. | ( ( (int) bi[5] & 0xff) << 8)
  19. | (int) bi[4] & 0xff;
  20. //图像高度
  21. height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
  22. | ( ( (int) bi[10] & 0xff) << 16)
  23. | ( ( (int) bi[9] & 0xff) << 8)
  24. | (int) bi[8] & 0xff;
  25. //图像位数
  26. bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
  27. //图像大小
  28. size = ( ( (int) bi[23] & 0xff) << 24)
  29. | ( ( (int) bi[22] & 0xff) << 16)
  30. | ( ( (int) bi[21] & 0xff) << 8)
  31. | (int) bi[20] & 0xff;
  32. }
  33. catch (Exception e)
  34. {
  35. e.printStackTrace(System.out);
  36. }
  37. }
  38. }
复制代码

2.1.2 构建位数组
由于像素使用的字节若不是4的倍数,则会自动扩大,由此产生空白。因此我们需要在一开始计算出空白的大小,即
  1. int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
复制代码


由此构建数组如下

  1. byte brgb[] = new byte[ (img.width + blank) * 3 * img.height];
复制代码


2.1.3 读取BMP格式的图像
使用stream.read(brgb, 0, (img.width + blank) * 3 * img.height);读入图像后使用toolkit生成图像:

  1. Toolkit kit = Toolkit.getDefaultToolkit();
  2. image = kit.createImage(new MemoryImageSource(img.width, img.height, data, 0, img.width));
复制代码


2.2 过滤图像,单通道显示

2.2.1  RGBImageFilter类派生
JAVA中存在用于过滤图像的专用类RGBImageFilter,我们只需要对其进行派生即可。

2.2.2 红绿蓝单通道显示
对于每一个像素单元,由三个字节存储RGB三色,还有一个字节用于存储透明度。四个字节的排序为 透明度-红-绿-蓝,由于是16进制并且透明度不改变,因此可以用形如0xffffffff过滤器与色素相与得到指定通道。
红色:0xffff0000
绿色:0xff00ff00
蓝色:0xff0000ff

2.2.3 灰度显示
与单通道显示不同的是,灰度显示本质上是红绿蓝三通道为同一值,从而让灰度存在255阶。
简单的方法是直接选出某一通道,例如红色,覆盖掉其他通道的颜色值从而使得图像显示成灰色。然而这样选取的问题在于,对于一幅红色为0或255的图像,无论蓝色绿色为何,过滤后的图像只会是白色或黑色。
比较好的一种算法是:红色值*0.3+绿色值*0.59+蓝色值*0.11,将得到的值赋予每个通道从而得到灰度值。此种算法的优点在于综合了各个通道,从而避免极端情况。
int gray = (int)(((rgb & 0x00ff0000)>>16)*0.3 + ((rgb & 0x0000ff00)>>8)*0.59 + (rgb & 0x000000ff)*0.11);


2.3 存储为JPG格式
存储为JPG格式我们使用了JAVA的API接口ImageIO实现。由于要使用ImageIO只能将内存中的缓存图像写入文件,因此要先生成缓存图像BufferedImage将图像“画”到其中:


  1. BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);

  2. Graphics2D g2 = bi.createGraphics();
  3. g2.drawImage(image, 0, 0, null);
  4. g2.dispose();
复制代码


最后使用ImageIO写入

  1. ImageIO.write(bi, "jpg", imgFile);
复制代码
自己写的ImageIO类

  1. public class MyImageIO implements IImageIO
  2. {
  3.     private static int bfhead = 14;
  4.     private static int bfinfo = 40;
  5.     public class ImageHead
  6.     {
  7.         private int width;
  8.         private int height;
  9.         private int bitcount;
  10.         private int size;
  11.         public ImageHead(FileInputStream stream)
  12.         {
  13.             try
  14.             {
  15.                 byte bh[] = new byte[bfhead];
  16.                 byte bi[] = new byte[bfinfo];
  17.                 stream.read(bh, 0, bfhead);
  18.                 stream.read(bi, 0, bfinfo);
  19.                 width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
  20.                 | ( ( (int) bi[6] & 0xff) << 16)
  21.                 | ( ( (int) bi[5] & 0xff) << 8)
  22.                 | (int) bi[4] & 0xff;
  23.                 height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
  24.                 | ( ( (int) bi[10] & 0xff) << 16)
  25.                 | ( ( (int) bi[9] & 0xff) << 8)
  26.                 | (int) bi[8] & 0xff;
  27.                 bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
  28.                 size = ( ( (int) bi[23] & 0xff) << 24)
  29.                 | ( ( (int) bi[22] & 0xff) << 16)
  30.                 | ( ( (int) bi[21] & 0xff) << 8)
  31.                 | (int) bi[20] & 0xff;
  32.             }
  33.             catch (Exception e)
  34.             {
  35.                 e.printStackTrace(System.out);
  36.             }
  37.         }
  38.     }
  39.     public Image myRead(String filePath)
  40.     {
  41.         try
  42.         {
  43.             Image image;
  44.             FileInputStream stream = new FileInputStream(filePath);
  45.      ImageHead img = new ImageHead(stream);
  46.             int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
  47.      int data[] = new int[img.height * img.width];
  48.             byte brgb[] = new byte[ (img.width + blank) * 3 * img.height];
  49.      if (img.bitcount == 24)
  50.      {
  51.          stream.read(brgb, 0, (img.width + blank) * 3 * img.height);
  52.          int nindex = 0;
  53.          for (int j = 0; j < img.height; j++)
  54.          {
  55.              for (int i = 0; i < img.width; i++)
  56.              {
  57.           data[img.width * (img.height - j - 1) + i] =
  58.               (255 & 0xff) << 24
  59.               | ( ( (int) brgb[nindex + 2] & 0xff) << 16)
  60.               | ( ( (int) brgb[nindex + 1] & 0xff) << 8)
  61.               | (int) brgb[nindex] & 0xff;
  62.           nindex += 3;
  63.              }
  64.              nindex += blank;
  65.          }
  66.      }
  67.             Toolkit kit = Toolkit.getDefaultToolkit();
  68.      image = kit.createImage(new MemoryImageSource(img.width, img.height, data, 0, img.width));
  69.             return image;
  70.         }
  71.         catch (Exception e)
  72.         {
  73.             e.printStackTrace(System.out);
  74.         }
  75.         return (Image)null;
  76.     }

  77.     public Image myWrite(Image image, String filePath)
  78.     {
  79.         try
  80.         {
  81.             File imgFile = new File(filePath + ".jpg");
  82.             BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
  83.             Graphics2D g2 = bi.createGraphics();
  84.             g2.drawImage(image, 0, 0, null);
  85.             g2.dispose();
  86.             ImageIO.write(bi, "jpg", imgFile); 
  87.             return image;
  88.         }
  89.         catch (Exception e)
  90.         {
  91.             e.printStackTrace(System.out);
  92.         }
  93.         return image;
  94.     }
  95. }
复制代码
ImageProcess 图像处理,包括RGB单通道颜色以及灰度

  1. public class ImageProcessor implements IImageProcessor
  2. {
  3.     public Image showChanelR(Image sourceImage)
  4.     {
  5.         RedFilter filter = new RedFilter();
  6.         Toolkit kit = Toolkit.getDefaultToolkit();
  7. Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
  8.         return newimg;
  9.     }
  10.     public Image showChanelG(Image sourceImage)
  11.     {
  12.         GreenFilter filter = new GreenFilter();
  13.         Toolkit kit = Toolkit.getDefaultToolkit();
  14. Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
  15.         return newimg;
  16.     }
  17.     public Image showChanelB(Image sourceImage)
  18.     {
  19.         BlueFilter filter = new BlueFilter();
  20.         Toolkit kit = Toolkit.getDefaultToolkit();
  21. Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
  22.         return newimg;
  23.     }
  24.     public Image showGray(Image sourceImage)
  25.     {
  26.         GrayFilter filter = new GrayFilter();
  27.         Toolkit kit = Toolkit.getDefaultToolkit();
  28. Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
  29.         return newimg;
  30.     }
  31.     class RedFilter extends RGBImageFilter
  32.     {
  33.         public RedFilter()
  34.         {
  35.             canFilterIndexColorModel = true;
  36.         }
  37.         public int filterRGB(int x, int y, int rgb)
  38.         {
  39.             return (rgb & 0xffff0000);
  40.         }
  41.     }
  42.     class GreenFilter extends RGBImageFilter
  43.     {
  44.         public GreenFilter()
  45.         {
  46.             canFilterIndexColorModel = true;
  47.         }
  48.         public int filterRGB(int x, int y, int rgb)
  49.         {
  50.             return (rgb & 0xff00ff00);
  51.         }
  52.     }
  53.     class BlueFilter extends RGBImageFilter
  54.     {
  55.         public BlueFilter()
  56.         {
  57.             canFilterIndexColorModel = true;
  58.         }
  59.         public int filterRGB(int x, int y, int rgb)
  60.         {
  61.             return (rgb & 0xff0000ff);
  62.         }
  63.     }
  64.     class GrayFilter extends RGBImageFilter
  65.     {
  66.         public GrayFilter()
  67.         {
  68.             canFilterIndexColorModel = true;
  69.         }
  70.         public int filterRGB(int x, int y, int rgb)
  71.         {
  72.             int gray = (int)(((rgb & 0x00ff0000)>>16)*0.3 + ((rgb & 0x0000ff00)>>8)*0.59 + (rgb & 0x000000ff)*0.11);
  73.             return (rgb & 0xff000000)+(gray<<16)+(gray<<8)+gray;
  74.         } 
  75.     }
  76. }
复制代码

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多