基于java的圖片文件格式轉換和線性縮放
圖片文件格式轉換最核心的問題就是要解決各種圖片格式的編碼和解碼,推薦用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。
在進行格式轉換時,并不需要關心原圖的格式,只要要轉換的圖片格式在jimi的解碼格式范圍內,就可以完全透明的進行decode過程:
實際的解碼只需要以行代碼,就這么簡單。
編碼過程最簡單的也只需要很少的代碼:
以上代碼就完成了圖片編碼到輸出到os生成轉換后文件的全過程。
上面代碼中的 writer.setOptions(options)是用來對輸出文件的屬性進行相關的設置,每種格式的屬性都不一樣,com.sun.jimi.core.options.*中針對每種圖片編碼格式的相關屬性提供了getter和setter方法,可以方便的進行設置:
com.sun.jimi.core.options.*中針對每種圖片編碼格式的相關屬性提供了getter和setter方法,可以方便的進行設置:
格式轉換就這么簡單。
jimi不支持的encode格式的解決
這里用到了AnimatedGifEncoder 類,是我在網上搜索到的,對gif編碼提供了一個實現,雖然還有待晚善的地方,不過單作格式轉關已經夠用了:)
需要注意的是:AnimatedGifEncoder 不能對所有格式的圖片正確的識別,所以先要將其他格式轉為jpg格式(最簡單的方法是用imageIO)
這樣直接放入BufferedImage中就ok了
實際的編碼過程在上面這句完成。
最后,在完成之前別忘了用上面幾句消滅證據喲:)
當然這種方法其實并不好,最徹底的方法是修改AnimatedGifEncoder,不過做人涅要厚道一點,畢竟是人家寫的代碼嘛,如果有興趣的朋友可以討論一下。
格式轉換解決了,縮放功能也就不算是問題了,以下代碼同時實現了格式轉關和線性縮放:
BufferedImage的構造函數中的參數類型為int,所以以上代碼在改變圖象尺寸時稍有偏差,不過簡單演示一下還是可以的。
jimi的example中可以找到很多單項圖片處理功能的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,有時間可以研究一下,會有不少收獲的。