Posted on 2006-07-04 09:41
花 閱讀(285)
評(píng)論(0) 編輯 收藏 所屬分類:
Java
相信大家平時(shí)碰到過一些在JAVA中對(duì)圖像進(jìn)行處理的需求,比如需要對(duì)上傳的圖片加上自己的簽名或圖標(biāo),或者生成和解析動(dòng)態(tài)的GIF圖片,以及處理PSD文件圖像信息。本文就JAVA在圖像處理中一些基本應(yīng)用進(jìn)行了介紹。希望通過能夠?qū)Υ蠹以谝院蟮膱D像處理中有些幫助。
一、對(duì)一個(gè)現(xiàn)有的圖片進(jìn)行文字和圖標(biāo)的合成
? ? ? ? ? ? ? ? ? ? ?
我們先從下面的這段簡(jiǎn)單的代碼開始
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 {
? ?//讀取模板圖片內(nèi)容
? ?BufferedImage image = ImageIO.read(new FileInputStream("c:\\1.jpg"));
? ?Graphics2D g = image.createGraphics();//得到圖形上下文
? ?g.setColor(Color.BLACK); //設(shè)置畫筆顏色
? ?//設(shè)置字體
? ?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();
? ?}
}
}
相信大家看到這里已經(jīng)知道了大致的操作過程,我想我還是在這里把基本的原理簡(jiǎn)單說明一下便于對(duì)后續(xù)內(nèi)容的闡述:首先我們通過javax.imageio.ImageIO的read方法讀取圖像在BufferedImage中,然后我們可以通過BufferedImage的createGraphics方法取得圖像的上下文便于對(duì)圖像的處理,如加上自己喜愛的文字或圖片等,最后調(diào)用JPEGCodec的encode方法進(jìn)行JPEG編碼,然后就是保存到文件中了。
這就是我運(yùn)行上面代碼的結(jié)果
需要提出的是JPEGCodec是非標(biāo)準(zhǔn)類,如果程序是運(yùn)行JDK1.4以上版本的話,可以采取以下代碼進(jìn)行JPEG編碼ImageIO.write(image, "JPEG", out);
可能在你的實(shí)際需求還要加入一些圖標(biāo)的修飾,要做到這一步,我們只需要在上面的代碼中利用Graphics2D的drawImage方法做到。下面是加入圖標(biāo)的代碼
public static void main(String[] args) {
?try {
? ? BufferedImage image = ImageIO.read(new FileInputStream("c:\\1.jpg"));
? ? //讀取圖標(biāo)
? ? 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);
? ? //寫入圖標(biāo)
? ? 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();
? ?}
}
代碼運(yùn)行的結(jié)果如下
二、生成和解析動(dòng)態(tài)的GIF圖片
有了以上對(duì)圖象的基本處理之后,我們?cè)賮砜纯磳?duì)動(dòng)態(tài)GIF圖片的處理。
GIF是一種由CompuServe創(chuàng)建的壓縮和傳送圖像文件的格式。
GIF圖像是基于顏色列表的(存儲(chǔ)的數(shù)據(jù)是該點(diǎn)的顏色對(duì)應(yīng)于顏色列表的索引值),最多只支持8位(256色)。GIF文件內(nèi)部分成許多存儲(chǔ)塊,用來存儲(chǔ)多幅圖像(Frame)或者是決定圖像表現(xiàn)行為的控制塊,用以實(shí)現(xiàn)動(dòng)畫和交互式應(yīng)用。因此我們要生成和分析GIF圖像的話,就需要對(duì)GIF文件格式進(jìn)行分析,這里我們采用網(wǎng)上的一個(gè)開源代碼進(jìn)行處理。
先在http://www.fmsware.com/stuff/gif.zip 下載處理GIF圖片的代碼,解壓之后可以發(fā)現(xiàn)有AnimatedGifEncoder.java, GifDecoder.java, LZWEncoder.java,NeuQuant.java這4個(gè)JAVA文件,在這些文件的開頭都已經(jīng)有了簡(jiǎn)單的說明。其中AnimatedGifEncoder.是用來生成GIF文件的類,而GifDecoder則是用來解析GIF動(dòng)態(tài)圖像Frame信息的類。LZWEncoder是LZW壓縮算法類,NeuQuant是用來生成顏色列表的類。
把它們加入到我們的項(xiàng)目文件中,然后我們就來利用AnimatedGifEncoder來寫一段合成動(dòng)態(tài)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); //設(shè)置延遲時(shí)間
? for (int i = 0; i < imgFileName.length; i++) {
? ?e.addFrame(ImageIO.read(new FileInputStream(imgFileName[i])));//加入Frame
? }
? e.finish();
?} catch (Exception e) {
? e.printStackTrace();
}
}
代碼運(yùn)行的結(jié)果如下
是不是覺得有了這個(gè)AnimatedGifEncoder類,合成GIF文件挺方便的,現(xiàn)在我們?cè)賮砜纯碐ifDecoder的使用。
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的個(gè)數(shù)
? for (int i = 0; i < n; i++) {
? ?BufferedImage frame = decoder.getFrame(i); //得到frame
? ?int delay = decoder.getDelay(i);//得到延遲時(shí)間
? ?//生成JPG文件
? ?String outFilePath = "c:\\test_"+i+".jpg";
? ?FileOutputStream out = new FileOutputStream(outFilePath);
? ?ImageIO.write(frame,"jpeg",out);
? }
?} catch (Exception e) {
? e.printStackTrace();
?}
}
}
代碼運(yùn)行完畢之后,就可以生成了相應(yīng)的4個(gè)jpg文件。
對(duì)于以上的代碼有下面幾點(diǎn)需要補(bǔ)充:
1. 我測(cè)試過使用BMP文件的情況,但是沒有通過代碼的測(cè)試,可能是在把BMP圖像轉(zhuǎn)為256色圖像時(shí)出現(xiàn)了錯(cuò)誤。所以在使用之前還需要用其他工具把BMP文件轉(zhuǎn)為JPG格式。
2. 在合成GIF文件的AnimatedGifEncoder類中有下面幾個(gè)值得關(guān)注的函數(shù)
2.1:setFrameRate(float)每秒種播放的幀數(shù)
2.2:setQuality(int quality) 設(shè)置在GIF規(guī)范中轉(zhuǎn)換為256位圖像時(shí)的質(zhì)量參數(shù)這個(gè)值設(shè)置的越小,質(zhì)量越高,但速度越慢,反之依然,不過超過20以后,速度不會(huì)有明顯的提升,默認(rèn)為10。
2.3:setSize(int x,int y) 設(shè)置GIF圖像的大小,默認(rèn)值為第一個(gè)加入的幀的圖像的大小。
三、對(duì)PSD圖像文件的分析
我們先用PS對(duì)模板圖片加上一串字符,保存為TestPsd.psd,注意保存時(shí)不要合并圖層。然后從http://www.fmsware.com/stuff/PSDReader.java 下載一個(gè)分析PSD代碼的JAVA文件,并加入到我們的項(xiàng)目中。并運(yùn)行下面的代碼
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();
?}
}
}
此時(shí)我們便可以發(fā)現(xiàn)3個(gè)解析后的JPG文件,因?yàn)榘ū尘皥D層在內(nèi)有3個(gè)圖層,故有3個(gè)JPG文件。 目前PSDReader 類只支持沒有壓縮過的或者使用RLE壓縮的RGB文件,并且也不支持PS3.0以上的特殊功能。
總結(jié)
在JAVA對(duì)圖像的處理過程中,通常基本步驟是通過讀取圖像信息到圖像緩沖中->同時(shí)取得圖形上下文->對(duì)圖像進(jìn)行相應(yīng)的處理->生成圖像文件。