java中图像简单处理 博客分类: swtImage swt image io drag scroll
程序员文章站
2024-03-20 00:02:40
...
Java简单图像处理
Java图像格式转换
ImageIO 目前支持一下格式: BMP, JPG,PNG, JPEG, WBMP, GIF
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageIOTest {
public static void main(String args[]) throws IOException {
File inputFile = new File("c:\\11.jpg");
BufferedImage input = ImageIO.read(inputFile);
ImageIO.write(input, "GIF", outputFile);
//ImageIO.write(input, "JPEG", outputFile);
//ImageIO.write(input, "JPG", outputFile);
//ImageIO.write(input, "PNG", outputFile);
}
}
还可以使用JAI(sun公司java advanced imaging,三个重要的jar文件mlibwrapper_jar.jar、jar_codec.jar和jar_core.jar移到你的classpath环境变量指定的目录下。我们推荐把它们放到你的JDK的jre/lib/ext目录下。)jimi(sun公司)。
SWT图像介绍
这部分内容大多是以前从网上找的,出处不记得了,望原版见谅。
SWT Images简介
软件开发人员可以利用 SWT 封装的 Image, ImageData 等类来创建图像、存储图像数据,也可以对存储的图像数据进行各种图像变换。本文将演示如何正确的使用 Image, ImageData 等类,以及如何使图像变灰、变亮/黑、图像旋转、图像拉伸、图片透明叠加、图片反色等相关问题。
下面就来介绍一下 Image 和 ImageData 这两个在 SWT Images 中最重要的类。
类 org.eclipse.swt.graphics.Image 被用来表示可以在设备上显示的图片,可以用方法如GC.drawImage() 或者 Button.setImage() 等来将它显示出来。Image 类提供了几个构造函数,可以完成以下功能:
• 装载一个现有的图象。可以通过传入文件名或者 InputStream 作为参数,但是图象的格式必须是它所支持的格式之(目前 SWT Image 支持 BMP、GIF、JPG、PNG、Windows ICO 等格式)一,否则会抛出 SWTException 异常。
• 构造一个用已经存在的 ImageData 进行初始化的图像。
• 构造一个空图像。可以通过修改其像素值或者向它拷贝一个 SWT 图形上下文的内容 (GC) 来绘制该图像,并且可以指定空图像的大小。
类 org.eclipse.swt.graphics.ImageData 中存储了图像的像素数据信息。 ImageData 是一个包含有关图像大小、调色板、颜色值和透明度等信息的类。我们可以对这些图像像素数据可以直接读或者写操作,这意味着可以通过直接读取或者修改图像的数据,来设置或者取得图像中任何像素或者任何一组像素的颜色值。关于 ImageData ,我们还应当了解以下一些字段:
• width 和 height 指定图像的宽和高。Depth 指定图像的颜色深度。可能的值为 1、2、4、8、16、24 或者 32,指定编码每一个像素的值所使用的比特数。
• alpha 与 alphaData 定义图像的透明度。alpha 定义了图象的全局透明度值,默认值为 -1,并且alphaData 域将被忽略。当 alpha 不等于 -1 时, alphaData 存储了图象的透明度缓冲区,每个像素可以有一个在 0~255 之间的透明度值,数值越大,表示越不透明。值得注意的是,只有部分图象格式具有透明度,例如 GIF 和 PNG。
• palette 包含一个 PaletteData 对象,它存储有关图像的颜色模型的信息。SWT 的颜色模型可以是索引或者直接的,由palette的域 isDirect 来指定。如果颜色模型是索引的,那么 PaletteData 包含颜色索引,可以通过方法 getRGBs() 来获取 RGB 信息。如果它是直接的,那么它包含转换信息,表明应当如何从像素的整数值中提取出颜色 RGB 成分。
• data 包含像素值的字节缓冲区。字节编码的方法取决于所使用的颜色深度。对于一个 8 位的图像,数组中的一个字节正好表示图像中一个像素的值。对于 16 位图像,每一个像素值编码为缓冲区中的两个字节。这两个字节以最低有效字节顺序存储。对于 24 或者 32 位图像,每一个像素值以最高有效位字节顺序编码为缓冲区中的三个或者四个字节。
• bytesPerLine 表明缓冲区中有多少字节用于表示图像中一行像素的所有像素值。由于一个像素可能有多个字节表示,所以 bytesPerLine 可能是字段 width 值的若干倍。也就是说“一个像素扫描行上有多少个字节”,我们知道表示一个像素可能需要1,、3、4…n个字节等(分别对应256灰度图,24位真彩色等),因此,通过bytesPerPixel = bytesPerLine÷n就可以知道,一个扫描行上有多少个像素。我们将bytesPerPixel称为每个像素所占的字节数。
________________________________________
SWT图象处理
常见的图象处理包含图象的读/写、图像变灰、变亮/黑、图像旋转、图像拉伸、图片透明叠加、图片反色等。下面将就这些问题逐个介绍,表 1 列出了各个清单所对应的图像处理。
图像的读写
我们可以使用类 org.eclipse.swt.graphics.ImageLoader 来加载或者保存图像。 ImageLoader 具有一个全局的成员变量 ImageData[],它用于存储图片数据。
清单 1. 图像读写示例
图像可以直接得到
Image image = new Image(display, “e:/aa.jpg”);
我们还可以用ImageLoader得到(不仅能得到,还能保存为各种格式的图像文件,)
ImageLoader loader = new ImageLoader();
ImageData[] imgD = loader.load("icons/ipod.jpg");
if(imgD!=null&&imgD.length>0)
{
image = new Image(display, imgD[0]);
label.setImage(image);
loader.data[0] = image.getImageData();
loader.save("icons/qqq.png", SWT.IMAGE_PNG);
}
图像变灰
图像变灰在桌面应用程序中有着广泛的应用。例如,一个图标被作为一个按钮的背景,我们需要一个灰色效果的图标作为按钮的背景来表示这个按钮处于禁用状态。在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 度即将所有的像素点按照规则换一下位置。其他的旋转可用同样的方法。
旋转中心点为图形左下角,旋转90度的计算公式:
X’ = y;
y’= -x;
旋转中心点为图形左上角,旋转90度的计算公式:
X’ = -y;
y’= x;
旋转中心点为图形中心点,坐标为计算机平面坐标(左上角为(0,0)),旋转90度的计算公式:
X’ = y;
y’= width-x-1;
旋转中心点为图形中心点,坐标为左下角为(0,0),旋转90度的计算公式:
X’ = height –y -1;
y’= x;
图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 分别为待叠加图片A的 R、G、B 以及 alpha 分量乘以透明度参数 a 加上待叠加图片B的 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 || srcData1.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;
}24位真彩色图转为256色图(灰度图)
彩色图像转换为黑白图像时需要计算图像中每像素有效的亮度值,通过匹配像素亮度值可以轻松转换为黑白图像。
计算像素有效的亮度值可以使用下面的公式:
Y=0.3red+0.59green+0.11blue
然后使用 Color.FromArgb(Y,Y,Y) 来把计算后的值转换
转换代码可以使用下面的方法来实现:
按照以上同样的方法我们有:
public static Image convertToGrayscale(Image source )
{
if(source == null )return null;
ImageData ida = source.getImageData();
byte[] data2 = new byte[ida.data.length];
int offset = 0;
int k = 0;
int r, g,b,gray;
for(int i=0;i<ida.height;i++)
{
for(int j=0;j<ida.width;j++)
{
k = offset+j*3;
b = ida.data[k]&0xff;
g = ida.data[k + 1]&0xff;
r = ida.data[k + 2]&0xff;
gray = (int) (0.11*b + 0.59*g + 0.3*r);
data2[k]=data2[k+1]=data2[k+2]=(byte)gray;
}
offset += ida.bytesPerLine;
}
ImageData ida2 = new ImageData(ida.width, ida.height, ida.depth, ida.palette, ida.scanlinePad, data2);
Return new Image(source.getDevice(),ida2);
}
另外,我们也可以直接利用swt image在new 的时候指定flag来做到:
Image img1 = new Image(display,"E:/资料/小内容/Winter.jpg");
Image img2 = new Image(display,img1,SWT.IMAGE_GRAY);
Image的flag目前共有3个分别是SWT.IMAGE_GRAY, SWT.IMAGE_COPY, SWT.IMAGE_DISABLE。
经过与swt image中生成SWT.IMAGE_GRAY的计算方法。发现上面的清单有问题,具体再查。先这么着吧。
图像旋转/放大/移动的坐标对应
x = 1/ω * [x1*cos θ + y1*sinθ – (x0*cosθ + y0*sinθ)];
y = 1/ω * [y1*cosθ – x1*sinθ – (y0*cosθ - x0*sinθ)];
(x ,y)是原图中的点
(x1,y1)是视图窗口中的点
θ是旋转的角度
ω是放大倍数
(x0,y0)是平移时鼠标移动的偏移量
SWT_Image界面操作
图像拖动
public class DragImage
{
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.H_SCROLL | SWT.V_SCROLL);
final Composite composite = new Composite(shell, SWT.BORDER);
composite.setEnabled(false);
composite.setLayout(new FillLayout());
composite.setSize(700, 600);
final Color red = display.getSystemColor(SWT.COLOR_RED);
composite.addPaintListener(new PaintListener()
{
public void paintControl(PaintEvent e)
{
e.gc.setBackground(red);
e.gc.fillOval(5, 5, 690, 590);
}
});
final ScrollBar hBar = shell.getHorizontalBar();
hBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
Point location = composite.getLocation();
location.x = -hBar.getSelection();
composite.setLocation(location);
}
});
final ScrollBar vBar = shell.getVerticalBar();
vBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
Point location = composite.getLocation();
location.y = -vBar.getSelection();
composite.setLocation(location);
}
});
shell.addListener(SWT.Resize, new Listener()
{
public void handleEvent(Event e)
{
Point size = composite.getSize();
Rectangle rect = shell.getClientArea();
hBar.setMaximum(size.x);
vBar.setMaximum(size.y);
hBar.setThumb(Math.min(size.x, rect.width));
vBar.setThumb(Math.min(size.y, rect.height));
int hPage = size.x - rect.width;
int vPage = size.y - rect.height;
int hSelection = hBar.getSelection();
int vSelection = vBar.getSelection();
Point location = composite.getLocation();
if (hSelection >= hPage)
{
if (hPage <= 0)
hSelection = 0;
location.x = -hSelection;
}
if (vSelection >= vPage)
{
if (vPage <= 0)
vSelection = 0;
location.y = -vSelection;
}
composite.setLocation(location);
}
});
final Point[] offset = new Point[1];
Listener listener = new Listener()
{
public void handleEvent(Event event)
{
switch (event.type)
{
case SWT.MouseDown:
Rectangle rect = composite.getBounds();
if (rect.contains(event.x, event.y))
{
Point pt1 = composite.toDisplay(0, 0);
Point pt2 = shell.toDisplay(event.x, event.y);
offset[0] = new Point(pt2.x - pt1.x, pt2.y - pt1.y);
}
break;
case SWT.MouseMove:
if (offset[0] != null)
{
Point pt = offset[0];
composite.setLocation(event.x - pt.x, event.y - pt.y);
System.out.println("x : " + event.x + " y : " + event.y);
hBar.setSelection(pt.x - event.x);
vBar.setSelection(pt.y - event.y);
}
break;
case SWT.MouseUp:
offset[0] = null;
break;
}
}
};
shell.addListener(SWT.MouseDown, listener);
shell.addListener(SWT.MouseUp, listener);
shell.addListener(SWT.MouseMove, listener);
shell.setSize(600, 500);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
图像的几种显示
public class ImageProcesser
{
/*
* 图像按原始大小显示,当面板尺寸小于图像尺寸时,会出现滚动条
*/
public static void main(String[] args)
{
final Display display = Display.getDefault();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
FormToolkit formToolkit = new FormToolkit(display);
ScrolledForm scrolledForm = formToolkit.createScrolledForm(shell);
Composite container = scrolledForm.getBody();
GridLayout layout = new GridLayout(1, false);
container.setLayout(layout);
final Label label = new Label(container, SWT.NONE);
label.setLayoutData(new GridData(GridData.FILL_BOTH));
final Image image = new Image(display, "icons/ipod.jpg");
label.setImage(image);
shell.layout();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
if(image!=null)
{
image.dispose();
}
formToolkit.dispose();
}
/*
* 图像可以随canvas拉伸,图像会形变,不会出现滚动条
*/
// public static void main(String[] args) {
// Display display = Display.getDefault();
// Shell shell = new Shell(display);
// shell.setLayout(new GridLayout(1,false));
//
// final Canvas canvas = new Canvas(shell, SWT.DOUBLE_BUFFERED);
// canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
// final Image image = new Image(display, "icons/ipod.jpg");
// final int srcWidth = image.getImageData().width;
// final int srcHeight = image.getImageData().height;
//
// canvas.addPaintListener(new PaintListener() {
// public void paintControl(PaintEvent e) {
// Rectangle rect = canvas.getClientArea();
// Point p = new Point(rect.width,rect.height);
// e.gc.drawImage(image, 0, 0,srcWidth,srcHeight,0,0,p.x,p.y);
// }
// });
//
// shell.layout();
// shell.open();
// while (!shell.isDisposed()) {
// if (!display.readAndDispatch())
// display.sleep();
// }
// image.dispose();
// }
// /*
// * 图像“按比例”随面板大小形变(达到最适合面板效果),不会出现滚动条
// */
// public static void main(String[] args)
// {
// Display display = Display.getDefault();
// Shell shell = new Shell(display);
// shell.setLayout(new GridLayout(1, false));
//
// final Canvas canvas = new Canvas(shell, SWT.DOUBLE_BUFFERED);
// canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
// final Image image = new Image(display, "icons/ipod.jpg");
// final double srcWidth = image.getImageData().width;
// final double srcHeight = image.getImageData().height;
//
// canvas.addPaintListener(new PaintListener()
// {
// public void paintControl(PaintEvent e)
// {
// Rectangle rect = canvas.getClientArea();
// double areaWidth = rect.width;
// double areaHeight = rect.height;
//
// double xratio = (1.0*areaWidth)/(1.0*srcWidth);
// double yratio = (1.0*areaHeight)/(1.0*srcHeight);
//
// double ratio = xratio>=yratio?yratio:xratio;
//
// double destWidth = srcWidth * ratio;
// double destHeight = srcHeight * ratio;
//
// e.gc.setAntialias(SWT.ON);
// e.gc.drawImage(image, 0,0, (int) srcWidth,(int) srcHeight, 0,0, (int) destWidth,(int) destHeight);
// }
// });
//
// shell.layout();
// shell.open();
// while (!shell.isDisposed())
// {
// if (!display.readAndDispatch())
// display.sleep();
// }
// image.dispose();
// }
/*
* 面板大小不变,图形随放大缩小操作形变,会出现滚动条
*/
private static int cnt = 0;
// public static void main(String[] args)
// {
// final Display display = Display.getDefault();
// final Shell shell = new Shell(display);
// shell.setLayout(new GridLayout(1, true));
//
// FormToolkit formToolkit = new FormToolkit(display);
// final ScrolledForm scrolledForm = formToolkit.createScrolledForm(shell);
// scrolledForm.setLayoutData(new GridData(GridData.FILL_BOTH));
// Composite container = scrolledForm.getBody();
// container.setLayout(new FillLayout());
//
// final Label label = new Label(container, SWT.NONE);
// label.addMouseListener(new MouseAdapter()
// {
// @Override
// public void mouseUp(MouseEvent e)
// {
// scrolledForm.setFocus();
// }
// });
// final Image image = new Image(display, "icons/ipod.jpg");
// Image img = new Image(display, image.getImageData());
// label.setImage(img);
// final Composite comp = new Composite(shell, SWT.NONE);
// GridLayout layout = new GridLayout(5, false);
// comp.setLayout(layout);
// final Button btn1 = new Button(comp, SWT.PUSH);
// btn1.setText(" 原图 ");
// final Button btn2 = new Button(comp, SWT.PUSH);
// btn2.setText("放大25%");
// final Button btn3 = new Button(comp, SWT.PUSH);
// btn3.setText("缩小25%");
// final Button btn4 = new Button(comp, SWT.PUSH);
// btn4.setText("自适应");
//
// final Label infoLabel = new Label(comp, SWT.NONE);
// infoLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// infoLabel.setText("原图大小");
//
// SelectionListener listener = new SelectionAdapter()
// {
// @Override
// public void widgetSelected(SelectionEvent e)
// {
// Button btn = (Button)e.widget;
// if (btn == btn1)
// {
// cnt = 0;
// btn2.setEnabled(true);
// btn3.setEnabled(true);
// infoLabel.setText("原图");
// Object ratio = infoLabel.getData("ratio");
// if (ratio != null && ratio.equals(1.0))
// {
// return;
// }
// else
// {
// // 主要是为了在多次点击原图/自适应大小时,不至于频繁刷新图
// infoLabel.setData("ratio", new Double(1.0));
// }
// Image img = label.getImage();
// Image img2 = new Image(display, image.getImageData());
// label.setImage(img2);
// scrolledForm.reflow(true);
// img.dispose();
// }
// else if (btn == btn2)// 放大
// {
// if (cnt < 4)
// {
// cnt++;
// infoLabel.setText("图形大小1+(" + cnt + "*25%)");
// infoLabel.setData("ratio", new Double(1.0 + cnt * 0.25));
// }
// else
// {
// return;
// }
//
// Image im = label.getImage();
//
// double width = image.getImageData().width * (0.25 * cnt + 1.0);
// double height = image.getImageData().height * (0.25 * cnt + 1.0);
//
// ImageData imageData = image.getImageData().scaledTo((int)width, (int)height);
// Image newIm = new Image(display, imageData);
// label.setImage(newIm);
// scrolledForm.reflow(true);
// im.dispose();
//
// }
// else if (btn == btn3)// 缩小
// {
// if (cnt > -3)
// {
// cnt--;
// infoLabel.setText("图形大小1+(" + cnt + "*25%)");
// infoLabel.setData("ratio", new Double(1.0 + cnt * 0.25));
// }
// else
// {
// return;
// }
//
// Image im = label.getImage();
//
// double width = image.getImageData().width * (1.0 + 0.25 * cnt);
// double height = image.getImageData().height * (1.0 + 0.25 * cnt);
//
// ImageData imageData = image.getImageData().scaledTo((int)width, (int)height);
// Image newIm = new Image(display, imageData);
// label.setImage(newIm);
// scrolledForm.reflow(true);
// im.dispose();
// }
// else if (btn == btn4)// 自适应
// {
// infoLabel.setText("图形大小自适应");
// btn2.setEnabled(false);
// btn3.setEnabled(false);
// Image im = label.getImage();
//
// Point p = scrolledForm.getSize();
// double xratio = (1.0 * p.x) / (1.0 * image.getImageData().width);
// double yratio = (1.0 * p.y) / (1.0 * image.getImageData().height);
//
// double ratio = xratio >= yratio ? yratio : xratio;
//
// Object obj = infoLabel.getData("ratio");
// if (obj != null && obj.equals(ratio))
// {
// return;
// }
// else
// {
// infoLabel.setData("ratio", new Double(ratio));
// }
//
// double destWidth = image.getImageData().width * ratio;
// double destHeight = image.getImageData().height * ratio;
//
// ImageData imageData = image.getImageData().scaledTo((int)destWidth, (int)destHeight);
// Image newIm = new Image(display, imageData);
// label.setImage(newIm);
// scrolledForm.reflow(true);
// im.dispose();
// }
// }
// };
// btn1.addSelectionListener(listener);
// btn2.addSelectionListener(listener);
// btn3.addSelectionListener(listener);
// btn4.addSelectionListener(listener);
//
// shell.setSize(500, 500);
// shell.layout();
// shell.open();
// while (!shell.isDisposed())
// {
// if (!display.readAndDispatch())
// display.sleep();
// }
// image.dispose();
// formToolkit.dispose();
// }
}
图像的滚动
public class ScrollImage
{
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL);
Image originalImage = null;
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
dialog.setText("选择一个图片文件或者取消");
String string = dialog.open();
if (string != null)
{
originalImage = new Image(display, string);
}
if (originalImage == null)
{
int width = 150, height = 200;
originalImage = new Image(display, width, height);
GC gc = new GC(originalImage);
gc.fillRectangle(0, 0, width, height);
gc.drawLine(0, 0, width, height);
gc.drawLine(0, height, width, 0);
gc.drawText("默认图片", 10, 10);
gc.dispose();
}
final Image image = originalImage;
final Point origin = new Point(0, 0);
final ScrollBar hBar = shell.getHorizontalBar();
hBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
int hSelection = hBar.getSelection();
int destX = -hSelection - origin.x;
origin.x = -hSelection;
Rectangle rect = image.getBounds();
shell.scroll(destX, 0, 0, 0, rect.width, rect.height, false);
}
});
final ScrollBar vBar = shell.getVerticalBar();
vBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
int vSelection = vBar.getSelection();
int destY = -vSelection - origin.y;
origin.y = -vSelection;
Rectangle rect = image.getBounds();
shell.scroll(0, destY, 0, 0, rect.width, rect.height, false);
}
});
shell.addListener(SWT.Resize, new Listener()
{
public void handleEvent(Event e)
{
Rectangle rect = image.getBounds();
Rectangle client = shell.getClientArea();
hBar.setMaximum(rect.width);
vBar.setMaximum(rect.height);
//绘图面积改变时重新绘制滚动条
hBar.setThumb(Math.min(rect.width, client.width));
vBar.setThumb(Math.min(rect.height, client.height));
//当绘图面积大于图片时,不显示滚动条
if (hBar.getMaximum() == hBar.getThumb())
{
hBar.setVisible(false);
}
else
{
hBar.setVisible(true);
//当绘图面积改变时,重新设定滚动条中键滚动长度(即点击滚动条空白间隙的滚动长度)
hBar.setPageIncrement(hBar.getThumb());
//设定单击滚动条箭头(或是上、下、左、右键)的滚动长度
hBar.setIncrement(50);
}
if (vBar.getMaximum() == vBar.getThumb())
{
vBar.setVisible(false);
}
else
{
vBar.setVisible(true);
vBar.setPageIncrement(vBar.getThumb());
vBar.setIncrement(50);
}
int hPage = rect.width - client.width;
int vPage = rect.height - client.height;
int hSelection = hBar.getSelection();
int vSelection = vBar.getSelection();
if (hSelection >= hPage)
{
if (hPage <= 0)
hSelection = 0;
origin.x = -hSelection;
}
if (vSelection >= vPage)
{
if (vPage <= 0)
vSelection = 0;
origin.y = -vSelection;
}
shell.redraw();
}
});
shell.addListener(SWT.Paint, new Listener()
{
public void handleEvent(Event e)
{
GC gc = e.gc;
gc.drawImage(image, origin.x, origin.y);
Rectangle rect = image.getBounds();
Rectangle client = shell.getClientArea();
int marginWidth = client.width - rect.width;
if (marginWidth > 0)
{
gc.fillRectangle(rect.width, 0, marginWidth, client.height);
}
int marginHeight = client.height - rect.height;
if (marginHeight > 0)
{
gc.fillRectangle(0, rect.height, client.width, marginHeight);
}
}
});
shell.setSize(200, 150);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
图像的旋转
public class RotateImageExample
{
int oWidth;
int oHeight;
double nAngle;
double absSin;
double absCos;
Device device = null;
Transform transform = null;
GC gc;
static int x = 0;
public Image rotate(Image oImage, int angle)
{
Rectangle imageRectangle = oImage.getBounds();
oWidth = imageRectangle.width;
oHeight = imageRectangle.height;
nAngle = angle * Math.PI / 180.0;// 弧度
absSin = Math.abs(Math.sin(nAngle));
absCos = Math.abs(Math.cos(nAngle));
int nWidth = (int)Math.floor(oHeight * absSin + oWidth * absCos);
int nHeight = (int)Math.floor(oHeight * absCos + oWidth * absSin);
device = oImage.getDevice();
transform = new Transform(device);
transform.translate(oWidth / 2, oHeight / 2);
transform.rotate(angle);
transform.translate(-oWidth / 2, -oHeight / 2);
Image nImage = new Image(device, nWidth, nHeight);
gc = new GC(nImage);
gc.setTransform(transform);
gc.drawImage(oImage, 0, 0);
gc.dispose();
transform.dispose();
return nImage;
}
public static void main(String[] args)
{
Display display = Display.getDefault();
Shell shell = new Shell();
shell.setLayout(new FillLayout());
final Canvas canvas = new Canvas(shell, SWT.DOUBLE_BUFFERED);
final RotateImageExample rotimg = new RotateImageExample();
final Image image = new Image(Display.getCurrent(), "icons/ipod.jpg");
canvas.addPaintListener(new PaintListener()
{
@Override
public void paintControl(PaintEvent e)
{
Image img = rotimg.rotate(image, rotimg.x);
e.gc.drawImage(img, 0, 0);
img.dispose();
}
});
// shell.addMouseMoveListener(new MouseMoveListener()
// {
// @Override
// public void mouseMove(MouseEvent e)
// {
// r.x += 5;
// canvas.redraw();
// }
// });
canvas.addMouseMoveListener(new MouseMoveListener()
{
@Override
public void mouseMove(MouseEvent e)
{
RotateImageExample.x -= 5;
canvas.redraw();
}
});
shell.open();
shell.layout();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Java图像格式转换
ImageIO 目前支持一下格式: BMP, JPG,PNG, JPEG, WBMP, GIF
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageIOTest {
public static void main(String args[]) throws IOException {
File inputFile = new File("c:\\11.jpg");
BufferedImage input = ImageIO.read(inputFile);
ImageIO.write(input, "GIF", outputFile);
//ImageIO.write(input, "JPEG", outputFile);
//ImageIO.write(input, "JPG", outputFile);
//ImageIO.write(input, "PNG", outputFile);
}
}
还可以使用JAI(sun公司java advanced imaging,三个重要的jar文件mlibwrapper_jar.jar、jar_codec.jar和jar_core.jar移到你的classpath环境变量指定的目录下。我们推荐把它们放到你的JDK的jre/lib/ext目录下。)jimi(sun公司)。
SWT图像介绍
这部分内容大多是以前从网上找的,出处不记得了,望原版见谅。
SWT Images简介
软件开发人员可以利用 SWT 封装的 Image, ImageData 等类来创建图像、存储图像数据,也可以对存储的图像数据进行各种图像变换。本文将演示如何正确的使用 Image, ImageData 等类,以及如何使图像变灰、变亮/黑、图像旋转、图像拉伸、图片透明叠加、图片反色等相关问题。
下面就来介绍一下 Image 和 ImageData 这两个在 SWT Images 中最重要的类。
类 org.eclipse.swt.graphics.Image 被用来表示可以在设备上显示的图片,可以用方法如GC.drawImage() 或者 Button.setImage() 等来将它显示出来。Image 类提供了几个构造函数,可以完成以下功能:
• 装载一个现有的图象。可以通过传入文件名或者 InputStream 作为参数,但是图象的格式必须是它所支持的格式之(目前 SWT Image 支持 BMP、GIF、JPG、PNG、Windows ICO 等格式)一,否则会抛出 SWTException 异常。
• 构造一个用已经存在的 ImageData 进行初始化的图像。
• 构造一个空图像。可以通过修改其像素值或者向它拷贝一个 SWT 图形上下文的内容 (GC) 来绘制该图像,并且可以指定空图像的大小。
类 org.eclipse.swt.graphics.ImageData 中存储了图像的像素数据信息。 ImageData 是一个包含有关图像大小、调色板、颜色值和透明度等信息的类。我们可以对这些图像像素数据可以直接读或者写操作,这意味着可以通过直接读取或者修改图像的数据,来设置或者取得图像中任何像素或者任何一组像素的颜色值。关于 ImageData ,我们还应当了解以下一些字段:
• width 和 height 指定图像的宽和高。Depth 指定图像的颜色深度。可能的值为 1、2、4、8、16、24 或者 32,指定编码每一个像素的值所使用的比特数。
• alpha 与 alphaData 定义图像的透明度。alpha 定义了图象的全局透明度值,默认值为 -1,并且alphaData 域将被忽略。当 alpha 不等于 -1 时, alphaData 存储了图象的透明度缓冲区,每个像素可以有一个在 0~255 之间的透明度值,数值越大,表示越不透明。值得注意的是,只有部分图象格式具有透明度,例如 GIF 和 PNG。
• palette 包含一个 PaletteData 对象,它存储有关图像的颜色模型的信息。SWT 的颜色模型可以是索引或者直接的,由palette的域 isDirect 来指定。如果颜色模型是索引的,那么 PaletteData 包含颜色索引,可以通过方法 getRGBs() 来获取 RGB 信息。如果它是直接的,那么它包含转换信息,表明应当如何从像素的整数值中提取出颜色 RGB 成分。
• data 包含像素值的字节缓冲区。字节编码的方法取决于所使用的颜色深度。对于一个 8 位的图像,数组中的一个字节正好表示图像中一个像素的值。对于 16 位图像,每一个像素值编码为缓冲区中的两个字节。这两个字节以最低有效字节顺序存储。对于 24 或者 32 位图像,每一个像素值以最高有效位字节顺序编码为缓冲区中的三个或者四个字节。
• bytesPerLine 表明缓冲区中有多少字节用于表示图像中一行像素的所有像素值。由于一个像素可能有多个字节表示,所以 bytesPerLine 可能是字段 width 值的若干倍。也就是说“一个像素扫描行上有多少个字节”,我们知道表示一个像素可能需要1,、3、4…n个字节等(分别对应256灰度图,24位真彩色等),因此,通过bytesPerPixel = bytesPerLine÷n就可以知道,一个扫描行上有多少个像素。我们将bytesPerPixel称为每个像素所占的字节数。
________________________________________
SWT图象处理
常见的图象处理包含图象的读/写、图像变灰、变亮/黑、图像旋转、图像拉伸、图片透明叠加、图片反色等。下面将就这些问题逐个介绍,表 1 列出了各个清单所对应的图像处理。
图像的读写
我们可以使用类 org.eclipse.swt.graphics.ImageLoader 来加载或者保存图像。 ImageLoader 具有一个全局的成员变量 ImageData[],它用于存储图片数据。
清单 1. 图像读写示例
图像可以直接得到
Image image = new Image(display, “e:/aa.jpg”);
我们还可以用ImageLoader得到(不仅能得到,还能保存为各种格式的图像文件,)
ImageLoader loader = new ImageLoader();
ImageData[] imgD = loader.load("icons/ipod.jpg");
if(imgD!=null&&imgD.length>0)
{
image = new Image(display, imgD[0]);
label.setImage(image);
loader.data[0] = image.getImageData();
loader.save("icons/qqq.png", SWT.IMAGE_PNG);
}
图像变灰
图像变灰在桌面应用程序中有着广泛的应用。例如,一个图标被作为一个按钮的背景,我们需要一个灰色效果的图标作为按钮的背景来表示这个按钮处于禁用状态。在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 度即将所有的像素点按照规则换一下位置。其他的旋转可用同样的方法。
旋转中心点为图形左下角,旋转90度的计算公式:
X’ = y;
y’= -x;
旋转中心点为图形左上角,旋转90度的计算公式:
X’ = -y;
y’= x;
旋转中心点为图形中心点,坐标为计算机平面坐标(左上角为(0,0)),旋转90度的计算公式:
X’ = y;
y’= width-x-1;
旋转中心点为图形中心点,坐标为左下角为(0,0),旋转90度的计算公式:
X’ = height –y -1;
y’= x;
图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 分别为待叠加图片A的 R、G、B 以及 alpha 分量乘以透明度参数 a 加上待叠加图片B的 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 || srcData1.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;
}24位真彩色图转为256色图(灰度图)
彩色图像转换为黑白图像时需要计算图像中每像素有效的亮度值,通过匹配像素亮度值可以轻松转换为黑白图像。
计算像素有效的亮度值可以使用下面的公式:
Y=0.3red+0.59green+0.11blue
然后使用 Color.FromArgb(Y,Y,Y) 来把计算后的值转换
转换代码可以使用下面的方法来实现:
按照以上同样的方法我们有:
public static Image convertToGrayscale(Image source )
{
if(source == null )return null;
ImageData ida = source.getImageData();
byte[] data2 = new byte[ida.data.length];
int offset = 0;
int k = 0;
int r, g,b,gray;
for(int i=0;i<ida.height;i++)
{
for(int j=0;j<ida.width;j++)
{
k = offset+j*3;
b = ida.data[k]&0xff;
g = ida.data[k + 1]&0xff;
r = ida.data[k + 2]&0xff;
gray = (int) (0.11*b + 0.59*g + 0.3*r);
data2[k]=data2[k+1]=data2[k+2]=(byte)gray;
}
offset += ida.bytesPerLine;
}
ImageData ida2 = new ImageData(ida.width, ida.height, ida.depth, ida.palette, ida.scanlinePad, data2);
Return new Image(source.getDevice(),ida2);
}
另外,我们也可以直接利用swt image在new 的时候指定flag来做到:
Image img1 = new Image(display,"E:/资料/小内容/Winter.jpg");
Image img2 = new Image(display,img1,SWT.IMAGE_GRAY);
Image的flag目前共有3个分别是SWT.IMAGE_GRAY, SWT.IMAGE_COPY, SWT.IMAGE_DISABLE。
经过与swt image中生成SWT.IMAGE_GRAY的计算方法。发现上面的清单有问题,具体再查。先这么着吧。
图像旋转/放大/移动的坐标对应
x = 1/ω * [x1*cos θ + y1*sinθ – (x0*cosθ + y0*sinθ)];
y = 1/ω * [y1*cosθ – x1*sinθ – (y0*cosθ - x0*sinθ)];
(x ,y)是原图中的点
(x1,y1)是视图窗口中的点
θ是旋转的角度
ω是放大倍数
(x0,y0)是平移时鼠标移动的偏移量
SWT_Image界面操作
图像拖动
public class DragImage
{
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.H_SCROLL | SWT.V_SCROLL);
final Composite composite = new Composite(shell, SWT.BORDER);
composite.setEnabled(false);
composite.setLayout(new FillLayout());
composite.setSize(700, 600);
final Color red = display.getSystemColor(SWT.COLOR_RED);
composite.addPaintListener(new PaintListener()
{
public void paintControl(PaintEvent e)
{
e.gc.setBackground(red);
e.gc.fillOval(5, 5, 690, 590);
}
});
final ScrollBar hBar = shell.getHorizontalBar();
hBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
Point location = composite.getLocation();
location.x = -hBar.getSelection();
composite.setLocation(location);
}
});
final ScrollBar vBar = shell.getVerticalBar();
vBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
Point location = composite.getLocation();
location.y = -vBar.getSelection();
composite.setLocation(location);
}
});
shell.addListener(SWT.Resize, new Listener()
{
public void handleEvent(Event e)
{
Point size = composite.getSize();
Rectangle rect = shell.getClientArea();
hBar.setMaximum(size.x);
vBar.setMaximum(size.y);
hBar.setThumb(Math.min(size.x, rect.width));
vBar.setThumb(Math.min(size.y, rect.height));
int hPage = size.x - rect.width;
int vPage = size.y - rect.height;
int hSelection = hBar.getSelection();
int vSelection = vBar.getSelection();
Point location = composite.getLocation();
if (hSelection >= hPage)
{
if (hPage <= 0)
hSelection = 0;
location.x = -hSelection;
}
if (vSelection >= vPage)
{
if (vPage <= 0)
vSelection = 0;
location.y = -vSelection;
}
composite.setLocation(location);
}
});
final Point[] offset = new Point[1];
Listener listener = new Listener()
{
public void handleEvent(Event event)
{
switch (event.type)
{
case SWT.MouseDown:
Rectangle rect = composite.getBounds();
if (rect.contains(event.x, event.y))
{
Point pt1 = composite.toDisplay(0, 0);
Point pt2 = shell.toDisplay(event.x, event.y);
offset[0] = new Point(pt2.x - pt1.x, pt2.y - pt1.y);
}
break;
case SWT.MouseMove:
if (offset[0] != null)
{
Point pt = offset[0];
composite.setLocation(event.x - pt.x, event.y - pt.y);
System.out.println("x : " + event.x + " y : " + event.y);
hBar.setSelection(pt.x - event.x);
vBar.setSelection(pt.y - event.y);
}
break;
case SWT.MouseUp:
offset[0] = null;
break;
}
}
};
shell.addListener(SWT.MouseDown, listener);
shell.addListener(SWT.MouseUp, listener);
shell.addListener(SWT.MouseMove, listener);
shell.setSize(600, 500);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
图像的几种显示
public class ImageProcesser
{
/*
* 图像按原始大小显示,当面板尺寸小于图像尺寸时,会出现滚动条
*/
public static void main(String[] args)
{
final Display display = Display.getDefault();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
FormToolkit formToolkit = new FormToolkit(display);
ScrolledForm scrolledForm = formToolkit.createScrolledForm(shell);
Composite container = scrolledForm.getBody();
GridLayout layout = new GridLayout(1, false);
container.setLayout(layout);
final Label label = new Label(container, SWT.NONE);
label.setLayoutData(new GridData(GridData.FILL_BOTH));
final Image image = new Image(display, "icons/ipod.jpg");
label.setImage(image);
shell.layout();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
if(image!=null)
{
image.dispose();
}
formToolkit.dispose();
}
/*
* 图像可以随canvas拉伸,图像会形变,不会出现滚动条
*/
// public static void main(String[] args) {
// Display display = Display.getDefault();
// Shell shell = new Shell(display);
// shell.setLayout(new GridLayout(1,false));
//
// final Canvas canvas = new Canvas(shell, SWT.DOUBLE_BUFFERED);
// canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
// final Image image = new Image(display, "icons/ipod.jpg");
// final int srcWidth = image.getImageData().width;
// final int srcHeight = image.getImageData().height;
//
// canvas.addPaintListener(new PaintListener() {
// public void paintControl(PaintEvent e) {
// Rectangle rect = canvas.getClientArea();
// Point p = new Point(rect.width,rect.height);
// e.gc.drawImage(image, 0, 0,srcWidth,srcHeight,0,0,p.x,p.y);
// }
// });
//
// shell.layout();
// shell.open();
// while (!shell.isDisposed()) {
// if (!display.readAndDispatch())
// display.sleep();
// }
// image.dispose();
// }
// /*
// * 图像“按比例”随面板大小形变(达到最适合面板效果),不会出现滚动条
// */
// public static void main(String[] args)
// {
// Display display = Display.getDefault();
// Shell shell = new Shell(display);
// shell.setLayout(new GridLayout(1, false));
//
// final Canvas canvas = new Canvas(shell, SWT.DOUBLE_BUFFERED);
// canvas.setLayoutData(new GridData(GridData.FILL_BOTH));
// final Image image = new Image(display, "icons/ipod.jpg");
// final double srcWidth = image.getImageData().width;
// final double srcHeight = image.getImageData().height;
//
// canvas.addPaintListener(new PaintListener()
// {
// public void paintControl(PaintEvent e)
// {
// Rectangle rect = canvas.getClientArea();
// double areaWidth = rect.width;
// double areaHeight = rect.height;
//
// double xratio = (1.0*areaWidth)/(1.0*srcWidth);
// double yratio = (1.0*areaHeight)/(1.0*srcHeight);
//
// double ratio = xratio>=yratio?yratio:xratio;
//
// double destWidth = srcWidth * ratio;
// double destHeight = srcHeight * ratio;
//
// e.gc.setAntialias(SWT.ON);
// e.gc.drawImage(image, 0,0, (int) srcWidth,(int) srcHeight, 0,0, (int) destWidth,(int) destHeight);
// }
// });
//
// shell.layout();
// shell.open();
// while (!shell.isDisposed())
// {
// if (!display.readAndDispatch())
// display.sleep();
// }
// image.dispose();
// }
/*
* 面板大小不变,图形随放大缩小操作形变,会出现滚动条
*/
private static int cnt = 0;
// public static void main(String[] args)
// {
// final Display display = Display.getDefault();
// final Shell shell = new Shell(display);
// shell.setLayout(new GridLayout(1, true));
//
// FormToolkit formToolkit = new FormToolkit(display);
// final ScrolledForm scrolledForm = formToolkit.createScrolledForm(shell);
// scrolledForm.setLayoutData(new GridData(GridData.FILL_BOTH));
// Composite container = scrolledForm.getBody();
// container.setLayout(new FillLayout());
//
// final Label label = new Label(container, SWT.NONE);
// label.addMouseListener(new MouseAdapter()
// {
// @Override
// public void mouseUp(MouseEvent e)
// {
// scrolledForm.setFocus();
// }
// });
// final Image image = new Image(display, "icons/ipod.jpg");
// Image img = new Image(display, image.getImageData());
// label.setImage(img);
// final Composite comp = new Composite(shell, SWT.NONE);
// GridLayout layout = new GridLayout(5, false);
// comp.setLayout(layout);
// final Button btn1 = new Button(comp, SWT.PUSH);
// btn1.setText(" 原图 ");
// final Button btn2 = new Button(comp, SWT.PUSH);
// btn2.setText("放大25%");
// final Button btn3 = new Button(comp, SWT.PUSH);
// btn3.setText("缩小25%");
// final Button btn4 = new Button(comp, SWT.PUSH);
// btn4.setText("自适应");
//
// final Label infoLabel = new Label(comp, SWT.NONE);
// infoLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// infoLabel.setText("原图大小");
//
// SelectionListener listener = new SelectionAdapter()
// {
// @Override
// public void widgetSelected(SelectionEvent e)
// {
// Button btn = (Button)e.widget;
// if (btn == btn1)
// {
// cnt = 0;
// btn2.setEnabled(true);
// btn3.setEnabled(true);
// infoLabel.setText("原图");
// Object ratio = infoLabel.getData("ratio");
// if (ratio != null && ratio.equals(1.0))
// {
// return;
// }
// else
// {
// // 主要是为了在多次点击原图/自适应大小时,不至于频繁刷新图
// infoLabel.setData("ratio", new Double(1.0));
// }
// Image img = label.getImage();
// Image img2 = new Image(display, image.getImageData());
// label.setImage(img2);
// scrolledForm.reflow(true);
// img.dispose();
// }
// else if (btn == btn2)// 放大
// {
// if (cnt < 4)
// {
// cnt++;
// infoLabel.setText("图形大小1+(" + cnt + "*25%)");
// infoLabel.setData("ratio", new Double(1.0 + cnt * 0.25));
// }
// else
// {
// return;
// }
//
// Image im = label.getImage();
//
// double width = image.getImageData().width * (0.25 * cnt + 1.0);
// double height = image.getImageData().height * (0.25 * cnt + 1.0);
//
// ImageData imageData = image.getImageData().scaledTo((int)width, (int)height);
// Image newIm = new Image(display, imageData);
// label.setImage(newIm);
// scrolledForm.reflow(true);
// im.dispose();
//
// }
// else if (btn == btn3)// 缩小
// {
// if (cnt > -3)
// {
// cnt--;
// infoLabel.setText("图形大小1+(" + cnt + "*25%)");
// infoLabel.setData("ratio", new Double(1.0 + cnt * 0.25));
// }
// else
// {
// return;
// }
//
// Image im = label.getImage();
//
// double width = image.getImageData().width * (1.0 + 0.25 * cnt);
// double height = image.getImageData().height * (1.0 + 0.25 * cnt);
//
// ImageData imageData = image.getImageData().scaledTo((int)width, (int)height);
// Image newIm = new Image(display, imageData);
// label.setImage(newIm);
// scrolledForm.reflow(true);
// im.dispose();
// }
// else if (btn == btn4)// 自适应
// {
// infoLabel.setText("图形大小自适应");
// btn2.setEnabled(false);
// btn3.setEnabled(false);
// Image im = label.getImage();
//
// Point p = scrolledForm.getSize();
// double xratio = (1.0 * p.x) / (1.0 * image.getImageData().width);
// double yratio = (1.0 * p.y) / (1.0 * image.getImageData().height);
//
// double ratio = xratio >= yratio ? yratio : xratio;
//
// Object obj = infoLabel.getData("ratio");
// if (obj != null && obj.equals(ratio))
// {
// return;
// }
// else
// {
// infoLabel.setData("ratio", new Double(ratio));
// }
//
// double destWidth = image.getImageData().width * ratio;
// double destHeight = image.getImageData().height * ratio;
//
// ImageData imageData = image.getImageData().scaledTo((int)destWidth, (int)destHeight);
// Image newIm = new Image(display, imageData);
// label.setImage(newIm);
// scrolledForm.reflow(true);
// im.dispose();
// }
// }
// };
// btn1.addSelectionListener(listener);
// btn2.addSelectionListener(listener);
// btn3.addSelectionListener(listener);
// btn4.addSelectionListener(listener);
//
// shell.setSize(500, 500);
// shell.layout();
// shell.open();
// while (!shell.isDisposed())
// {
// if (!display.readAndDispatch())
// display.sleep();
// }
// image.dispose();
// formToolkit.dispose();
// }
}
图像的滚动
public class ScrollImage
{
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL);
Image originalImage = null;
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
dialog.setText("选择一个图片文件或者取消");
String string = dialog.open();
if (string != null)
{
originalImage = new Image(display, string);
}
if (originalImage == null)
{
int width = 150, height = 200;
originalImage = new Image(display, width, height);
GC gc = new GC(originalImage);
gc.fillRectangle(0, 0, width, height);
gc.drawLine(0, 0, width, height);
gc.drawLine(0, height, width, 0);
gc.drawText("默认图片", 10, 10);
gc.dispose();
}
final Image image = originalImage;
final Point origin = new Point(0, 0);
final ScrollBar hBar = shell.getHorizontalBar();
hBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
int hSelection = hBar.getSelection();
int destX = -hSelection - origin.x;
origin.x = -hSelection;
Rectangle rect = image.getBounds();
shell.scroll(destX, 0, 0, 0, rect.width, rect.height, false);
}
});
final ScrollBar vBar = shell.getVerticalBar();
vBar.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
int vSelection = vBar.getSelection();
int destY = -vSelection - origin.y;
origin.y = -vSelection;
Rectangle rect = image.getBounds();
shell.scroll(0, destY, 0, 0, rect.width, rect.height, false);
}
});
shell.addListener(SWT.Resize, new Listener()
{
public void handleEvent(Event e)
{
Rectangle rect = image.getBounds();
Rectangle client = shell.getClientArea();
hBar.setMaximum(rect.width);
vBar.setMaximum(rect.height);
//绘图面积改变时重新绘制滚动条
hBar.setThumb(Math.min(rect.width, client.width));
vBar.setThumb(Math.min(rect.height, client.height));
//当绘图面积大于图片时,不显示滚动条
if (hBar.getMaximum() == hBar.getThumb())
{
hBar.setVisible(false);
}
else
{
hBar.setVisible(true);
//当绘图面积改变时,重新设定滚动条中键滚动长度(即点击滚动条空白间隙的滚动长度)
hBar.setPageIncrement(hBar.getThumb());
//设定单击滚动条箭头(或是上、下、左、右键)的滚动长度
hBar.setIncrement(50);
}
if (vBar.getMaximum() == vBar.getThumb())
{
vBar.setVisible(false);
}
else
{
vBar.setVisible(true);
vBar.setPageIncrement(vBar.getThumb());
vBar.setIncrement(50);
}
int hPage = rect.width - client.width;
int vPage = rect.height - client.height;
int hSelection = hBar.getSelection();
int vSelection = vBar.getSelection();
if (hSelection >= hPage)
{
if (hPage <= 0)
hSelection = 0;
origin.x = -hSelection;
}
if (vSelection >= vPage)
{
if (vPage <= 0)
vSelection = 0;
origin.y = -vSelection;
}
shell.redraw();
}
});
shell.addListener(SWT.Paint, new Listener()
{
public void handleEvent(Event e)
{
GC gc = e.gc;
gc.drawImage(image, origin.x, origin.y);
Rectangle rect = image.getBounds();
Rectangle client = shell.getClientArea();
int marginWidth = client.width - rect.width;
if (marginWidth > 0)
{
gc.fillRectangle(rect.width, 0, marginWidth, client.height);
}
int marginHeight = client.height - rect.height;
if (marginHeight > 0)
{
gc.fillRectangle(0, rect.height, client.width, marginHeight);
}
}
});
shell.setSize(200, 150);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
图像的旋转
public class RotateImageExample
{
int oWidth;
int oHeight;
double nAngle;
double absSin;
double absCos;
Device device = null;
Transform transform = null;
GC gc;
static int x = 0;
public Image rotate(Image oImage, int angle)
{
Rectangle imageRectangle = oImage.getBounds();
oWidth = imageRectangle.width;
oHeight = imageRectangle.height;
nAngle = angle * Math.PI / 180.0;// 弧度
absSin = Math.abs(Math.sin(nAngle));
absCos = Math.abs(Math.cos(nAngle));
int nWidth = (int)Math.floor(oHeight * absSin + oWidth * absCos);
int nHeight = (int)Math.floor(oHeight * absCos + oWidth * absSin);
device = oImage.getDevice();
transform = new Transform(device);
transform.translate(oWidth / 2, oHeight / 2);
transform.rotate(angle);
transform.translate(-oWidth / 2, -oHeight / 2);
Image nImage = new Image(device, nWidth, nHeight);
gc = new GC(nImage);
gc.setTransform(transform);
gc.drawImage(oImage, 0, 0);
gc.dispose();
transform.dispose();
return nImage;
}
public static void main(String[] args)
{
Display display = Display.getDefault();
Shell shell = new Shell();
shell.setLayout(new FillLayout());
final Canvas canvas = new Canvas(shell, SWT.DOUBLE_BUFFERED);
final RotateImageExample rotimg = new RotateImageExample();
final Image image = new Image(Display.getCurrent(), "icons/ipod.jpg");
canvas.addPaintListener(new PaintListener()
{
@Override
public void paintControl(PaintEvent e)
{
Image img = rotimg.rotate(image, rotimg.x);
e.gc.drawImage(img, 0, 0);
img.dispose();
}
});
// shell.addMouseMoveListener(new MouseMoveListener()
// {
// @Override
// public void mouseMove(MouseEvent e)
// {
// r.x += 5;
// canvas.redraw();
// }
// });
canvas.addMouseMoveListener(new MouseMoveListener()
{
@Override
public void mouseMove(MouseEvent e)
{
RotateImageExample.x -= 5;
canvas.redraw();
}
});
shell.open();
shell.layout();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}