Java图片处理/压缩

jopen 7年前

图片压缩分为无损有损压缩处理。

  • 首先考虑用开源的或商业的jar包。

1.thumbnailator-0.4.2-all.jar

2.图片压缩:magickimage 

Java图片处理/压缩:ImageMagick for java 使用Jmagick压缩高质量图片(包括Jmagick的应用)

ImageMagick for java 使用Jmagick压缩高质量图片j

在做pdf文档转成jpg的时候,发现了Jmagick的创建高质量的图片的一个java类库,自己以前使用另外的一个类库,感觉这个更好点,就试着用了下,感觉不错

1.使用的windows下的jmagick-win-6.3.9-Q16.zip 地址是:http://downloads.jmagick.org/6.3.9/

2.doc对应的api地址:http://downloads.jmagick.org/jmagick-doc/

3.安装ImageMagick,官方网站:http://www.imagemagick.org/

我使用的是:ImageMagick-6.4.6-4-Q16-windows-dll.exe :点击下载

4. 安装ImageMagick-6.4.6-4-Q16-windows-dll.exe,将 安装目录下(按自己所安装的目录找) 下的所有dll文件 copy 到系统盘下的 “C:\WINDOWS\system32\”文件夹里

5. 配置环境变量
再环境变量path里添加新的值 “C:\Program Files\ImageMagick-6.4.6-4-Q16“使用IDE可以不用配置

6.解压jmagick-win-6.3.9-Q16.zip
将 jmagick.dll 复制到系统盘下的 “C:\WINDOWS\system32\”文件夹里 和 复制到jdk的bin(例“D:\jdk6\bin”)文件里各一份
将 jmagick.jar 复制到Tomcat下的lib文件夹里 和 所使用项目的WEB-INF下lib文件里 各一份

7.web应用如果部署到tomcat下,那么最好在catalina.bat文件中改变如下设置
set JAVA_OPTS=%JAVA_OPTS% -Xms256M -Xmx768M -XX:MaxPermSize=128M – Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager – Djava.util.logging.config.file=”${catalina.base}\conf\logging.properties”
避免heap溢出的问题,参数看你自己的机器而定。( -Xms256M -Xmx768M -XX:MaxPermSize=128M )

8.还要注意如果部署到web应用,你在使用的class里面需要
System.setProperty(“jmagick.systemclassloader”,”no”);
要不然会报出UnsatisfiedLinkError: no JMagick in java.library.path.
实例测试code:

    
    package com.utils;     import magick.ImageInfo;  import magick.MagickApiException;  import magick.MagickException;  import magick.MagickImage;     public class Treamspdf {   public static void main(String[] args) {  resetsize("E:/mylearn/workspace/TTPDF/src/com/utils/http_imgload.jpg","new.jpg");  }   public static void resetsize(String picFrom,String picTo){    try{     ImageInfo info=new ImageInfo(picFrom);     MagickImage image=new MagickImage(new ImageInfo(picFrom));     MagickImage scaled=image.scaleImage(120, 97);     scaled.setFileName(picTo);     scaled.writeImage(info);    }catch(MagickApiException ex){     ex.printStackTrace();    } catch(MagickException   ex)   {     ex.printStackTrace();    }   }  }

常用的水印,切图,压缩等简单程序工具类,继续下面

