相信大家平时碰到过一些在JAVA中对图像进行处理的需求,比如需要对上传的图片加上自己的签名或图标,或者生成和解析动态的GIF图片,以及处理PSD文件图像信息。本文就JAVA在图像处理中一些基本应用进行了介绍。希望通过能够对大家在以后的图像处理中有些帮助。
一、对一个现有的图片进行文字和图标的合成
我们先从下面的这段简单的代码开始
import java.awt.*; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.*; /** * @author Anders.Hu * 2005-01-12 */ public class Test { public static void main(String[] args) { try { //读取模板图片内容 BufferedImage image = ImageIO.read(new FileInputStream("c://1.jpg")); Graphics2D g = image.createGraphics();//得到图形上下文 g.setColor(Color.BLACK); //设置画笔颜色 //设置字体 g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 15));//写入签名 g.drawString("很好吃诶,要不要也来一口?",43, image.getHeight() - 10); g.dispose(); FileOutputStream out = new FileOutputStream("c://2.jpg"); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(image); out.close(); } catch(Exception e) { e.printStackTrace(); } } } |
相信大家看到这里已经知道了大致的操作过程,我想我还是在这里把基本的原理简单说明一下便于对后续内容的阐述:首先我们通过javax.imageio.ImageIO的read方法读取图像在BufferedImage中,然后我们可以通过BufferedImage的createGraphics方法取得图像的上下文便于对图像的处理,如加上自己喜爱的文字或图片等,最后调用JPEGCodec的encode方法进行JPEG编码,然后就是保存到文件中了。
这就是我运行上面代码的结果
需要提出的是JPEGCodec是非标准类,如果程序是运行JDK1.4以上版本的话,可以采取以下代码进行JPEG编码ImageIO.write(image, "JPEG", out);
可能在你的实际需求还要加入一些图标的修饰,要做到这一步,我们只需要在上面的代码中利用Graphics2D的drawImage方法做到。下面是加入图标的代码
public static void main(String[] args) { try { BufferedImage image = ImageIO.read(new FileInputStream("c://1.jpg")); //读取图标 BufferedImage image_biao = ImageIO.read(new FileInputStream("c://i.jpg")); Graphics2D g = image.createGraphics(); g.setColor(Color.YELLOW); g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 25)); g.drawString("很好吃诶,要不要也来一口?",43, image.getHeight() - 80); //写入图标 g.drawImage(image_biao, 20,image.getHeight() - 80, image_biao.getWidth(null), image_biao.getHeight(null), null); g.dispose(); FileOutputStream out = new FileOutputStream("c://3.jpg"); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(image); out.close(); } catch(Exception e) { e.printStackTrace(); } } |
代码运行的结果如下
二、生成和解析动态的GIF图片
有了以上对图象的基本处理之后,我们再来看看对动态GIF图片的处理。
GIF是一种由CompuServe创建的压缩和传送图像文件的格式。
GIF图像是基于颜色列表的(存储的数据是该点的颜色对应于颜色列表的索引值),最多只支持8位(256色)。GIF文件内部分成许多存储块,用来存储多幅图像(Frame)或者是决定图像表现行为的控制块,用以实现动画和交互式应用。因此我们要生成和分析GIF图像的话,就需要对GIF文件格式进行分析,这里我们采用网上的一个开源代码进行处理。
先在http://www.fmsware.com/stuff/gif.zip 下载处理GIF图片的代码,解压之后可以发现有AnimatedGifEncoder.java, GifDecoder.java, LZWEncoder.java,NeuQuant.java这4个JAVA文件,在这些文件的开头都已经有了简单的说明。其中AnimatedGifEncoder.是用来生成GIF文件的类,而GifDecoder则是用来解析GIF动态图像Frame信息的类。LZWEncoder是LZW压缩算法类,NeuQuant是用来生成颜色列表的类。
把它们加入到我们的项目文件中,然后我们就来利用AnimatedGifEncoder来写一段合成动态GIF文件的代码。
import java.io.FileInputStream; import javax.imageio.ImageIO; import open.AnimatedGifEncoder; /** * @author Anders.Hu * 2005-01-13 */ public class TestMakeGIF { public static void main(String[] args) { try { //指定Frame的文件 String imgFileName[] = new String[]{"c://1.jpg","c://2.jpg", "c://3.jpg"}; String outputFileName = "c://test.gif"; AnimatedGifEncoder e = new AnimatedGifEncoder(); e.start(outputFileName);//开始处理 e.setDelay(500); //设置延迟时间 for (int i = 0; i < imgFileName.length; i++) { e.addFrame(ImageIO.read(new FileInputStream(imgFileName[i])));//加入Frame } e.finish(); } catch (Exception e) { e.printStackTrace(); } } |
代码运行的结果如下
是不是觉得有了这个AnimatedGifEncoder类,合成GIF文件挺方便的,现在我们再来看看GifDecoder的使用。
public class TestGifDecoder { public static void main(String[] args) { try { String inputFileName = "c://test.gif"; GifDecoder decoder = new GifDecoder(); decoder.read(inputFileName); int n = decoder.getFrameCount();//得到frame的个数 for (int i = 0; i < n; i++) { BufferedImage frame = decoder.getFrame(i); //得到frame int delay = decoder.getDelay(i);//得到延迟时间 //生成JPG文件 String outFilePath = "c://test_"+i+".jpg"; FileOutputStream out = new FileOutputStream(outFilePath); ImageIO.write(frame,"jpeg",out); } } catch (Exception e) { e.printStackTrace(); } } } |
代码运行完毕之后,就可以生成了相应的4个jpg文件。
对于以上的代码有下面几点需要补充:
1.我测试过使用BMP文件的情况,但是没有通过代码的测试,可能是在把BMP图像转为256色图像时出现了错误。所以在使用之前还需要用其他工具把BMP文件转为JPG格式。
2.在合成GIF文件的AnimatedGifEncoder类中有下面几个值得关注的函数
2.1:setFrameRate(float)每秒种播放的帧数
2.2:setQuality(int quality) 设置在GIF规范中转换为256位图像时的质量参数这个值设置的越小,质量越高,但速度越慢,反之依然,不过超过20以后,速度不会有明显的提升,默认为10。
2.3:setSize(int x,int y) 设置GIF图像的大小,默认值为第一个加入的帧的图像的大小。
三、对PSD图像文件的分析
我们先用PS对模板图片加上一串字符,保存为TestPsd.psd,注意保存时不要合并图层。然后从http://www.fmsware.com/stuff/PSDReader.java 下载一个分析PSD代码的JAVA文件,并加入到我们的项目中。并运行下面的代码
import java.awt.Point; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import open.PSDReader; import com.sun.image.codec.jpeg.*; /** * @author Ander.Hu * 2005-10-13 */ public class TestPsd { public static void main(String[] args) { try { PSDReader r = new PSDReader(); r.read("c://testPsd.psd"); int n = r.getFrameCount(); for (int i = 0; i < n; i++) { BufferedImage image = r.getLayer(i); Point offset = r.getLayerOffset(i); //生成JPG文件 String outFilePath = "c://testPsd_"+i+".jpg"; FileOutputStream out = new FileOutputStream(outFilePath); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(image); } } catch(Exception e) { e.printStackTrace(); } } } |
此时我们便可以发现3个解析后的JPG文件,因为包括背景图层在内有3个图层,故有3个JPG文件。 目前PSDReader 类只支持没有压缩过的或者使用RLE压缩的RGB文件,并且也不支持PS3.0以上的特殊功能。
总结
在JAVA对图像的处理过程中,通常基本步骤是通过读取图像信息到图像缓冲中->同时取得图形上下文->对图像进行相应的处理->生成图像文件。