zoukankan      html  css  js  c++  java
  • java图片上传压缩处理

        过去做的项目都是针对企业级应用,第一次开发新闻版块图片上传的功能,需要解决用户上传图片后,按照用户规定的尺寸大小或者按照图片比例,对图片进行压缩。

        自己试写的工具类,写的时候考虑了几个关键点:

        1、图片格式

        JAVA的API很好,com.sun.image.codec.jpeg.JPEGCodec和com.sun.image.codec.jpeg.JPEGImageEncoder 这两个类基本上自动解决了类型转换的问题,可以正常实现bmp转jpg、png转jpg、gif转jpg但是暂时还没有解决gif转gif的功能。

        2、画面质量的问题

        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);

        3、压缩速度

        测试36MB的bmp图片(8192*6144)压缩成(160*120)的jpg的5KB图片,只需要2-3秒的时间。批量处理100张(1027*768)的bmp图像,转换成(120*80)的jpg图片总共只需要17秒。

        4、根据用户喜好选择压缩模式

        按比例或者按规定尺寸

        //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,然后运行就可以了

    原文:http://cuisuqiang.iteye.com/blog/2045855

  • 相关阅读:
    [转发]深入理解git,从研究git目录开始
    iOS系统网络抓包方法
    charles抓包工具
    iOS多线程中performSelector: 和dispatch_time的不同
    IOS Core Animation Advanced Techniques的学习笔记(五)
    IOS Core Animation Advanced Techniques的学习笔记(四)
    IOS Core Animation Advanced Techniques的学习笔记(三)
    IOS Core Animation Advanced Techniques的学习笔记(二)
    IOS Core Animation Advanced Techniques的学习笔记(一)
    VirtualBox复制CentOS后提示Device eth0 does not seem to be present的解决方法
  • 原文地址:https://www.cnblogs.com/vaer/p/4337995.html
Copyright © 2011-2022 走看看