圖片文件格式轉換最核心的問題就是要解決各種圖片格式的編碼和解碼,推薦用jimi包,可從
http://java.sun.com/products/jimi/下載該包及其源碼和demo。
需要注意的是:jimi提供了對幾乎所有圖片格式的解碼支持,但是為提供gif和tif/tiff格式的編碼api,gif編碼問題在網上可以找到縣相關的源碼,tiff好像jai:
http://java.sun.com/products/java-media/jai/index.jsp提供了它的編碼,不過我沒有用jai,暫時用jpeg編碼代替了。
察看jimi的源碼,在com.sun.jimi.core中是jimi的核心處理api。
public?void?toJPG(String?source,?String?dest,?int?quality)?{
if?(dest?==?null?||?dest.trim().equals(""))
dest?=?source;
if?(!dest.toLowerCase().trim().endsWith("jpg"))?{
dest?+=?".jpg";
System.out.println("Overriding?to?JPG,?output?file:?"?+?dest);
}
if?(quality?<?0?||?quality?>?100?||?(quality?+?"")?==?null
||?(quality?+?"").equals(""))?{
System.out.println("quality?must?between?’0’?and?’100’");
System.out.println("set?to?DEFAULT?value:’75’");
quality?=?75;
}
try?{
JPGOptions?options?=?new?JPGOptions();
options.setQuality(quality);
ImageProducer?image?=?Jimi.getImageProducer(source);
JimiWriter?writer?=?Jimi.createJimiWriter(dest);
writer.setSource(image);
//?加入屬性設置,非必要
//?/*
writer.setOptions(options);
//?*/
writer.putImage(dest);
}?catch?(JimiException?je)?{
System.err.println("Error:?"?+?je);
}
}?
在進行格式轉換時,并不需要關心原圖的格式,只要要轉換的圖片格式在jimi的解碼格式范圍內,就可以完全透明的進行decode過程:
ImageProducer?image?=?Jimi.getImageProducer(source);?
實際的解碼只需要以行代碼,就這么簡單。
編碼過程最簡單的也只需要很少的代碼:
JimiWriter?writer?=?Jimi.createJimiWriter(dest);
writer.setSource(image);
//?加入屬性設置,非必要
//?/*
writer.setOptions(options);
//?*/
writer.putImage(dest);?
以上代碼就完成了圖片編碼到輸出到os生成轉換后文件的全過程。
上面代碼中的?writer.setOptions(options)是用來對輸出文件的屬性進行相關的設置,每種格式的屬性都不一樣,com.sun.jimi.core.options.*中針對每種圖片編碼格式的相關屬性提供了getter和setter方法,可以方便的進行設置:
com.sun.jimi.core.options.*中針對每種圖片編碼格式的相關屬性提供了getter和setter方法,可以方便的進行設置:
JPGOptions?options?=?new?JPGOptions();
options.setQuality(quality);?
格式轉換就這么簡單。
jimi不支持的encode格式的解決
/**
*?
*?@param?source
*?@param?dest
*?@throws?JimiException
*/
public?void?toGIF(String?source,?String?dest)?throws?JimiException?{
if?(dest?==?null?||?dest.trim().equals(""))
dest?=?source;
//?1:轉換為jpg
if?(!dest.toLowerCase().trim().endsWith("jpg"))?{
dest?+=?".jpg";
}
toJPG(source,?dest,?75);
BufferedImage?file_in?=?null;
File?file?=?new?File(dest);
try?{
file_in?=?javax.imageio.ImageIO.read(file);
}?catch?(IOException?e)?{
e.printStackTrace();
}
int?end?=?dest.lastIndexOf(".");
file.deleteOnExit();
//?output?*.gif
file.renameTo(new?File(dest.substring(0,?end)?+?".gif"));
//?jpg?to?gif
AnimatedGifEncoder?e?=?new?AnimatedGifEncoder();
e.start(dest);
e.addFrame(file_in);
e.finish();
}?
這里用到了AnimatedGifEncoder?類,是我在網上搜索到的,對gif編碼提供了一個實現,雖然還有待晚善的地方,不過單作格式轉關已經夠用了:)
AnimatedGifEncoder?e?=?new?AnimatedGifEncoder();
e.start(dest);
e.addFrame(file_in);
e.finish();?
需要注意的是:AnimatedGifEncoder?不能對所有格式的圖片正確的識別,所以先要將其他格式轉為jpg格式(最簡單的方法是用imageIO)
BufferedImage?file_in?=?null;
File?file?=?new?File(dest);
try?{
file_in?=?javax.imageio.ImageIO.read(file);
}?catch?(IOException?e)?{
e.printStackTrace();
}?
這樣直接放入BufferedImage中就ok了
e.addFrame(file_in);?
實際的編碼過程在上面這句完成。
int?end?=?dest.lastIndexOf(".");
file.deleteOnExit();
//?output?*.gif
file.renameTo(new?File(dest.substring(0,?end)?+?".gif"));?
最后,在完成之前別忘了用上面幾句消滅證據喲:)
當然這種方法其實并不好,最徹底的方法是修改AnimatedGifEncoder,不過做人涅要厚道一點,畢竟是人家寫的代碼嘛,如果有興趣的朋友可以討論一下。
格式轉換解決了,縮放功能也就不算是問題了,以下代碼同時實現了格式轉關和線性縮放:
/**
*?
*?@param?img
*?@param?dest
*?@throws?JimiException
*/
public?void?toTIF(Image?img,?String?dest)?throws?JimiException?{
if?(!dest.toLowerCase().trim().endsWith("tif"))?{
dest?+=?".tif";
System.out.println("Overriding?to?TIF,?output?file:?"?+?dest);
}
dest?=?dest.substring(0,?dest.lastIndexOf("."))?+?".jpg";
JimiWriter?writer?=?Jimi.createJimiWriter(dest);
writer.setSource(img);
dest?=?dest.substring(0,?dest.lastIndexOf("."))?+?".tif";
writer.putImage(dest);
}
/**
*?線性改變圖片尺寸(可同時改變圖片格式)
*?
*?@param?source
*?源文件完整路徑
*?@param?desc
*?目標文件完整路徑
*?@param?ins
*?放大/縮小比率
*?@throws?JimiException
*?@throws?IOException
*/
public?void?changeDimension(String?source,?String?desc,?double?ins)
throws?JimiException,?IOException?{
String?temp?=?desc;
File?_file?=?null;
if?(desc?==?null?||?desc.trim().equals(""))
desc?=?source;
if?(!desc.toLowerCase().trim().endsWith("jpg"))?{
temp?=?desc.trim()?+?".jpg";
}
this.toJPG(source,?temp,?75);
_file?=?new?File(temp);?//?讀入文件
Image?src?=?javax.imageio.ImageIO.read(_file);?//?構造Image對象
double?wideth?=?(double)?src.getWidth(null);?//?得到源圖寬
double?height?=?(double)?src.getHeight(null);?//?得到源圖長
int?iWideth?=?(int)?(wideth?*?ins);
int?iHeight?=?(int)?(height?*?ins);
BufferedImage?tag?=?new?BufferedImage(iWideth,?iHeight,
BufferedImage.TYPE_INT_RGB);
tag.getGraphics().drawImage(src,?0,?0,?iWideth,?iHeight,?null);?//?繪制縮小后的圖
if?(!temp.trim().equals(desc))
_file.deleteOnExit();
if?(desc.toLowerCase().trim().endsWith("gif"))?{
AnimatedGifEncoder?e?=?new?AnimatedGifEncoder();
e.start(desc);
e.addFrame(tag);
e.finish();
}?else?if?(desc.toLowerCase().trim().endsWith("tif")?||?desc.toLowerCase().trim().endsWith("tiff"))?{
this.toTIF(tag,?desc);
}?else?{
JimiWriter?writer?=?Jimi.createJimiWriter(desc);
writer.setSource(tag);
writer.putImage(desc);
}
}?
BufferedImage的構造函數中的參數類型為int,所以以上代碼在改變圖象尺寸時稍有偏差,不過簡單演示一下還是可以的。
jimi的example中可以找到很多單項圖片處理功能的demo,有時間可以研究一下,會有不少收獲的。
posted on 2006-07-06 17:22
SIMONE 閱讀(317)
評論(0) 編輯 收藏 所屬分類:
JAVA