GIF解碼和編碼操作庫源碼,共有四個類文件(請下載):
1.AnimatedGifEncoder.java
2.GifDecoder.java
3.LZWEncoder.java
4.NeuQuant.java
簡單應用:
import javax.imageio.ImageIO;
import java.io.*;
import java.awt.image.*;
public class Testgif{
public static void main(String args[]){
try{
BufferedImage src = ImageIO.read(new File("c:/work/1.jpg")); // 讀入文件
BufferedImage src1 = ImageIO.read(new File("c:/work/2.jpg")); // 讀入文件
BufferedImage src2 = ImageIO.read(new File("c:/work/3.jpg")); // 讀入文件
AnimatedGifEncoder e = new AnimatedGifEncoder();
e.setRepeat(0);
e.start("c:/work/laoma.gif");
e.setDelay(3000); // 1 frame per sec
e.addFrame(src);
e.setDelay(1000);
e.addFrame(src1);
e.setDelay(100);
e.addFrame(src2);
e.finish();
}catch(IOException e){
e.printStackTrace();
}
}
}
下面的例子來自:http://blog.csdn.net/ideas/archive/2006/08/25/1116198.aspx作者: ideas
1 多張jpg圖合成gif動畫
/**
* 把多張jpg圖片合成一張
* @param pic String[] 多個jpg文件名 包含路徑
* @param newPic String 生成的gif文件名 包含路徑
*/
private synchronized void jpgToGif(String pic[], String newPic) {
try {
AnimatedGifEncoder e = new AnimatedGifEncoder();
e.setRepeat(0);
e.start(newPic);
BufferedImage src[] = new BufferedImage[pic.length];
for (int i = 0; i < src.length; i++) {
e.setDelay(200); //設置播放的延遲時間
src[i] = ImageIO.read(new File(pic[i])); // 讀入需要播放的jpg文件
e.addFrame(src[i]); //添加到幀中
}
e.finish();
} catch (Exception e) {
System.out.println( "jpgToGif Failed:");
e.printStackTrace();
}
}
2 gif動畫分解成多張jpg
/** *//**
* 把gif圖片按幀拆分成jpg圖片
* @param gifName String 小gif圖片(路徑+名稱)
* @param path String 生成小jpg圖片的路徑
* @return String[] 返回生成小jpg圖片的名稱
*/
private synchronized String[] splitGif(String gifName,String path) {
try {
GifDecoder decoder = new GifDecoder();
decoder.read(gifName);
int n = decoder.getFrameCount(); //得到frame的個數
String[] subPic = new String[n];
String tag = this.getTag();
for (int i = 0; i < n; i++) {
BufferedImage frame = decoder.getFrame(i); //得到幀
//int delay = decoder.getDelay(i); //得到延遲時間
//生成小的JPG文件
subPic[i] = path + String.value(i)+ ".jpg";
FileOutputStream out = new FileOutputStream(subPic[i]);
ImageIO.write(frame, "jpeg", out);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(frame); //存盤
out.flush();
out.close();
}
return subPic;
} catch (Exception e) {
System.out.println( "splitGif Failed!");
e.printStackTrace();
return null;
}
}
3 根據提供的文字生成jpg圖片
/** *//**
* 根據提供的文字生成jpg圖片
* @param s String 文字
* @param smallWidth int 每個字的寬度和高度是一樣的
* @param bgcolor Color 背景色
* @param fontcolor Color 字色
* @param fontPath String 字體文件
* @param jpgname String jpg圖片名
* @return
*/
private String createJpgByFont(String s, int smallWidth,Color bgcolor,Color fontcolor,String fontPath,String jpgname)
{
try {
BufferedImage bimage = new BufferedImage(s.length()*smallWidth,
smallWidth,BufferedImage.TYPE_INT_RGB);
Graphics2D g = bimage.createGraphics();
g.setColor(bgcolor); //背景色
g.fillRect(0, 0, smallWidth, smallWidth); //畫一個矩形
//去除鋸齒(當設置的字體過大的時候,會出現鋸齒)
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(fontcolor); //字的顏色
File file = new File(fontPath); //字體文件
//根據字體文件所在位置,創建新的字體對象(此語句在jdk1.5下面才支持)
Font font = Font.createFont(Font.TRUETYPE_FONT, file);
//font.deriveFont(float f)復制當前 Font 對象并應用新設置字體的大小
g.setFont(font.deriveFont((float) smallWidth));
g.drawString(s,0, smallWidth); //在指定坐標除添加文字
g.dispose();
FileOutputStream out = new FileOutputStream(jpgname); //指定輸出文件
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage);
param.setQuality(50f, true);
encoder.encode(bimage, param); //存盤
out.flush();
out.close();
} catch (Exception e) {
System.out.println( "createJpgByFont Failed!");
e.printStackTrace();
}
}
4 多張小jpg圖合成一張大JPG圖,在這里對大圖只作寬度限制,不做高度限制
/** *//**
* 將多個小圖片合成一張大jpg圖 (小的jpg圖片按照行列順序平鋪)
* @param smallJPG ArrayList 一組小的jpg圖片
* @param bigWidth int 大圖寬度
* @param smallWidth int 單個文字生成的小圖的寬度和高度是一致的
* @return
*/
private void createBigJPG(ArrayList smallJPG, int bigWidth,
int smallHeigh,Color bgColor ,String picName) {
try {
if (bigWidth < smallWidth) //如果大圖片的高度比小圖片的高度還小 直接返回
return;
int colCount = bigWidth / smallWidth; //每行放置的字數
int leftMargin = (int) ((bigWidth - colCount * smallWidth) / 2f); //左邊距
int rowCount = smallJPG.size(); //小圖行數
int setWidth = bigWidth; //每列中間不留空隙,只留左右邊距
int setHeight = smallWidth * rowCount ;
//按照大圖片寬高繪制一個背景圖片
BufferedImage bufImage = new BufferedImage(setWidth, setHeight,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufImage.createGraphics();
g.setColor(bgColor); //背景的顏色
g.fillRect(0, 0, setWidth, setHeight);
int y = 0; //縱坐標
for (int i = 0; i < rowCount; i++) { //遍歷每行
ArrayList col = (ArrayList) (smallJPG.get(i));
int x = leftMargin; //橫坐標 可能會出現左邊距
for (int j = 0; j < col.size(); j++) {
String jpgname = (String) (col.get(j));
ImageIcon icon = new ImageIcon(jpgname);
Image img = icon.getImage();
int imgWidth = img.getHeight(null);
g.drawImage(img, x, y, null);
x += imgWidth;
}
y += (smallWidth);
}
g.dispose();
FileOutputStream out = new FileOutputStream(picName); //指定輸出文件
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); //設置文件格式
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufImage); //從圖片緩沖中讀取
param.setQuality(50f, true);
encoder.encode(bufImage, param); //存盤
out.flush();
out.close();
} catch (Exception e) {
System.out.println( "createBigJPG Failed!");
e.printStackTrace();
}
}
注:
(1)AnimatedGifEncoder和GifDecoder,以及這兩個類涉及到的相關類,在網上搜索一下就可以找到。
(2)在linux系統下,如果你想支持更多系統外的字體,使用下面兩句話,可以不用為系統添加字體,直接把字體文件拷貝到相應位置即可,但是需要jdk1.5環境。
File file = new File(fontPath); //字體文件
Font font = Font.createFont(Font.TRUETYPE_FONT, file); //根據字體文件所在位置,創建新的字體對象
如果是jdk1.5以下版本則需要為系統添加字體,因為createFont(int fontFormat, File fontFile)
這個方法,是從1.5才開始有的。
(3)g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
我在測試中發現,當設置的字體過大的時候,會出現很明星的鋸齒,后來在網上找到了這個解決方法。
(4)有了以上幾個方法,就可以做出更好看的閃信了。我也是因為需求才寫下這些方法的,美工做了一些熱門詞匯的gif圖片,在短信轉彩信遇到這些詞匯時,要使用提供的圖片替換文字。