Standard Widget Toolkit ( SWT ,标准窗口小部件工具箱),是在 Eclipse 平台上使用的窗口小部件工具箱,它能向开发者提供和本机平台一致的用户界面和比较稳定的性能,也提供了强大的图像处理功能。本文首先介绍 SWT 封装的 Image , ImageData 等类,接着根据作者实际工作经验给出了一些常见图像处理的解决方法。
SWT 图像处理入门
Standard Widget Toolkit ( SWT,标准窗口小部件工具箱),是在 Eclipse 平台上使用的窗口小部件工具箱,它能向开发者提供和本机平台一致的用户界面和比较稳定的性能,也提供了强大的图像处理功能。本文首先介绍 SWT 封装的 Image, ImageData 等类,接着根据作者实际工作经验给出了一些常见图像处理的解决方法。
![]() ![]() |
SWT Images简介
软件开发人员可以利用 SWT 封装的 Image, ImageData 等类来创建图像、存储图像数据,也可以对存储的图像数据进行各种图像变换。本文将演示如何正确的使用 Image, ImageData 等类,以及如何使图像变灰、变亮/黑、图像旋转、图像拉伸、图片透明叠加、图片反色等相关问题。
下面就来介绍一下 Image 和 ImageData 这两个在 SWT Images 中最重要的类。
类 org.eclipse.swt.graphics.Image 被用来表示可以在设备上显示的图片,可以用方法如GC.drawImage() 或者 Button.setImage() 等来将它显示出来。Image 类提供了几个构造函数,可以完成以下功能:
类 org.eclipse.swt.graphics.ImageData 中存储了图像的像素数据信息。 ImageData 是一个包含有关图像大小、调色板、颜色值和透明度等信息的类。我们可以对这些图像像素数据可以直接读或者写操作,这意味着可以通过直接读取或者修改图像的 数据,来设置或者取得图像中任何像素或者任何一组像素的颜色值。关于 ImageData ,我们还应当了解以下一些字段:
![]() ![]() |
SWT图象处理
常见的图象处理包含图象的读/写、图像变灰、变亮/黑、图像旋转、图像拉伸、图片透明叠加、图片反色等。下面将就这些问题逐个介绍,表 1 列出了各个清单所对应的图像处理。
表 1. 示例代码清单
代码清单 | 图像处理类型 |
清单 1 | 图象的读写 |
清单 2 | 图像变灰 |
清单 3 | 图像变亮/变黑 |
清单 4 | 图像旋转 |
清单 5 | 图像反色 |
清单 6 | 图像拉伸 |
清单 7 | 图片透明叠加 |
图像的读写
我们可以使用类 org.eclipse.swt.graphics.ImageLoader 来加载或者保存图像。 ImageLoader 具有一个全局的成员变量 ImageData[],它用于存储图片数据。
清单 1. 图像读写示例
String fileName = "source.jpg"; String saveName = "saved.jpg"; ImageLoader loader = new ImageLoader(); ImageData[] imageData = loader.load(fileName); if(imageData.length > 0){ Image newImage = new Image(null, imageData[0]); //对newImage进行操作 ... loader.data[0] = newImage.getImageData(); loader.save(saveName, SWT.IMAGE_BMP); } |
图像变灰
图像变灰在桌面应用程序中有着广泛的应用。例如,一个图标被作为一个按钮的背景,我们需要一个灰色效果的图标作为按钮的背景来表示这个按钮处于禁用 状态。在SWT中,基于已经存在的图像来创建一个具有灰色效果的图像,我们可以使用构造函数 Image(Display display, Image image, int flag) 来创建,其中参数 flag 使用 SWT.IMAGE_GRAY。
清单2. 图像变灰示例
Image newImage = new Image(null, image, SWT.IMAGE_GRAY); |
图像变亮/变黑
下面讨论图像变亮/变黑。 RGB 和 HSL (也叫 HSB/HSV )是两种色彩空间,即:红、绿、蓝( Red, Green, Blue) 和色调、饱和度、亮度( Hue, Saturation, Lightness 或 Brightness 或 Value),前者适用于机器采样,目前的显示器颜色即由这三种基色构成,而后者更符合人类的直观感觉。在 Windows 的标准颜色对话框中均包含这两种表示方法。 RGB 的取值范围在 0~255 之间, HSL 的取值在 0~1 之间。因此我们只需要将 HSL 空间数据的 L 分量进行调整即可调整此图像的亮度。要实现图像变亮/变黑的功能,只需要调整清单 3 中函数 lightImage 行(*)中等号右边的值( 0 到 1 之间)。
清单 3. 图像变亮示例
private static ImageData lightImage(ImageData srcData) { double[] data = rgbTohsl(srcData.data); byte[] newData = new byte[srcData.data.length]; int bytesPerPixel = srcData.bytesPerLine / srcData.width; int destBytesPerLine = srcData.width * bytesPerPixel; for(int i = 0; i < data.length; i += 3) { data[i + 2] = 0.75; ----------------- (*) } data = hslTorgb(data); for(int i = 0; i < srcData.data.length; i ++) { newData[i] = (byte)data[i]; } ImageData newImageData = new ImageData(srcData.width, srcData.height, srcData.depth,srcData.palette, destBytesPerLine, newData); return newImageData; } |
其中,方法 double[] rgbTohsl(byte[] data) 是把 RGB 空间数据转换到 HSL 空间;相反的,方法 double[] hslTorgb(double[] data) 是把数据从 HSL 空间转换到 RGB 空间。
图像旋转
清单4中方法 rotate 实现了将图像相左旋转 90 度。如图 1 ,对于像素点 (x, y) ,向左旋转90 度以后,它在图象中的位置变成了 (y, width - x - 1) 。因此,相左旋转 90 度即将所有的像素点按照规则换一下位置。其他的旋转可用同样的方法。
图1 旋转前与相左旋转 90 度后
清单4. 图像旋转示例
private static ImageData rotate(ImageData srcData) { int bytesPerPixel = srcData.bytesPerLine / srcData.width; int destBytesPerLine = srcData.height * bytesPerPixel; byte[] newData = new byte[srcData.data.length]; int width = 0, height = 0; for (int srcY = 0; srcY < srcData.height; srcY++) { for (int srcX = 0; srcX < srcData.width; srcX++) { int destX = 0, destY = 0, destIndex = 0, srcIndex = 0; destX = srcY; destY = srcData.width - srcX - 1; width = srcData.height; height = srcData.width; destIndex = (destY * destBytesPerLine) + (destX * bytesPerPixel); srcIndex = (srcY * srcData.bytesPerLine) + (srcX * bytesPerPixel); System.arraycopy(srcData.data, srcIndex, newData, destIndex, bytesPerPixel); } } return new ImageData(width, height, srcData.depth, srcData.palette, destBytesPerLine, newData); } |
图像反色
对于彩色图像的 R、G、B 各彩色分量取反的技术就是图像的反色处理,这在处理二值化图像的连通区域选取的时候非常重要。如物体连通域用黑色表示,而二值化后的物体连通域图像可那是 白色的,而背景是黑色的,这时应手动选取图像的反色处理或有程序根据背景和物体连通域两种颜色的数量所占比例而自动选择是否选择选取图像的反色处理,其算 法很简单,假设源图像一像素的红,绿,蓝分量为 (R,G,B),则目标图像该像素的红绿蓝分量应变为 (255 - R,255 - G, 255 - B)。
清单5. 图像反色示例
private static ImageData reverseImage(ImageData srcData) { int bytesPerPixel = srcData.bytesPerLine / srcData.width; int destBytesPerLine = srcData.width * bytesPerPixel; byte[] newData = srcData.data; for (int i = 0; i < newData.length; i ++) newData[i] = (byte) (255 - newData[i]); ImageData newImageData = new ImageData(srcData.width, srcData.height, srcData.depth, srcData.palette, destBytesPerLine, newData); newImageData.transparentPixel = srcData.transparentPixel; return newImageData; } |
图像拉伸
图像的缩小/放大一般分为按比例缩小和不按比例缩小两种。图像的缩小操作中,是在现有的信息里如何挑选所需要的有用信息。图像的放大操作中,则需对 尺寸放大后所多出来的空格填入适当的值,这是信息的估计问题,所以较图像的缩小要难一些,而且图像大比例放大时经常会出现马赛克效应。庆幸的是,SWT 工具箱对图像的拉伸进行了封装,开发者只需要调用方法 ImageData.scaledTo(int width, int height) 来获得一个拉伸后的 ImageData。
清单6. 图像拉伸示例
Image newImage = new Image(null, imageData[0].scaledTo(imageData[0].width / 2, imageData[0].height / 2)); |
图片透明叠加
透明叠加方式是图象处理中常用的一种处理方式,在这种处理方式中,一幅图片叠加到另一幅图片上,但是这幅图象不是完全将原来的图象覆盖,而是能够部 分的透过叠加的图象显示出来,透明的程度由透明度参数指定(假定为 a,其值在 0 与 1 之间,数值越小表明被叠加的图片越透明),其原理是目标图片的 R、G、B 以及 alpha 分别为待叠加图片 1 的 R、G、B 以及 alpha 分量乘以透明度参数 a 加上待叠加图片 2 的 R、G、B 以及 alpha 分量乘以 1-a 的值。我们可以使用图片的透明叠加作出水印的效果。
清单7. 图像透明叠加示例
private static ImageData watermark(ImageData srcData1, ImageData srcData2, double alpha) { if(srcData1.width != srcData2.width || srcData1.height != srcData2.height || rcData1.bytesPerLine != srcData2.bytesPerLine) //未考虑不同大小图片的叠加 return null; int bytesPerPixe = srcData1.bytesPerLine / srcData1.width; int destBytesPerLine = srcData1.width * bytesPerPixe; byte[] newData = new byte[srcData1.data.length]; ImageData newImageData = new ImageData(srcData1.width, srcData1.height, srcData1.depth, srcData1.palette, destBytesPerLine, newData); for (int srcY = 0; srcY < srcData1.height; srcY++) { for (int srcX = 0; srcX < srcData1.bytesPerLine; srcX++) { int idx = srcY * srcData1.bytesPerLine + srcX; newImageData.data[idx] = (byte)(alpha * srcData1.data[idx] + (1- alpha) * srcData2.data[idx]); } } return newImageData; } |
需要说明的是,以上所列举的清单中大部分都没有对透明度数据进行处理,读者如对带有透明度数据图片进行处理的时候,可自行添加相关代码,其处理过程跟对 ImageData 数据处理过程类似。
![]() ![]() |
结论
从上面的介绍中,可以知道 SWT 对 Image 的支持非常好,开发者可以方便的对图象进行各种操作。对于想用 Java 来进行图像处理的编程人员来说, SWT Images 是一个不可多得选择。