JAVA语言如何对大图像进行转码、缩略处理

问题描述:大小在100M~2G,格式为tiff、tif的图片,需要转成web能够预览的格式为JPG或PNG,大小在500kb左右的图片

ImageIO类和Java Advanced Imaging Api可行,给你一个官方的案例:

File inputFile = new File("originalImage.tif");
BufferedImage inputImage = ImageIO.read(inputFile);

int newWidth = 800; 
int newHeight = 600; 
BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, inputImage.getType());
Graphics2D graphics2D = scaledImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(inputImage, 0, 0, newWidth, newHeight, null);
graphics2D.dispose();
File outputFile = new File("scaledImage.jpg");
ImageIO.write(scaledImage, "jpg", outputFile);


不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: Java实现图片(jpg/png)转成TIF格式(300dpi)踩坑笔记中的 3.2 工具类如下: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    	/**
         *
         * 功能描述: 图片转tif格式
         *
         * @param: [fileAbsolutePath]
         * @return: java.lang.String  转成TIF图片的地址全路径
         * @auther: KevinZc
         * @date: 2018/9/8 22:14
         */
        public String image2Tif(String fileAbsolutePath){
            OutputStream outputStream = null;
            String filterFilePath = null;
            String tifFilePath = null;
            ImageOutputStream ios = null;
            try {
                // 解决位深度太小 start ====注意:8位深度的图片会出现文件损坏问题
                File picture = new File(fileAbsolutePath);
                // 统一进行一次过滤 转换成24位深度
                filterFilePath = fileAbsolutePath.substring(0, fileAbsolutePath.lastIndexOf("."))+".JPG";
                tifFilePath = filterFilePath.substring(0, filterFilePath.lastIndexOf("."))+".tif";
                ios = ImageIO.createImageOutputStream(new File(filterFilePath));
                ImageIO.write(ImageIO.read(picture),"JPG", ios);
                // 解决位深度太小 end
                FileSeekableStream stream = new FileSeekableStream(filterFilePath);
                PlanarImage in = JAI.create("stream", stream);
                OutputStream os = null;
                os = new FileOutputStream(tifFilePath);
                // 设置dpi为300
                TIFFEncodeParam param = new TIFFEncodeParam();
                param.setCompression(TIFFEncodeParam.COMPRESSION_NONE);
                TIFFField[] extras = new TIFFField[2];
                extras[0] = new TIFFField(282, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) 300, 1}, {0, 0}});
    //            extras[0] = new TIFFField(282, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) dpi, 1}, {0, 0}});
                extras[1] = new TIFFField(283, TIFFTag.TIFF_RATIONAL, 1, (Object) new long[][]{{(long) 300, 1}, {0, 0}});
                param.setExtraFields(extras);
                TIFFImageEncoder enc = new TIFFImageEncoder(os, param);
                try {
                    enc.encode(in);
                    os.flush();
                    os.close();
                    stream.close();
                } catch (Exception e) {
                    logger.error("{}",e );
                    throw new RuntimeException(e);
                }
                return tifFilePath;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                    if (ios != null) {
                        ios.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    
  • 以下回答来自chatgpt:

    对于这个问题,可以使用Java的开源库ImageIO来实现TIF格式图像转码和缩略处理,并控制大小在500KB左右。

    以下是具体步骤:

    1. 加载TIF格式图像,使用ImageIO的read方法即可。
    File tifFile = new File("path/to/tif/file.tif");
    ImageInputStream input = ImageIO.createImageInputStream(tifFile);
    Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
    ImageReader reader = readers.next();
    reader.setInput(input);
    BufferedImage tifImage = reader.read(0);//读取第一帧,多帧需要循环读取
    
    1. 转换成JPG或PNG格式图像,并压缩大小。
    //根据需要转换成JPG或PNG格式
    BufferedImage outImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
    outImage.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(outImage, "jpg", baos);
    
    //压缩图片大小,控制在500KB以内
    long length = baos.toByteArray().length;
    double rate = Math.sqrt(500000d / length);
    if(rate > 1) {
        //如果小于500KB,则直接输出
        ImageIO.write(outImage, "jpg", response.getOutputStream());
    } else {
        //如果大于500KB,则缩小图片,再输出
        BufferedImage newImage = Thumbnails.of(outImage).scale(rate).asBufferedImage();
        ImageIO.write(newImage, "jpg", response.getOutputStream());
    }
    

    需要注意的问题:

    1. 对于大型TIF格式图像,在内存和CPU上会有较大压力,需要合理分配内存和处理线程,避免内存泄漏和程序崩溃。
    2. 图像转码和缩略处理需要一定时间,需要考虑使用多线程或异步处理来提高效率和用户体验。
    3. 对于不同的TIF格式图像,需要根据具体情况对转码和缩略处理的参数进行合理调整,以达到最优效果。

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

使用Image Optimizer