Java图像基础知识

前言

提起java的图像处理,可能很多人都觉的java不太适合这方面的业务,毕竟很多图形学和图像处理都是基于C或者C++来实现的,比如OpenCV的2D图像处理、Matlab的图像处理、OpenGL的2D和3D的图形和图像的渲染等。原因主要是这些底层语言在处理图像时有着先天性的优势,就是可调用GPU资源来加速图像的处理。

而Java语言明显不具备这个能力,但是如果我们的场景本身比较小,不需要大批量的渲染加载,只是简单的处理计算,对性能没有要求的,那么使用Java来处理图形和图像的相关业务也是可以的。

提到Java的图像处理,第一时间想到的就是Java的awt包下提供的图形和图像的处理类,除此之外,前面的文章中我们曾经提到的一个java的图像处理库JAI,全称是java advanced image,奈何这个库只发行了2个版本就停止,不过好在后面又有大佬维护了一个jai-ext的java图像库。

本篇文章主要介绍下java图像处理过程中的一些基础知识。

基础知识

像素:像素是组成图像的基础单位,我们把一张图片无限放大,看到的每一个小格子就

是一个像素。比如一张图片768* 512,则表示图片宽度768个像素,高度是512个像素。而在GIS中计算分辨率时,总是会提到一个DPI的值,这个值在Arcgis中为96,在OGC标准中一般取91,指的是每英寸有多少个像素,这个值可保证客户端的比例尺与服务端图像的比例尺一致。

颜色空间(ColorSpace):颜色空间是一个抽象数学模型,用于描述颜色的属性和范围

它定义了颜色值的表示方式以及这些值如何映射到视觉感知,其实决定了最终这些像素值是如何呈现在我们硬件上的,比如我们的电脑显示器,印刷等。

常见的颜色空间

//RBG空间

@Native public static final int TYPE_RGB = 5;

//灰度空间

@Native public static final int TYPE_GRAY = 6;

//hsv空间(色相、饱和度、明度)

@Native public static final int TYPE_HSV = 7;

//HLS空间(色相、亮度、饱和度)

@Native public static final int TYPE_HLS = 8;

//打印模式的颜色空间

@Native public static final int TYPE_CMYK = 9;

颜色模型:有了颜色空间后,我们就需要一个类将像素值和颜色值对应起来,这就是

ColorModel(颜色模型),java提供了多中颜色模型的实现类,主要区别是像素值是直接存储RGB值还是存储索引值,其中ComponentColorModel 是直接基于像素值的颜色模型,IndexColorModel 是存储索引值,然后通过在调色板中查找来获取最终的颜色值。

下面我们重点看下ComponentColorModel 的构造函数,来深入了解下这个类的使用

其构造函数有五个参数,分别是:

colorSpace:颜色空间,前面介绍过了。

bits:位深数组,表示每一个通道的占用的bit位数,这个值越大,代表最后的像素值越大,色彩值越丰富,能够表示的色彩就越细腻,比如常见的三通道8位,能表示的色彩值最大255*255*255。

hasAlpha:是否有alpha通道

isAlphaPremultiplied:这是处理透明的一个参数

transparency: 透明类型 ,其中1表示完全不透明 2表示完全透明3表示介于两者之间,也就是透明度可调。

transferType: 像素的数据类型,比如可以是DataBuffer.TYPE_BYTE、DataBuffer.TYPE_INT、DataBuffer.TYPE_SHORT、DataBuffer.TYPE_FLOAT等

IndexColorModel适合于颜色数量有限且已知的情况,通过较小的索引值就可以高效地表示大量像素,从而节省内存空间,一般用于网页图形和压缩图像格式中。

下面介绍另一个重要参数SampleModel:该参数定义像素数据的组织结构、存储模式、样本的排列顺序和访问规则,它和上面的ColorModel一起决定了图像的最终显示效果。

其实现类最常用的ComponentSampleModel其构造参数如下:

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

w: 图片宽度

h: 图片高度

