一、前言
通过jdk的开发包com.sun.image.codec.jpeg.JPEGImageEncoder、com.sun.image.codec.jpeg.JPEGCodec图像压缩器对java.awt.Graphics/java.awt.Image渲染的图形图像,进行图像质量尺寸压缩、图像JPG/PNG/GIF等格式间转换、gif动画图像缩放等(如需对图片任意裁剪处理请参考"通过java.awt.Graphics/image定义CropImageUtil图片剪切工具类进行图片任意截切处理代码示例"文章)。
二、代码示例
import java.awt.Color;@b@import java.awt.Component;@b@import java.awt.Graphics;@b@import java.awt.Graphics2D;@b@import java.awt.Image;@b@import java.awt.MediaTracker;@b@import java.awt.Toolkit;@b@import java.awt.image.BufferedImage;@b@import java.awt.image.ConvolveOp;@b@import java.awt.image.Kernel;@b@import java.io.ByteArrayOutputStream;@b@import java.io.File;@b@import java.io.FileInputStream;@b@import java.io.FileOutputStream;@b@import java.io.IOException;@b@import java.io.OutputStream; @b@import javax.imageio.ImageIO;@b@import javax.swing.ImageIcon; @b@import com.sun.image.codec.jpeg.JPEGCodec;@b@import com.sun.image.codec.jpeg.JPEGEncodeParam;@b@import com.sun.image.codec.jpeg.JPEGImageEncoder;@b@@b@/**@b@ * 图像压缩工具 @b@ */@b@public class ImageSizer {@b@@b@ /**@b@ * 压缩图片方法@b@ * @b@ * @param oldFile 将要压缩的图片@b@ * @param width 不能超过的最大压缩宽@b@ * @param height 不能超过的最大压缩长@b@ * @param quality 压缩清晰度 <b>建议为1.0</b>@b@ * @param smallIcon 压缩图片后,添加的扩展名@b@ * @return@b@ * @throws IOException @b@ */@b@ public static void imageZip(File oldFile, File destFile, String format, int maxWidth, int maxHeight, float quality) throws IOException {@b@ FileOutputStream out = null;@b@ try {@b@ // 文件不存在时@b@ if (!oldFile.exists())@b@ return;@b@ /** 对服务器上的临时文件进行处理 */@b@ Image srcFile = ImageIO.read(oldFile);@b@ int new_w = 0, new_h = 0;@b@ // 获取图片的实际大小 高度@b@ int h = (int) srcFile.getHeight(null);@b@ // 获取图片的实际大小 宽度@b@ int w = (int) srcFile.getWidth(null);@b@ // 为等比缩放计算输出的图片宽度及高度@b@ if ((((double) w) > (double) maxWidth) || (((double) h) > (double) maxHeight)) {@b@ // 为等比缩放计算输出的图片宽度及高度@b@ double rateW = ((double) srcFile.getWidth(null)) / (double) maxWidth * 1.0;@b@ double rateH = ((double) srcFile.getHeight(null)) / (double) maxHeight * 1.0;@b@ // 根据缩放比率大的进行缩放控制@b@ //double rate = rateW > rateH ? rateW : rateH;@b@ double rate;@b@ char zipType;@b@ if(rateW > rateH){@b@ rate = rateW;@b@ zipType = 'W';@b@ } else {@b@ rate = rateH;@b@ zipType = 'H';@b@ }@b@ new_w = (int) (((double) srcFile.getWidth(null)) / rate);@b@ new_h = (int) (((double) srcFile.getHeight(null)) / rate);@b@ @b@ double rate2 = 0;@b@ if(zipType == 'W' && new_h > maxHeight){@b@ rate = (double) new_h / (double) maxHeight * 1.0;@b@ } else if(zipType == 'H' && new_w > maxWidth){@b@ rate = (double) new_w / (double) maxWidth * 1.0;@b@ }@b@ if(rate2 != 0){@b@ new_w = (int) (((double) new_w) / rate);@b@ new_h = (int) (((double) new_h) / rate);@b@ System.out.println("2次修改宽高。");@b@ }@b@ } else {@b@ new_w = w;@b@ new_h = h;@b@ }@b@ @b@ if ( new_w < 1 ) @b@ throw new IllegalArgumentException( "image width " + new_w + " is out of range" );@b@ if ( new_h < 1 ) @b@ throw new IllegalArgumentException( "image height " + new_h + " is out of range" );@b@@b@ /** 宽,高设定 */@b@ BufferedImage tag = new BufferedImage(new_w, new_h,@b@ BufferedImage.TYPE_INT_RGB);@b@ tag.getGraphics().drawImage(srcFile, 0, 0, new_w, new_h, null);@b@ @b@ out = new FileOutputStream(destFile);@b@ JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);@b@ JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag);@b@ /** 压缩质量 */@b@ jep.setQuality(quality, true);@b@ encoder.encode(tag, jep);@b@ out.close();@b@ srcFile.flush();@b@ } finally{@b@ if(out != null)out.close();@b@ }@b@ }@b@@b@ @b@ public static final MediaTracker tracker = new MediaTracker(new Component() {@b@ private static final long serialVersionUID = 1234162663955668507L;} @b@ );@b@ @b@ @b@ /**@b@ * @param originalFile 原图像@b@ * @param resizedFile 压缩后的图像@b@ * @param width 图像宽@b@ * @param format 图片格式 jpg, png, gif(非动画)@b@ * @throws IOException@b@ */@b@ public static void resize(File originalFile, File resizedFile, int width, String format) throws IOException {@b@ FileInputStream fis = null;@b@ ByteArrayOutputStream byteStream = null;@b@ try{@b@ if(format!=null && "gif".equals(format.toLowerCase())){@b@ resize(originalFile, resizedFile, width, 1);@b@ return;@b@ }@b@ fis = new FileInputStream(originalFile);@b@ byteStream = new ByteArrayOutputStream();@b@ int readLength = -1;@b@ int bufferSize = 1024;@b@ byte bytes[] = new byte[bufferSize];@b@ while ((readLength = fis.read(bytes, 0, bufferSize)) != -1) {@b@ byteStream.write(bytes, 0, readLength);@b@ }@b@ byte[] in = byteStream.toByteArray();@b@ fis.close();@b@ byteStream.close();@b@ @b@ Image inputImage = Toolkit.getDefaultToolkit().createImage( in );@b@ waitForImage( inputImage );@b@ int imageWidth = inputImage.getWidth( null );@b@ if ( imageWidth < 1 ) @b@ throw new IllegalArgumentException( "image width " + imageWidth + " is out of range" );@b@ int imageHeight = inputImage.getHeight( null );@b@ if ( imageHeight < 1 ) @b@ throw new IllegalArgumentException( "image height " + imageHeight + " is out of range" );@b@ @b@ // Create output image.@b@ int height = -1;@b@ double scaleW = (double) imageWidth / (double) width;@b@ double scaleY = (double) imageHeight / (double) height;@b@ if (scaleW >= 0 && scaleY >=0) {@b@ if (scaleW > scaleY) {@b@ height = -1;@b@ } else {@b@ width = -1;@b@ }@b@ }@b@ Image outputImage = inputImage.getScaledInstance( width, height, java.awt.Image.SCALE_DEFAULT);@b@ checkImage( outputImage ); @b@ encode(new FileOutputStream(resizedFile), outputImage, format); @b@ }finally{@b@ try {@b@ if(byteStream != null) {@b@ byteStream.close();@b@ }@b@ if(fis != null) {@b@ fis.close();@b@ }@b@ } catch (IOException e) {@b@ e.printStackTrace();@b@ }@b@ }@b@ } @b@@b@ /** Checks the given image for valid width and height. */@b@ private static void checkImage( Image image ) {@b@ waitForImage( image );@b@ int imageWidth = image.getWidth( null );@b@ if ( imageWidth < 1 ) @b@ throw new IllegalArgumentException( "image width " + imageWidth + " is out of range" );@b@ int imageHeight = image.getHeight( null );@b@ if ( imageHeight < 1 ) @b@ throw new IllegalArgumentException( "image height " + imageHeight + " is out of range" );@b@ }@b@@b@ /** Waits for given image to load. Use before querying image height/width/colors. */@b@ private static void waitForImage( Image image ) {@b@ try {@b@ tracker.addImage( image, 0 );@b@ tracker.waitForID( 0 );@b@ tracker.removeImage(image, 0);@b@ } catch( InterruptedException e ) { e.printStackTrace(); }@b@ } @b@@b@ /** Encodes the given image at the given quality to the output stream. */@b@ private static void encode( OutputStream outputStream, Image outputImage, String format ) @b@ throws java.io.IOException {@b@ try {@b@ int outputWidth = outputImage.getWidth( null );@b@ if ( outputWidth < 1 ) @b@ throw new IllegalArgumentException( "output image width " + outputWidth + " is out of range" );@b@ int outputHeight = outputImage.getHeight( null );@b@ if ( outputHeight < 1 ) @b@ throw new IllegalArgumentException( "output image height " + outputHeight + " is out of range" );@b@ @b@ // Get a buffered image from the image.@b@ BufferedImage bi = new BufferedImage( outputWidth, outputHeight,@b@ BufferedImage.TYPE_INT_RGB ); @b@ Graphics2D biContext = bi.createGraphics();@b@ biContext.drawImage( outputImage, 0, 0, null );@b@ ImageIO.write(bi, format, outputStream);@b@ outputStream.flush(); @b@ }finally{@b@ if(outputStream != null) {@b@ outputStream.close();@b@ }@b@ }@b@ } @b@ @b@ /**@b@ * 缩放gif图片@b@ * @param originalFile 原图片@b@ * @param resizedFile 缩放后的图片@b@ * @param newWidth 宽度@b@ * @param quality 缩放比例 (等比例)@b@ * @throws IOException@b@ */@b@ private static void resize(File originalFile, File resizedFile, int newWidth, float quality) throws IOException {@b@ if (quality < 0 || quality > 1) {@b@ throw new IllegalArgumentException("Quality has to be between 0 and 1");@b@ } @b@ ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());@b@ Image i = ii.getImage();@b@ Image resizedImage = null; @b@ int iWidth = i.getWidth(null);@b@ int iHeight = i.getHeight(null); @b@ if (iWidth > iHeight) {@b@ resizedImage = i.getScaledInstance(newWidth, (newWidth * iHeight) / iWidth, Image.SCALE_SMOOTH);@b@ } else {@b@ resizedImage = i.getScaledInstance((newWidth * iWidth) / iHeight, newWidth, Image.SCALE_SMOOTH);@b@ } @b@ // This code ensures that all the pixels in the image are loaded.@b@ Image temp = new ImageIcon(resizedImage).getImage(); @b@ // Create the buffered image.@b@ BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null), temp.getHeight(null),@b@ BufferedImage.TYPE_INT_RGB); @b@ // Copy image to buffered image.@b@ Graphics g = bufferedImage.createGraphics(); @b@ // Clear background and paint the image.@b@ g.setColor(Color.white);@b@ g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));@b@ g.drawImage(temp, 0, 0, null);@b@ g.dispose(); @b@ // Soften.@b@ float softenFactor = 0.05f;@b@ float[] softenArray = {0, softenFactor, 0, softenFactor, 1-(softenFactor*4), softenFactor, 0, softenFactor, 0};@b@ Kernel kernel = new Kernel(3, 3, softenArray);@b@ ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);@b@ bufferedImage = cOp.filter(bufferedImage, null); @b@ // Write the jpeg to a file.@b@ FileOutputStream out = new FileOutputStream(resizedFile); @b@ // Encodes image as a JPEG data stream@b@ JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); @b@ JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage); @b@ param.setQuality(quality, true); @b@ encoder.setJPEGEncodeParam(param);@b@ encoder.encode(bufferedImage);@b@ }@b@ @b@ @b@ /**@b@ * 图片缩放(图片等比例缩放为指定大小,空白部分以白色填充)@b@ * @b@ * @param srcBufferedImage 源图片@b@ * @param destFile缩放后的图片文件@b@ * @param destHeight@b@ * @param destWidth@b@ */@b@ public static void zoom(BufferedImage srcBufferedImage, File destFile, String format, int destHeight, int destWidth) {@b@ try {@b@ int imgWidth = destWidth;@b@ int imgHeight = destHeight;@b@ int srcWidth = srcBufferedImage.getWidth();@b@ int srcHeight = srcBufferedImage.getHeight();@b@ double scaleW = destWidth * 1.0 / srcWidth;@b@ double scaleH = destHeight * 1.0 / srcHeight;@b@ if (scaleW >= scaleH) {@b@ double imgWidth1 = scaleH * srcWidth;@b@ double imgHeight1 = scaleH * srcHeight; @b@ imgWidth = (int)imgWidth1;@b@ imgHeight = (int)imgHeight1;@b@ } else {@b@ double imgWidth1 = scaleW * srcWidth;@b@ double imgHeight1 = scaleW * srcHeight; @b@ imgWidth = (int)imgWidth1;@b@ imgHeight = (int)imgHeight1;@b@ }@b@ BufferedImage destBufferedImage = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);@b@ Graphics2D graphics2D = destBufferedImage.createGraphics();@b@ graphics2D.setBackground(Color.WHITE); @b@ graphics2D.clearRect(0, 0, destWidth, destHeight);@b@ graphics2D.drawImage(srcBufferedImage.getScaledInstance(imgWidth, imgHeight, Image.SCALE_SMOOTH), (destWidth / 2) - (imgWidth / 2), (destHeight / 2) - (imgHeight / 2), null);@b@ graphics2D.dispose();@b@ ImageIO.write(destBufferedImage, format, destFile);@b@ } catch (IOException e) {@b@ e.printStackTrace();@b@ }@b@ }@b@}