過去作的項目都是針對企業級應用,第一次開發新聞版塊圖片上傳的功能,須要解決用戶上傳圖片後,按照用戶規定的尺寸大小或者按照圖片比例,對圖片進行壓縮。java
本身試寫的工具類,寫的時候考慮了幾個關鍵點:算法
一、圖片格式函數
JAVA的API很好,com.sun.image.codec.jpeg.JPEGCodec和com.sun.image.codec.jpeg.JPEGImageEncoder 這兩個類基本上自動解決了類型轉換的問題,能夠正常實現bmp轉jpg、png轉jpg、gif轉jpg,可是暫時尚未解決gif轉gif的功能。工具
二、畫面質量的問題測試
BufferedImage tag = new BufferedImage((int)newWidth, (int) newHeight, BufferedImage.TYPE_INT_RGB);ui
// Image.SCALE_SMOOTH 的縮略算法 生成縮略圖片的平滑度的 優先級比速度高 生成的圖片質量比較好 但速度慢this
tag.getGraphics().drawImage(img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);編碼
三、壓縮速度spa
測試36MB的bmp圖片(8192*6144)壓縮成(160*120)的jpg的5KB圖片,只須要2-3秒的時間。批量處理100張(1027*768)的bmp圖像,轉換成(120*80)的jpg圖片總共只須要17秒。code
四、根據用戶喜愛選擇壓縮模式
按比例或者按規定尺寸
//compressPic(大圖片路徑,生成小圖片路徑,大圖片文件名,生成小圖片文名,生成小圖片寬度,生成小圖片高度,是否等比縮放(默認爲true))
如下是源碼,如以爲能夠更加完善的話,但願你們能夠提供點意見!!
/** * 縮略圖實現,將圖片(jpg、bmp、png、gif等等)真實的變成想要的大小 */ package com.joewalker.test; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /******************************************************************************* * 縮略圖類(通用) 本java類能將jpg、bmp、png、gif圖片文件,進行等比或非等比的大小轉換。 具體使用方法 * compressPic(大圖片路徑,生成小圖片路徑,大圖片文件名,生成小圖片文名,生成小圖片寬度,生成小圖片高度,是否等比縮放(默認爲true)) */ public class CompressPicDemo { private File file = null; // 文件對象 private String inputDir; // 輸入圖路徑 private String outputDir; // 輸出圖路徑 private String inputFileName; // 輸入圖文件名 private String outputFileName; // 輸出圖文件名 private int outputWidth = 100; // 默認輸出圖片寬 private int outputHeight = 100; // 默認輸出圖片高 private boolean proportion = true; // 是否等比縮放標記(默認爲等比縮放) public CompressPicDemo() { // 初始化變量 inputDir = ""; outputDir = ""; inputFileName = ""; outputFileName = ""; outputWidth = 100; outputHeight = 100; } public void setInputDir(String inputDir) { this.inputDir = inputDir; } public void setOutputDir(String outputDir) { this.outputDir = outputDir; } public void setInputFileName(String inputFileName) { this.inputFileName = inputFileName; } public void setOutputFileName(String outputFileName) { this.outputFileName = outputFileName; } public void setOutputWidth(int outputWidth) { this.outputWidth = outputWidth; } public void setOutputHeight(int outputHeight) { this.outputHeight = outputHeight; } public void setWidthAndHeight(int width, int height) { this.outputWidth = width; this.outputHeight = height; } /* * 得到圖片大小 * 傳入參數 String path :圖片路徑 */ public long getPicSize(String path) { file = new File(path); return file.length(); } // 圖片處理 public String compressPic() { try { //得到源文件 file = new File(inputDir + inputFileName); if (!file.exists()) { return ""; } Image img = ImageIO.read(file); // 判斷圖片格式是否正確 if (img.getWidth(null) == -1) { System.out.println(" can't read,retry!" + "<BR>"); return "no"; } else { int newWidth; int newHeight; // 判斷是不是等比縮放 if (this.proportion == true) { // 爲等比縮放計算輸出的圖片寬度及高度 double rate1 = ((double) img.getWidth(null)) / (double) outputWidth + 0.1; double rate2 = ((double) img.getHeight(null)) / (double) outputHeight + 0.1; // 根據縮放比率大的進行縮放控制 double rate = rate1 > rate2 ? rate1 : rate2; newWidth = (int) (((double) img.getWidth(null)) / rate); newHeight = (int) (((double) img.getHeight(null)) / rate); } else { newWidth = outputWidth; // 輸出的圖片寬度 newHeight = outputHeight; // 輸出的圖片高度 } BufferedImage tag = new BufferedImage((int) newWidth, (int) newHeight, BufferedImage.TYPE_INT_RGB); /* * Image.SCALE_SMOOTH 的縮略算法 生成縮略圖片的平滑度的 * 優先級比速度高 生成的圖片質量比較好 但速度慢 */ tag.getGraphics().drawImage(img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null); FileOutputStream out = new FileOutputStream(outputDir + outputFileName); // JPEGImageEncoder可適用於其餘圖片類型的轉換 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(tag); out.close(); } } catch (IOException ex) { ex.printStackTrace(); } return "ok"; } public String compressPic (String inputDir, String outputDir, String inputFileName, String outputFileName) { // 輸入圖路徑 this.inputDir = inputDir; // 輸出圖路徑 this.outputDir = outputDir; // 輸入圖文件名 this.inputFileName = inputFileName; // 輸出圖文件名 this.outputFileName = outputFileName; return compressPic(); } public String compressPic(String inputDir, String outputDir, String inputFileName, String outputFileName, int width, int height, boolean gp) { // 輸入圖路徑 this.inputDir = inputDir; // 輸出圖路徑 this.outputDir = outputDir; // 輸入圖文件名 this.inputFileName = inputFileName; // 輸出圖文件名 this.outputFileName = outputFileName; // 設置圖片長寬 setWidthAndHeight(width, height); // 是不是等比縮放 標記 this.proportion = gp; return compressPic(); } // main測試 // compressPic(大圖片路徑,生成小圖片路徑,大圖片文件名,生成小圖片文名,生成小圖片寬度,生成小圖片高度,是否等比縮放(默認爲true)) public static void main(String[] arg) { CompressPicDemo mypic = new CompressPicDemo(); System.out.println("輸入的圖片大小:" + mypic.getPicSize("e:\\1.jpg")/1024 + "KB"); int count = 0; // 記錄所有圖片壓縮所用時間 for (int i = 0; i < 100; i++) { int start = (int) System.currentTimeMillis(); // 開始時間 mypic.compressPic("e:\\", "e:\\test\\", "1.jpg", "r1"+i+".jpg", 120, 120, true); int end = (int) System.currentTimeMillis(); // 結束時間 int re = end-start; // 但圖片生成處理時間 count += re; System.out.println("第" + (i+1) + "張圖片壓縮處理使用了: " + re + "毫秒"); System.out.println("輸出的圖片大小:" + mypic.getPicSize("e:\\test\\r1"+i+".jpg")/1024 + "KB"); } System.out.println("總共用了:" + count + "毫秒"); } }
原文:http://www.iteye.com/topic/266585
---------------------------------------------------------------------------------------------
整理文檔,搜刮出一個Java作圖片壓縮的代碼,稍微整理精簡一下作下分享。
首先,要壓縮的圖片格式不能說動態圖片,你能夠使用bmp、png、gif等,至於壓縮質量,能夠經過BufferedImage來指定。
在C盤的temp下放置一張圖片pic123.jpg,儘可能找一個像素高一點的圖片,這裏我找了一張5616*3744的。
package test; import java.io.*; import java.util.Date; import java.awt.*; import java.awt.image.*; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.*; /** * 圖片壓縮處理 * @author 崔素強 */ public class ImgCompress { private Image img; private int width; private int height; @SuppressWarnings("deprecation") public static void main(String[] args) throws Exception { System.out.println("開始:" + new Date().toLocaleString()); ImgCompress imgCom = new ImgCompress("C:\\temp\\pic123.jpg"); imgCom.resizeFix(400, 400); System.out.println("結束:" + new Date().toLocaleString()); } /** * 構造函數 */ public ImgCompress(String fileName) throws IOException { File file = new File(fileName);// 讀入文件 img = ImageIO.read(file); // 構造Image對象 width = img.getWidth(null); // 獲得源圖寬 height = img.getHeight(null); // 獲得源圖長 } /** * 按照寬度仍是高度進行壓縮 * @param w int 最大寬度 * @param h int 最大高度 */ public void resizeFix(int w, int h) throws IOException { if (width / height > w / h) { resizeByWidth(w); } else { resizeByHeight(h); } } /** * 以寬度爲基準,等比例放縮圖片 * @param w int 新寬度 */ public void resizeByWidth(int w) throws IOException { int h = (int) (height * w / width); resize(w, h); } /** * 以高度爲基準,等比例縮放圖片 * @param h int 新高度 */ public void resizeByHeight(int h) throws IOException { int w = (int) (width * h / height); resize(w, h); } /** * 強制壓縮/放大圖片到固定的大小 * @param w int 新寬度 * @param h int 新高度 */ public void resize(int w, int h) throws IOException { // SCALE_SMOOTH 的縮略算法 生成縮略圖片的平滑度的 優先級比速度高 生成的圖片質量比較好 但速度慢 BufferedImage image = new BufferedImage(w, h,BufferedImage.TYPE_INT_RGB ); image.getGraphics().drawImage(img, 0, 0, w, h, null); // 繪製縮小後的圖 File destFile = new File("C:\\temp\\456.jpg"); FileOutputStream out = new FileOutputStream(destFile); // 輸出到文件流 // 能夠正常實現bmp、png、gif轉jpg JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(image); // JPEG編碼 out.close(); } }
運行後在C盤temp下生成一個465.jpg,像素大小爲600*400,像素大小是我指定的。用時也就是一兩秒的事情,注意,我這張圖片是10M的,壓縮後是40.5KB。
一些細節事項能夠參考代碼中的註釋。
要注意的是,你可能想試一試較大圖片的處理能力,若是你的JDK沒有指定默認內存,那可能會有以下異常,由於內存不夠大:
開始:2014-4-14 16:25:11 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.awt.image.DataBufferByte.<init>(DataBufferByte.java:58) at java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:397) at java.awt.image.Raster.createWritableRaster(Raster.java:938) at javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1169) at javax.imageio.ImageReader.getDestination(ImageReader.java:2879) at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:943) at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:915) at javax.imageio.ImageIO.read(ImageIO.java:1422) at javax.imageio.ImageIO.read(ImageIO.java:1282) at test.ImgCompress.<init>(ImgCompress.java:31) at test.ImgCompress.main(ImgCompress.java:21)
解決方法:
在Eclipse裏選:Window->Preference->Installed JREs->Edit(選中jre),
在Default VM Arguments裏輸入-Xms256m -Xmx1024m,表示最小內存256M,最大1G,而後運行就能夠了