java 缩略图 内存溢出_Java修改图片尺寸,总是报内存溢出怎么解决?

项目需求:有很多尺寸很大的图片(图片大小可能几十MB,甚至上百MB),需要等比例缩小它们的尺寸,相当于生成缩略图。

例如:原图8268x6201,需要压缩成400x300。

我现在的方法:将图片整个读入内存,然后修改宽、高,最后写回磁盘。

核心代码大概这样:BufferedImage oldImg = ImageIO.read(in);

BufferedImage newImg = new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);

Graphs2D g = newImg.createGraphics();

g.drawImage(oldImg, 0, 0, 400, 300, null);

g.dispose();

ImageIO.write(newImg, 'jpg', new BufferedStream(out));

但是由于图片本身很大,而且可能会同时有多个线程在转,所以频繁发生内存溢出,报错:java.lang.OutOfMemoryError: Java heap space.

尝试:我试过增大分配给JVM的内存,但是效果不明显。首先机器内存有限,不可能无限增加。而且图片的大小没有上限,所以此方法不能很好地解决问题。

理想的情况,应该是通过一种“流式的算法”,一边把原始图片从磁盘读到内存,一边修改尺寸,一边写到磁盘生成目标图片。这种算法理论上只需要常数级内存空间。不过我在网上找了很久也没有找到。

我对图形学、图片格式、图片处理相关的知识不熟悉,不知道是否存在这样的算法,以及Java是否支持这样的算法。在此请教大家。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当处理大量图片生成缩略图时,如果不注意内存的管理,很容易导致内存溢出。以下是一个避免内存溢出Java多线程生成缩略图的例子: ```java import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThumbnailGenerator { private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors(); public static void generateThumbnails(String[] imagePaths, String outputDirectory, int thumbnailWidth, int thumbnailHeight) { ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE); for (String imagePath : imagePaths) { executor.execute(() -> { try { generateThumbnail(imagePath, outputDirectory, thumbnailWidth, thumbnailHeight); } catch (IOException e) { e.printStackTrace(); } }); } executor.shutdown(); while (!executor.isTerminated()) { // 等待所有任务完成 } } private static void generateThumbnail(String imagePath, String outputDirectory, int thumbnailWidth, int thumbnailHeight) throws IOException { BufferedImage originalImage = ImageIO.read(new File(imagePath)); int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType(); BufferedImage resizedImage = new BufferedImage(thumbnailWidth, thumbnailHeight, type); Graphics2D g = resizedImage.createGraphics(); g.drawImage(originalImage, 0, 0, thumbnailWidth, thumbnailHeight, null); g.dispose(); String outputFilePath = outputDirectory + File.separator + getFileName(imagePath); ImageIO.write(resizedImage, "jpg", new File(outputFilePath)); } private static String getFileName(String filePath) { File file = new File(filePath); return file.getName(); } } ``` 在这个例子中,我们使用了`ExecutorService`来创建一个固定大小的线程池。然后,我们遍历所有的图片路径,并将生成缩略图的任务提交给线程池进行处理。 在`generateThumbnail`方法中,我们使用`ImageIO.read`读取原始图片,并根据指定的宽度和高度创建一个新的缩略图。然后,我们将原始图片绘制到缩略图中,并将缩略图保存到指定的输出目录。 最后,在`generateThumbnails`方法中,我们等待所有任务完成后关闭线程池。 使用这个例子,你可以在处理大量图片生成缩略图时避免内存溢出。你可以调整线程池的大小来适应你的需求,并根据需要修改生成缩略图的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值