zoukankan      html  css  js  c++  java
  • 一次线上图片打印失败问题排查

    01 问题由来

    昨天产品在测试系统的时候,提了个bug,有个功能打印图片时,图片无法显示。为了重现这个bug,特意去测试环境看了下,还真存在,于是去看错误日志,发现报异常了。

    在某个类的某一行,有这个java.lang.ClassNotFoundException: com.sun.image.codec.jpeg.JPEGCodec报错信息,于是启动开发环境,打好断点,开始调试。

    JPEGCodeccom.sun.image.codec.jpeg包下面的,在jdk1.6及以前的版本中都可以正常使用,但是在jdk1.7以上的版本中,就被移除了,但是在jre中的rt.jar包中,还是保留着。

    由于本地开发环境配置项目的依赖库时,用的时jre1.8的库,所以在开始调试的时候,一切正常,但是把依赖库切换到Java-SE-1.8的时候,直接编译报错了。

    02 旧的方法

    /**
     * 对图片进行压缩
     * @param filePath 图片文件路径
     * @param bufferedImg BufferedImage对象
     */
    public static void compressImage(String filePath, BufferedImage bufferedImg) {
    	FileOutputStream out = null;
    	try {
    		if (bufferedImg == null) {
    			return ;
    		}
    		out = new FileOutputStream(filePath);
    
    		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
    		JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(bufferedImg);
    		jep.setQuality(0.8f, true);
    		encoder.encode(bufferedImg, jep);
    	} catch (Exception e) {
    		e.printStackTrace();
    	} finally {
    		try {
    			if (out != null) {
    				out.close();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    03 使用ImageIO

    ImagegetScaledInstance(int width, int height, int hints)方法中,参数width是压缩图片的宽,参数height是压缩图片的高,参数hints是选择不同的压缩算法,有五种:SCALE_DEFAULTSCALE_FASTSCALE_SMOOTHSCALE_REPLICATESCALE_AREA_AVERAGING

    widthheight都为负数时,就使用原始图像尺寸,如果为正数且大小小于原始图片尺寸,就会在原图左上角部分覆盖。

    Image.SCALE_SMOOTH的缩略算法,生成缩略图片的平滑度的优先级比缩放速度高,生成的图片质量比较好,但速度慢。

    /**
     * 对图片进行压缩
     * @param filePath 图片文件路径
     * @param bufferedImg BufferedImage对象
     */
    public static void compressImage2(String filePath, BufferedImage bufferedImg) {
    	FileOutputStream out = null;
    	try {
    		if (bufferedImg == null) {
    			return ;
    		}
    		bufferedImg.getGraphics().drawImage(bufferedImg.getScaledInstance(-60, -60, bufferedImg.SCALE_SMOOTH), 0, 0, null);
    		out = new FileOutputStream(filePath);
    		ImageIO.write(bufferedImg, "jpeg", out);
    	} catch (Exception e) {
    		e.printStackTrace();
    	} finally {
    		try {
    			if (out != null) {
    				out.close();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    04 新旧方法测试

    编写main方法,找一张图片来测试下。

    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.imageio.ImageIO;
    
    import com.sun.image.codec.jpeg.JPEGCodec;
    import com.sun.image.codec.jpeg.JPEGEncodeParam;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
    
    /**
     * java.lang.ClassNotFoundException: com.sun.image.codec.jpeg.JPEGCodec
     * 
     * @author 小川
     * @date 2019-07-31 20:37:25
     */
    public class ImageIO_2019_07_31 {
    
        /**
         * 对图片进行压缩
         * 
         * @param filePath    图片文件路径
         * @param bufferedImg BufferedImage对象
         */
        public static void compressImage(String filePath, BufferedImage bufferedImg) {
            FileOutputStream out = null;
            try {
                if (bufferedImg == null) {
                    return;
                }
                out = new FileOutputStream(filePath);
    
                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(bufferedImg);
                jep.setQuality(0.8f, true);
                encoder.encode(bufferedImg, jep);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 对图片进行压缩
         * 
         * @param filePath    图片文件路径
         * @param bufferedImg BufferedImage对象
         */
        public static void compressImage2(String filePath, BufferedImage bufferedImg) {
            FileOutputStream out = null;
            try {
                if (bufferedImg == null) {
                    return;
                }
                /**
                 * Image.getScaledInstance(int width, int height, int hints)
                 * width、height都为负数,就使用原始图像尺寸,如果为正数且大小小于原始图片尺寸,就会在原图左上角部分覆盖
                 * Image.SCALE_SMOOTH的缩略算法,生成缩略图片的平滑度的优先级比缩放速度高,生成的图片质量比较好,但速度慢
                 */
                bufferedImg.getGraphics().drawImage(bufferedImg.getScaledInstance(-60, -60, bufferedImg.SCALE_SMOOTH), 0, 0, null);
                out = new FileOutputStream(filePath);
                ImageIO.write(bufferedImg, "jpeg", out);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 根据本地文件得到BufferedImage对象
         * 
         * @param filePath 图片文件路径
         * @return
         */
        public static BufferedImage getBufferedImageByExistFile(File file) {
            BufferedImage image = null;
            try {
                image = ImageIO.read(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return image;
        }
    
        public static void main(String[] args) {
            // 原图196kb
            String filePath = "E:\jumao.jpg";
            // 创建File对象
            File file = new File(filePath);
    
            // 获取BufferedImage对象
            BufferedImage bufferedImg = getBufferedImageByExistFile(file);
    
            // 原来的方法 143kb
            compressImage("E:\jumao01.jpg", bufferedImg);
    
            // 调用升级后的方法 107kb
            compressImage2("E:\jumao02.jpg", bufferedImg);
    
        }
    
    }
    

    在E盘中,生成了两张压缩后的图片,从图片的大小上来看,新方法是完胜旧方法的。

    如果你也有遇到过此问题,也可以使用上面的新方法,兼容性更好。

  • 相关阅读:
    bzoj4137[FJOI2015]火星商店问题
    HNOI2019游记
    bzoj4785:[ZJOI2017]树状数组:二维线段树
    快速傅里叶变换(FFT)
    动规大总结
    复习动规(4)
    复习动规(3)
    复习动规(2)
    复习动规(1)
    2019CSP-S游记(真)
  • 原文地址:https://www.cnblogs.com/xiaochuan94/p/11286577.html
Copyright © 2011-2022 走看看