pixelStride:像素步幅,也就是采样间隔,一般都是numBands,比如三通道图像就是3,也就是像素数组中每三个数据代表一个像素的值。

scanlineStride: 线性步幅,表示切换到下一行的像素时,数组的位置变换,一般是numBands*width

bandOffsets:波段偏移量,一般都是从0开始,表示每个像素步幅在通道上的偏移量,比如RGB数据,一般都是new int[] {0,1,2}

介绍了上面的几个参数后,那么使用Java来创建一个图像就只差一步了,就是构造一个像素数组,这个数组的构造和前面的像素类型有关,比如要创建768*512大小的图片,颜色模型TYPE_BYTE的数据类型,则需要创建一个大小为768*512*3大小的byte数组。

接下来我们来看下根据以上参数,构造一个BufferedImage对象

/**

* 图像基础知识

*/

public class ImageProcess {

@Test

public void createImage(){

int width = 768;

int height = 512;

ColorModel colorModel = buildColorModel(DataBuffer.TYPE_BYTE);

SampleModel sampleModel = buildSampleModel(DataBuffer.TYPE_BYTE,width,height);

//构造像素数组

int[] buffers = new int[width*height*3];

Random random = new Random();

for(int i=width*height;i<width*height*2;i++){

buffers[i] = random.nextInt(256);

}

//DataBuffer

DataBuffer dataBuffer = new DataBufferInt(buffers,width*height*3);

//创建像素

WritableRaster raster = Raster.createWritableRaster(sampleModel,dataBuffer,new Point(0,0));

//创建图像

BufferedImage image = new BufferedImage(colorModel,raster,false,null);

}

public ColorModel buildColorModel(int dataType){

ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);

int[] bits = {8,8,8};

ColorModel colorModel = new ComponentColorModel(colorSpace,bits,false,false,

Transparency.TRANSLUCENT, dataType);

return colorModel;

}

public SampleModel buildSampleModel(int dataType,int width,int height){

SampleModel sampleModel = new ComponentSampleModel(dataType, width,height,

3,width*3,new int[]{0,1,2});

return sampleModel;

}

}

好了今天关于Java图像的基础知识就介绍到这里,下一节将介绍Geotools以及JAI-EXT的开源库中对图像的处理方式,当然本文并未完全介绍java 2D图像的相关内容,篇幅有限,大家在过程中如有任何疑问,可在评论区交流。

相关文章

第十三章:Java图形用户界面编程

Java图形用户界面(Graphical User Interface,GUI)编程是一种创建交互式应用程序界面的技术。通过使用GUI,开发人员可以创建具有按钮、文本框、复选框等可视化组件的应用程序。...

java课程设计大作业 2048小游戏(设计实现文档+源代码)

目录一、 实现方案3二、 具体代码及程序框图分析4三、 参考资料14一、 实现方案本游戏采用Java语言编写,使用Eclipse编译器, jdk1.7.0_51编译环境。游戏的UI主要运用Java图形...

小高分享(63)Java中的图形、图像与音频

分享兴趣,传播快乐,增长见闻,留下美好!亲爱的您,这里是LearningYard新学苑。今天小编为你带来小高分享(63)Java中的图形、图像与音频欢迎您的访问!Share interests, sp...

Java-GUI编程之绘图

很多程序如各种小游戏都需要在窗口中绘制各种图形,除此之外,即使在开发JavaEE项目时,有时候也必须"动态"地向客户 端生成各种图形、图表,比如 图形验证码、统计图等,这都需要利用AW...

Java-GUI编程之处理位图

如果仅仅绘制一些简单的几何图形,程序的图形效果依然比较单调 。 AWT 也允许在组件上绘制位图, Graphics 提供了 drawlmage() 方法用于绘制位图,该方法需要一个Image参数一一代...

如何自学Java语言?

随着互联网的高速发展,越来越多的人开始学习Java,对于喜欢编程的朋友来说,Java是一门非常值得去学习的语言,那么Java语言应该怎么学呢?Java是一门面向对象编程语言,不仅吸收了C++语言的各种...