package com.utils;        import java.awt.Dimension;  import java.awt.Rectangle;  import java.text.SimpleDateFormat;  import java.util.Date;        import magick.CompositeOperator;  import magick.CompressionType;  import magick.DrawInfo;  import magick.ImageInfo;  import magick.MagickException;  import magick.MagickImage;  import magick.PixelPacket;  import magick.PreviewType;        public class Aa {            static{          //不能漏掉这个,不然jmagick.jar的路径找不到          System.setProperty("jmagick.systemclassloader","no");      }            /**       * 压缩图片       * @param filePath 源文件路径       * @param toPath   缩略图路径       */      public static void createThumbnail(String filePath, String toPath) throws MagickException{          ImageInfo info = null;          MagickImage image = null;          Dimension imageDim = null;          MagickImage scaled = null;          try{              info = new ImageInfo(filePath);              image = new MagickImage(info);              imageDim = image.getDimension();              int wideth = imageDim.width;              int height = imageDim.height;              if (wideth > height) {                  height = 660 * height / wideth;                  wideth = 660;              }              scaled = image.scaleImage(wideth, height);//小图片文件的大小.              scaled.setFileName(toPath);              scaled.writeImage(info);          }finally{              if(scaled != null){                  scaled.destroyImages();              }          }      }            /**       * 水印(图片logo)       * @param filePath  源文件路径       * @param toImg     修改图路径       * @param logoPath  logo图路径       * @throws MagickException       */      public static void initLogoImg(String filePath, String toImg, String logoPath) throws MagickException {          ImageInfo info = new ImageInfo();          MagickImage fImage = null;          MagickImage sImage = null;          MagickImage fLogo = null;          MagickImage sLogo = null;          Dimension imageDim = null;          Dimension logoDim = null;          try {              fImage = new MagickImage(new ImageInfo(filePath));              imageDim = fImage.getDimension();              int width = imageDim.width;              int height = imageDim.height;              if (width > 660) {                  height = 660 * height / width;                  width = 660;              }              sImage = fImage.scaleImage(width, height);                    fLogo = new MagickImage(new ImageInfo(logoPath));              logoDim = fLogo.getDimension();              int lw = width / 8;              int lh = logoDim.height * lw / logoDim.width;              sLogo = fLogo.scaleImage(lw, lh);                    sImage.compositeImage(CompositeOperator.AtopCompositeOp, sLogo,  width-(lw + lh/10), height-(lh + lh/10));              sImage.setFileName(toImg);              sImage.writeImage(info);          } finally {              if(sImage != null){                  sImage.destroyImages();              }          }      }            /**       * 水印(文字)          * @param filePath 源文件路径       * @param toImg    修改图路径       * @param text     名字(文字内容自己随意)       * @throws MagickException       */      public static void initTextToImg(String filePath, String toImg,  String text) throws MagickException{              ImageInfo info = new ImageInfo(filePath);              if (filePath.toUpperCase().endsWith("JPG") || filePath.toUpperCase().endsWith("JPEG")) {                  info.setCompression(CompressionType.JPEGCompression); //压缩类别为JPEG格式                  info.setPreviewType(PreviewType.JPEGPreview); //预览格式为JPEG格式                  info.setQuality(95);              }              MagickImage aImage = new MagickImage(info);              Dimension imageDim = aImage.getDimension();              int wideth = imageDim.width;              int height = imageDim.height;              if (wideth > 660) {                  height = 660 * height / wideth;                  wideth = 660;              }              int a = 0;              int b = 0;              String[] as = text.split("");              for (String string : as) {                  if(string.matches("[\u4E00-\u9FA5]")){                      a++;                  }                  if(string.matches("[a-zA-Z0-9]")){                      b++;                  }              }              int tl = a*12 + b*6 + 300;              MagickImage scaled = aImage.scaleImage(wideth, height);              if(wideth > tl && height > 5){                  DrawInfo aInfo = new DrawInfo(info);                  aInfo.setFill(PixelPacket.queryColorDatabase("white"));                  aInfo.setUnderColor(new PixelPacket(0,0,0,100));                  aInfo.setPointsize(12);                  //解决中文乱码问题,自己可以去随意定义个自己喜欢字体,我在这用的微软雅黑                  String fontPath = "C:/WINDOWS/Fonts/MSYH.TTF";  //              String fontPath = "/usr/maindata/MSYH.TTF";                  aInfo.setFont(fontPath);                  aInfo.setTextAntialias(true);                  aInfo.setOpacity(0);                  aInfo.setText(" " + text + "于 " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + " 上传于XXXX网,版权归作者所有!");                  aInfo.setGeometry("+" + (wideth-tl) + "+" + (height-5));                  scaled.annotateImage(aInfo);              }              scaled.setFileName(toImg);              scaled.writeImage(info);              scaled.destroyImages();      }            /**       * 切图       * @param imgPath 源图路径       * @param toPath  修改图路径       * @param w       * @param h       * @param x       * @param y       * @throws MagickException       */      public static void cutImg(String imgPath, String toPath, int w, int h, int x, int y) throws MagickException {          ImageInfo infoS = null;          MagickImage image = null;          MagickImage cropped = null;          Rectangle rect = null;          try {              infoS = new ImageInfo(imgPath);              image = new MagickImage(infoS);              rect = new Rectangle(x, y, w, h);              cropped = image.cropImage(rect);              cropped.setFileName(toPath);              cropped.writeImage(infoS);                } finally {              if (cropped != null) {                  cropped.destroyImages();              }          }      }  }



  • 其次自己写java代码:

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