ImageIO.read()和ImageIO.write()图片失真。

  • • 发表于2020-10-14 11:39:23.0
  • • 作者 勇气
  • • 84 次浏览
  • • 0 条评论
  • • 最后编辑时间 2020-10-14 11:47:31.0
  • • 来自 [笔 记]

原创声明:本文为作者原创,未经允许不得转载,经授权转载需注明作者和出处

最近在做一个需求,通过一个接口上传图片到服务器(window系统)的外部路径,然后再通过调用另一个接口,通过绝对路径url,把图片流输出到servlet中返回给前端。
同事的代码使用了JImageIO.read()先读取了图片的文件流,再使用ImageIO.write()把图片流输出到Servlet中,代码如下:
   @GetMapping("/showBanner")
   public void showBanner(String url, HttpServletResponse response) throws IOException {
        //参数url是服务上图片的绝对路径
        url = FileUtils.verifyPathWarn(url);
        // 载入图像
        FileInputStream fileInputStream = new FileInputStream(url);
        BufferedImage buffImg = ImageIO.read(fileInputStream);

        // 禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        // 将图像输出到Servlet输出流中。
        ServletOutputStream sos = response.getOutputStream();
        ImageIO.write(buffImg, "jpeg", sos);
        sos.close();
        if (fileInputStream != null) {
            fileInputStream.close();
        }
    }
上面这段代码是可以获得图片的,但是发现获得的图片会变成红色。于是百度了一下,找到了更好的方法。那就是先使用java.awt.Toolkit处理为Image,再转换为BufferedImage后,再使用ImageIO.write()输出,这样图片就不会变红,修改后代码如下:
    @GetMapping("/showBanner")
    public void showBanner(String url, HttpServletResponse response) throws IOException {
        //参数url是服务上图片的绝对路径
        url = FileUtils.verifyPathWarn(url);

        Image img = Toolkit.getDefaultToolkit().getImage(url);
        BufferedImage buffImg = toBufferedImage(img);
        // 禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        // 将图像输出到Servlet输出流中。
        ServletOutputStream sos = response.getOutputStream();
        ImageIO.write(buffImg, "jpeg", sos);
        sos.close();
    }

    /**
     * 把Image转换成BufferedImage
    **/
    public BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        image = new ImageIcon(image).getImage();
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                    image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
             e.printStackTrace();
            logger.error("Image图片转换为BufferedImage错误:" + e.getMessage());
        }
        if (bimage == null) {
            int type = BufferedImage.TYPE_INT_RGB;
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }
        Graphics g = bimage.createGraphics();

        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }

参考链接:
https://blog.csdn.net/shixing_11/article/details/6897871
https://blog.csdn.net/u012371450/article/details/105867577

ps:
项目环境和框架:spring boot + mybatis + shiro(权限控制) + jdk1.8

这个需求其实可以考虑直接在shiro配置中加上配置结合配置前端的webMvcConfigurerAdapter来处理。但是由于原本项目已经采用上面的方法,加上其他的限制,所以就延用此方法。
参考链接:
https://www.jianshu.com/p/7f92de7c9aff
https://blog.csdn.net/wanglong1990421/article/details/100020771

评论区(共0条评论)
0条评论
Ctrl+Enter
作者

Michael

勇气

帖子:2 回复:0

这个人很懒,什么都没留下

作者详情》
Top