使用JAVA对图片进行效果变换
?原文链接: http://www.ismyway.com/articles/simpleimageeffect/index.html
一提到JAVA,谈论最多的就是JSP/SERVLET/J2EE之类的,但对于用JAVA对图片进行效果变换,到论坛里看了看,关于这方面的话题并不多,网上关于图像效果处理的文章也并不丰富,于是在自己摸索了几天,并且参考了AnfyJava(专业级的JAVA效果生成器)后,我用轻量级控件写了一个(AnfyJava继承的是Applet,Applet是java.awt包中的,属于重量级控件,SUN现在推荐使用swing来编写图形程序,因此,我用的是JApplet)。
其实,用JAVA做图像效果和其它语言在本质上并没有什么区别,只不过在实现起来有所不同罢了,下面我就把我在项目中处理的经验与大家分享一下吧。
图像的变换,实际上就是把两幅图片的内容进行某些运算,生成新的图像,然后显示出来,最终实现从一幅图片到另一幅图片的过度效果。变换的具体过程如下:
在上面的过程中,图片A和B的尺寸最好保持一致,如果不一致的话,可能要做一些额外的处理,在此,我选用的图片A和B的尺寸是一致的。
首先,我们将其当作一个Applet来写,由于Applet的局限性,不可以直接使用File类来读取图像文件,因此,我们只能通过如下方法来获取图像文件。
?
?
?
?
package pic;import java.awt.*;import java.io.*;import java.net.*;import java.awt.event.*;import java.awt.image.*;import javax.swing.*;public class effectextends JAppletimplements Runnable {//定义变量Toolkit toolkit;int totalBlocks = 0; //图像被分解成的块数,默认为 宽X高int[] blocks; //保存块数的信息Image[] bufferImage = new Image[2]; //屏幕上的图形缓冲VolatileImage offScreenImage;Image imageBuf; //保存图片缓冲区内容Graphics2D offScreenGraphics;Thread thread;MediaTracker mediaTracker;boolean[] isImageReady; //图片是否已经装载MemoryImageSource memoryimagesource;int imageWidth, imageHeight; //图像的宽及高int[] pixelA, pixelB;int[] redA, greenA, blueA, redB, greenB, blueB;public effect() throws HeadlessException {bufferImage[0] = getImage("a.jpg");bufferImage[1] = getImage("b.jpg");if ( (bufferImage[0].getWidth(this) != bufferImage[1].getWidth(this)) ||(bufferImage[0].getHeight(this) != bufferImage[1].getHeight(this))) {System.out.println("图像尺寸不一致!");return;}toolkit = getToolkit();imageWidth = bufferImage[0].getWidth(this);imageHeight = bufferImage[0].getHeight(this);totalBlocks = imageWidth * imageHeight; //计算分解的块数blocks = new int[totalBlocks];pixelA = new int[totalBlocks];pixelB = new int[totalBlocks];redA = new int[totalBlocks];greenA = new int[totalBlocks];blueA = new int[totalBlocks];redB = new int[totalBlocks];greenB = new int[totalBlocks];blueB = new int[totalBlocks];GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();GraphicsDevice gd = ge.getDefaultScreenDevice();GraphicsConfiguration gc = gd.getDefaultConfiguration();offScreenImage = gc.createCompatibleVolatileImage(imageWidth, imageHeight); //创建图像缓冲offScreenGraphics = offScreenImage.createGraphics(); //取得缓冲的graphics对象}public void init() {getImagePixels(bufferImage[0], pixelA);getImagePixels(bufferImage[1], pixelB);for (int i = 0; i < totalBlocks; i++) {blocks[i] = pixelA[i]; //保存图像A的像素信息redA[i] = pixelA[i] & 0xff0000; //保存图像B的red值greenA[i] = pixelA[i] & 0x00ff00; //保存图像B的green值blueA[i] = pixelA[i] & 0x0000ff; //保存图像B的blue值redB[i] = pixelB[i] & 0xff0000; //保存图像B的red值greenB[i] = pixelB[i] & 0x00ff00; //保存图像B的green值blueB[i] = pixelB[i] & 0x0000ff; //保存图像B的blue值}prepareImagePixels(); //将像素信息还原为图像}public void run() {//检查java版本String javaVersion;try {javaVersion = System.getProperty("java.version");}catch (SecurityException _ex) {javaVersion = "unk";}if (javaVersion.startsWith("1.0")) {System.out.println("require java 1.1 or later version!");return;}try { //暂停3秒钟后等待效果开始thread.sleep(3000l);}catch (InterruptedException ex1) {}int line = 0;Thread currentThread = Thread.currentThread();while (line < imageHeight && thread == currentThread) {for (int i = 0; i < imageWidth; i++) {int offset = line * imageWidth + i;blocks[offset] = pixelB[offset]; //与下一被注释的语句作用相同//blocks[offset] = redB[offset] | greenB[offset] | blueB[offset];}memoryimagesource.newPixels(); //生成新的图像line++;repaint();//适当延时try {thread.sleep(20l);}catch (InterruptedException ex) {}}}public void paint(Graphics g) {if (offScreenGraphics != null) { //保证在destory()时不引发异常offScreenGraphics.drawImage(imageBuf, 0, 0, this);g.drawImage(offScreenImage, 0, 0, this);}}public void start() {if (thread == null) {thread = new Thread(this);thread.start();}}public void stop() {thread = null;}public final void update(Graphics g) {paint(g);}public void destroy() {if (offScreenImage != null) {offScreenImage.flush();}offScreenImage = null;if (offScreenGraphics != null) {offScreenGraphics.dispose();}offScreenGraphics = null;System.gc();}/*** 通过给定的文件名获得图像* @param filename 给定图像的文件名* @return 图像*/Image getImage(String filename) {URLClassLoader urlLoader = (URLClassLoader)this.getClass().getClassLoader();URL url = null;Image image = null;url = urlLoader.findResource(filename);image = Toolkit.getDefaultToolkit().getImage(url);MediaTracker mediatracker = new MediaTracker(this);try {mediatracker.addImage(image, 0);mediatracker.waitForID(0);}catch (InterruptedException _ex) {image = null;}if (mediatracker.isErrorID(0)) {image = null;}return image;}/*** 取得给定图像的像素数组* @param image 指定的图像* @param pixels 保存像素信息的数组* @return 成功返回true*/private boolean getImagePixels(Image image, int pixels[]) {PixelGrabber pixelgrabber = new PixelGrabber(image, 0, 0, imageWidth,imageHeight, pixels,0, imageWidth);try {pixelgrabber.grabPixels();}catch (InterruptedException _ex) {return false;}return true;}/*** 将像素数组还原为图像*/void prepareImagePixels() {memoryimagesource = new MemoryImageSource(imageWidth, imageHeight,new DirectColorModel(24, 0xff0000,0x00ff00, 0x0000ff), blocks, 0, imageWidth);try {memoryimagesource.setAnimated(true);memoryimagesource.setFullBufferUpdates(true);imageBuf = createImage(memoryimagesource);memoryimagesource.newPixels(); //生成新的图像}catch (NoSuchMethodError _ex) {}}/*** 取得图像的宽度* @return 宽度*/public int getWidth() {return imageWidth;}/*** 取得图像的高度* @return 高度*/public int getHeight() {return imageHeight;}public static void main(String args[]) {JFrame frame = new JFrame("Demo");effect e = new effect();e.init();e.start();frame.getContentPane().setLayout(new BorderLayout());frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setResizable(false);frame.getContentPane().add(e);frame.setSize(new Dimension(e.getWidth() + 6, e.getHeight() + 20));Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();Dimension frameSize = frame.getSize();frame.setLocation( (screenSize.width - frameSize.width) / 2,(screenSize.height - frameSize.height) / 2);frame.show();}}?