• Java 图像处理(一)


      曾几何时,Java图像处理已经被认为是太过鸡肋,就连Java的创始公司,在java图像处理方面也是浅尝辄止,可能相比较C++,Java在这方面的处理,确实差强人意。

    不过Java类库中有一个叫JAI的库,全程是java advanced image—Java高级预想处理,其实个人觉得这个库非常丰富,奈何JAI只发行了2个版本就停止维护了,

    到现在也没有找到源码,资料更是少的可怜。鉴于上述原因,本人将开始记录JAI以及Java 二维图像相关知识,本文主要介绍Java图像的主要类以及图像基础知识。

      Java中我们对图像的操纵一般使用BufferImage,比如我们一般会使用一下方法,将一个图片文件读取到bufferimage

    BufferedImage image = ImageIO.read(new File("D:\\Gis开发\\数据\\影像数据\\tiff\\china.tif"));

            这个是将已经存在的图片文件,读取到BufferedImage中,其实大家都知道图像之所以会呈现出各种颜色,无外乎就是像素值、颜色模型、样本模型这三个重要参数来体现的。其实Java的图像类

    BufferedImage也无外乎这三个重要参数。
    比如我们通过BufferedImage构造参数就可以发现,其中一个构造参数是
    public BufferedImage (ColorModel cm,
                          WritableRaster raster,
                          boolean isRasterPremultiplied,
                          Hashtable<?,?> properties)

     这个构造参数中,ColorModel是颜色模型,raster是栅格数据,它是由像素值和样本模型构成的,这个我们可以通过它的构造函数看到

    protected WritableRaster(SampleModel sampleModel,
                             DataBuffer dataBuffer,
                             Point origin) 

    其中sampleModel是样例模型,dataBuffer是像素值数组。

    下面介绍以上三个要素:

    • ColorModel

    Java中ColorModel的实现类主要有ComponentColorModel、IndexColorModel等,我们先来看看ComponentColorModel构造函数

    复制代码
    public ComponentColorModel (ColorSpace colorSpace,
                                    boolean hasAlpha,
                                    boolean isAlphaPremultiplied,
                                    int transparency,
                                    int transferType) 
    复制代码

    其中colorSpace很重要,颜色空间其实决定了最终这些像素值是如何呈现在我们硬件上的,比如我们的电脑显示器,印刷等。

    比如常见以下颜色空间:

    复制代码
    RGB彩色模型
    @Native public static final int TYPE_RGB = 5; 
    灰度模型
    @Native public static final int TYPE_GRAY = 6
    CMYK彩色模型
    @Native public static final int TYPE_CMYK = 9;
    复制代码

    比如我们通常的彩色图是用 TYPE_RGB,创建灰度图用TYPE_GRAY,以及TYPE_CMYK颜色模型。

    hasAlpha:是否有透明通道,比如常见的png(32),就有alpha通道  

    isAlphaPremultiplied:  这是处理透明的一个参数(相对深奥,后面会详细研究)

    transparency:  透明类型    其中1表示完全不透明  2表示完全透明或不透明  3表示介于两者之间,也就是透明度可调(一般选择3)

    transferType:   就是像素的数据类型,跟下面的dataType我认为是一样的

    • SampleModel
    Java中sampleModel的实现类主要有ComponentSampleModel以及它的子类PixelInterleavedSampleModel,我们来看看它的构造函数
    public ComponentSampleModel(int dataType,
                                    int w, int h,
                                    int pixelStride,
                                    int scanlineStride,int bandOffsets[])

    其中datatype:数据类型,即就是像素值的表示单位,比如常见的RGB三通道,使用TYPE_BYTE来表示,即就是每个通道8位,用0-255来表示,常见的DEM地形数据,也会直接使用TYPE_SHORT或者TYPE_FLOAT来定义。

    w:  图片宽度 

    h:  图片高度

    pixelStride:像素步幅,其实就是我们的像素在宽和高方向的间隔设置,通常设置为1,表示每个像素都会填充一个值,如果设置为2,则表示每2个位置设置一个像素值,这样其中的databuffer数组就会相应的缩减。

    scanlineStride:  线性步幅,如果pixelStride为1,则scanlineStride为width。

    bandOffsets:波段偏移量,一般都是0,比如RGB数据,一般都是new int[] {0,0,0}

    • 像素值

    像素值其实就是表示颜色的数字,这里提示一点,比如RGB数据,如果数据类型是TYPE_BYTE,如果图片是10x10大小,则这个DataBufferByte的数组大小就是10*10*3。

    下面我们来自定义一个图片:

    复制代码
    byte[] rasterBuffer = new byte[10*10*3];
    DataBufferByte dataBuffer = new DataBufferByte(rasterBuffer, 10*10*3);
    ColorSpace space = ColorSpace.getInstance(ColorSpace.CS_GRAY);
    ComponentSampleModel sampleModle = new ComponentSampleModel(DataBuffer.TYPE_BYTE,10, 10, 1, 10*3, new int[] {0,1,2});
    int[] bits = {8,8,8};
    ComponentColorModel colorModel = new ComponentColorModel(space, bits, false, false, Transparency.TRANSLUCENT,DataBuffer.TYPE_BYTE);
    WritableRaster raster = Raster.createWritableRaster(sampleModle,dataBuffer,new Point(0,0));
    BufferedImage image = new BufferedImage(colorModel,raster,false,null); 
    复制代码

     其实在日常开发中,我们经常会遇到ComponentColorModel,但是偶尔也会遇到IndexColorModel,这两个颜色模型有什么区别呢?

     自己找了一个这样的数据,解析后发现,如下操作

    从这个输出可以看出,图像的是IndexColorModel和普通ComponentColorModel是一样的,唯一不同的是rgb的数组大小不一样,下面我们来看看对应的samplemodel

     可以看出虽然colorModel有3通道,但实际samplemodel的band只有一个,也就是说实际只有一个samplebands

    这也就解是了原本按照三通道的样本,该数据的databuffer应该是7162*5968*3    而实际它的databuffer的size只有

    7162*5968,也就是上图中的data的size大小,这跟我们平时看到的ComponentColorModel的data不一样,也就是用一位byte就表示了三个通道的颜色分量。

     扩展

     一般对于图像显示而言,我们拿到每个通道的颜色分量,其实还是需要转为显示器等输出设备可以识别的,这个我们可以通过ColorModel的getRGB()方法,我们来看下这个方法

    复制代码
    public int getRGB(int pixel) {
    if (numComponents > 1) {
    throw new
    IllegalArgumentException("More than one component per pixel");
    }
    if (signed) {
    throw new
    IllegalArgumentException("Component value is signed");
    }

    return (getAlpha(pixel) << 24)
    | (getRed(pixel) << 16)
    | (getGreen(pixel) << 8)
    | (getBlue(pixel) << 0);
    }
    复制代码

     可以看出是通过三通道的分量的位运算获得最后的像素值,而IndexColorModel的getRGB()我们来看下

    final public int getRGB(int pixel) {
            return rgb[pixel & pixel_mask];
        }

    明显只有一个像素来计算最后的整数像素值。

     

    总结

          好了今天就简单介绍Java图像处理的基础操作,后续还将持续介绍一些实用的图像处理方法,下一篇将介绍Java中图像的放射变换,欢迎大家持续关注。

    
    


     

  • 相关阅读:
    文件共享服务器(cifs协议 -- 微软开发)
    Clickhouse相关 LSM
    网络中冗余备份
    怎样提升小程序日活?签到抽奖可行吗?
    vmpalyer虚拟机的使用教程,小白也能看懂
    windows线程同步与互斥
    南大通用GBase8s 常用SQL语句(260)
    尚医通 (五) --------- 医院模块
    ThemeForest – Canvas 7.2.0 – 多用途 HTML5 模板
    Java基础 —— 项目一:ATM存取款系统
  • 原文地址:https://www.cnblogs.com/share-gis/p/15937945.html