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个字节都是用来存储图像信息,包括图像宽度、高度、大小等等,因此可以构建图像信息类来读取并存储图像的信息。
- public class ImageHead
- {
- private int width;
- private int height;
- private int bitcount;
- private int size;
- public ImageHead(FileInputStream stream)
- {
- try
- {
- byte bh[] = new byte[bfhead];
- byte bi[] = new byte[bfinfo];
- stream.read(bh, 0, bfhead);
- stream.read(bi, 0, bfinfo);
- //图像宽度
- width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
- | ( ( (int) bi[6] & 0xff) << 16)
- | ( ( (int) bi[5] & 0xff) << 8)
- | (int) bi[4] & 0xff;
- //图像高度
- height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
- | ( ( (int) bi[10] & 0xff) << 16)
- | ( ( (int) bi[9] & 0xff) << 8)
- | (int) bi[8] & 0xff;
- //图像位数
- bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
- //图像大小
- size = ( ( (int) bi[23] & 0xff) << 24)
- | ( ( (int) bi[22] & 0xff) << 16)
- | ( ( (int) bi[21] & 0xff) << 8)
- | (int) bi[20] & 0xff;
- }
- catch (Exception e)
- {
- e.printStackTrace(System.out);
- }
- }
- }
复制代码 2.1.2 构建位数组 由于像素使用的字节若不是4的倍数,则会自动扩大,由此产生空白。因此我们需要在一开始计算出空白的大小,即
- int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
复制代码
由此构建数组如下
- 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生成图像:
- Toolkit kit = Toolkit.getDefaultToolkit();
- 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将图像“画”到其中:
- BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
- Graphics2D g2 = bi.createGraphics();
- g2.drawImage(image, 0, 0, null);
- g2.dispose();
复制代码
最后使用ImageIO写入
- ImageIO.write(bi, "jpg", imgFile);
复制代码 | 自己写的ImageIO类
- public class MyImageIO implements IImageIO
- {
- private static int bfhead = 14;
- private static int bfinfo = 40;
- public class ImageHead
- {
- private int width;
- private int height;
- private int bitcount;
- private int size;
- public ImageHead(FileInputStream stream)
- {
- try
- {
- byte bh[] = new byte[bfhead];
- byte bi[] = new byte[bfinfo];
- stream.read(bh, 0, bfhead);
- stream.read(bi, 0, bfinfo);
- width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
- | ( ( (int) bi[6] & 0xff) << 16)
- | ( ( (int) bi[5] & 0xff) << 8)
- | (int) bi[4] & 0xff;
- height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
- | ( ( (int) bi[10] & 0xff) << 16)
- | ( ( (int) bi[9] & 0xff) << 8)
- | (int) bi[8] & 0xff;
- bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
- size = ( ( (int) bi[23] & 0xff) << 24)
- | ( ( (int) bi[22] & 0xff) << 16)
- | ( ( (int) bi[21] & 0xff) << 8)
- | (int) bi[20] & 0xff;
- }
- catch (Exception e)
- {
- e.printStackTrace(System.out);
- }
- }
- }
- public Image myRead(String filePath)
- {
- try
- {
- Image image;
- FileInputStream stream = new FileInputStream(filePath);
- ImageHead img = new ImageHead(stream);
- int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
- int data[] = new int[img.height * img.width];
- byte brgb[] = new byte[ (img.width + blank) * 3 * img.height];
- if (img.bitcount == 24)
- {
- stream.read(brgb, 0, (img.width + blank) * 3 * img.height);
- int nindex = 0;
- for (int j = 0; j < img.height; j++)
- {
- for (int i = 0; i < img.width; i++)
- {
- data[img.width * (img.height - j - 1) + i] =
- (255 & 0xff) << 24
- | ( ( (int) brgb[nindex + 2] & 0xff) << 16)
- | ( ( (int) brgb[nindex + 1] & 0xff) << 8)
- | (int) brgb[nindex] & 0xff;
- nindex += 3;
- }
- nindex += blank;
- }
- }
- Toolkit kit = Toolkit.getDefaultToolkit();
- image = kit.createImage(new MemoryImageSource(img.width, img.height, data, 0, img.width));
- return image;
- }
- catch (Exception e)
- {
- e.printStackTrace(System.out);
- }
- return (Image)null;
- }
- public Image myWrite(Image image, String filePath)
- {
- try
- {
- File imgFile = new File(filePath + ".jpg");
- BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
- Graphics2D g2 = bi.createGraphics();
- g2.drawImage(image, 0, 0, null);
- g2.dispose();
- ImageIO.write(bi, "jpg", imgFile);
- return image;
- }
- catch (Exception e)
- {
- e.printStackTrace(System.out);
- }
- return image;
- }
- }
复制代码ImageProcess 图像处理,包括RGB单通道颜色以及灰度
- public class ImageProcessor implements IImageProcessor
- {
- public Image showChanelR(Image sourceImage)
- {
- RedFilter filter = new RedFilter();
- Toolkit kit = Toolkit.getDefaultToolkit();
- Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
- return newimg;
- }
- public Image showChanelG(Image sourceImage)
- {
- GreenFilter filter = new GreenFilter();
- Toolkit kit = Toolkit.getDefaultToolkit();
- Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
- return newimg;
- }
- public Image showChanelB(Image sourceImage)
- {
- BlueFilter filter = new BlueFilter();
- Toolkit kit = Toolkit.getDefaultToolkit();
- Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
- return newimg;
- }
- public Image showGray(Image sourceImage)
- {
- GrayFilter filter = new GrayFilter();
- Toolkit kit = Toolkit.getDefaultToolkit();
- Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
- return newimg;
- }
- class RedFilter extends RGBImageFilter
- {
- public RedFilter()
- {
- canFilterIndexColorModel = true;
- }
- public int filterRGB(int x, int y, int rgb)
- {
- return (rgb & 0xffff0000);
- }
- }
- class GreenFilter extends RGBImageFilter
- {
- public GreenFilter()
- {
- canFilterIndexColorModel = true;
- }
- public int filterRGB(int x, int y, int rgb)
- {
- return (rgb & 0xff00ff00);
- }
- }
- class BlueFilter extends RGBImageFilter
- {
- public BlueFilter()
- {
- canFilterIndexColorModel = true;
- }
- public int filterRGB(int x, int y, int rgb)
- {
- return (rgb & 0xff0000ff);
- }
- }
- class GrayFilter extends RGBImageFilter
- {
- public GrayFilter()
- {
- canFilterIndexColorModel = true;
- }
- public int filterRGB(int x, int y, int rgb)
- {
- int gray = (int)(((rgb & 0x00ff0000)>>16)*0.3 + ((rgb & 0x0000ff00)>>8)*0.59 + (rgb & 0x000000ff)*0.11);
- return (rgb & 0xff000000)+(gray<<16)+(gray<<8)+gray;
- }
- }
- }
复制代码
|