曾几何时,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:

  • 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中图像的放射变换,欢迎大家持续关注。




Java 图像处理(一)的更多相关文章

  1. Java 图像处理框架-Marvin

    网上看到,摘录过来的,暂时还没涉足这方面的东西 Marvin 1.4.5 的插件接口支持处理多个图像作为输入,新的插件可通过多个图片来确认背景,新的插件可使用多个图片来合并相同场景. Marvin 是 ...

  2. Java图像处理最快技术:ImageJ 学习第一篇

    ImageJ是世界上最快的纯Java的图像处理程序. 它能够过滤一个2048x2048的图像在0.1秒内(*). 这是每秒40万像素!ImageJ的扩展通过使用内置的文本编辑器和Java编译器的Ima ...

  3. Atitit. 图像处理jpg图片的压缩 清理垃圾图片 java版本

    Atitit. 图像处理jpg图片的压缩  清理垃圾图片 java版本 1. 清理图片压缩图片尺寸 1 2. 所以要使用ImageWriter 1 3. Thumbnails质量压缩builder.o ...

  4. atitit.验证码识别step3----去除边框---- 图像处理类库 attilax总结java版本

    atitit.验证码识别step3----去除边框---- 图像处理类库 attilax总结java版本 1. 去除边框思路原理 1 2. Thumbnailator 是一个用来生成图像缩略图.裁切. ...

  5. JAVA上百实例源码以及开源项目

    简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级.中级.高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情.执着,对IT的憧憬. ...

  6. 优秀java开源项目与解决方案推荐与概论

    http://www.oschina.net/project/lang/19/java http://www.open-open.com/ http://java-source.net/ https: ...

  7. 两个月的Java实习结束,继续努力

    前言 只有光头才能变强 2018年8月30日,今天我辞职了.在6月25号入职,到现在也有两个月时间了. 感受: 第一天是期待的:第一次将项目拉到本地上看的时候,代码很多,有非常多的模块,模块下又有da ...

  8. JAVA上百实例源码网站

    JAVA源码包1JAVA源码包2JAVA源码包3JAVA源码包4 JAVA开源包1 JAVA开源包2 JAVA开源包3 JAVA开源包4 JAVA开源包5 JAVA开源包6 JAVA开源包7 JAVA ...

  9. JAVA图像缩放处理

    http://www.blogjava.net/kinkding/archive/2009/05/23/277552.html ———————————————————————————————————— ...

随机推荐

  1. 嵌入式Linux应用开发完全手册之环境搭建

    @ 目录 0.下载源配置 1.电脑BIOS启动虚拟化 2.linux网卡查看与IP设置 3.windows NAT虚拟网络配置 4.修改 Ubuntu 的 mountd 端口 5.vim设置 6.Mo ...

  2. django之model,crm操作

    一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 pr ...

  3. jinja2.exceptions.TemplateNotFound 报错处理

    一.检查模板文件夹是否正确. 遇到这个问题,首先需要检查你的模板文件夹命名是否规范,Flask默认会在工程下寻找templates文件夹,这个是默认配置,不能写成template或者其他名字.当然,如 ...

  4. Prometheus+alertmanager告警配置-2

    prometheus 告警 prometheus 通过alertmanager进行告警 实现监控告警的步骤: 在prometheus中定义告警规则rule_files alertmanager配置告警 ...

  5. 请写出你最常见到的5个runtime exception?

    所谓系统异常,就是-..,它们都是RuntimeException的子类,在jdk doc中查RuntimeException类,就可以看到其所有的子类列表,也就是看到了所有的系统异常.我比较有印象的 ...

  6. SpringBoot 日志

    springboot日志简介 SpringBoot使用的日志是sl4j + logback,sl4j是抽象层,不做具体的实现.实现主要是logback来做.SpringBoot同时也整合了其他框架的日 ...

  7. Hashmap如何同步?

    当我们需要一个同步的HashMap时,有两种选择: ●使用Collections.synchronizedMap(..)来同步HashMap. ●使用ConcurrentHashMap的 这两个选项之 ...

  8. redis 为什么是单线程的?

    一.Redis为什么是单线程的? 因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽.既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理 ...

  9. 学习FastDfs(三)

    FASTDFS是什么 FastDFS是由国人余庆所开发,其项目地址:https://github.com/happyfish100 FastDFS是一个轻量级的开源分布式文件系统,主要解决了大容量的文 ...

  10. 深入理解FIFO(包含有FIFO深度的解释)

    FIFO: 一.先入先出队列(First Input First Output,FIFO)这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令. 1.什么是FIFO? FIFO是 ...