我正在尝试使用Java ImageIO
复制大量图像。每个副本都会调整原始图片的大小。由于图像集的大小很大(60,000)。我尝试使用多线程来解决问题。这是代码:
package generate.image
import scala.util.Random._
import scala.math._
import java.io.File
import java.io.PrintWriter
import java.util.concurrent.{ExecutorService, TimeUnit, Executors}
import java.awt.Image
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
class ImageResizer{
def resizeImage(srcImgPath: String, distImgPath: String, width: Int, height: Int){
val srcFile: File = new File(srcImgPath)
val srcImg: Image = ImageIO.read(srcFile)
val buffImg: BufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
buffImg.getGraphics().drawImage(
srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0,
0, null
)
ImageIO.write(buffImg, "JPEG", new File(distImgPath))
}
}
class ImageWorker(imgSrc: String, imgName: String, width: Int, height: Int) extends Runnable{
override def run(): Unit = {
val resizer = new ImageResizer()
resizer.resizeImage(imgSrc, imgName, width, height);
}
}
object ImageGenerate {
def main(args:Array[String]): Unit = {
// parameters
val dirName = args(0)
val images = new File(dirName).listFiles.filter(_.getName.endsWith(".JPEG"))
val imgCnt = images.length
// threadpool
val pool = Executors.newFixedThreadPool(25)
// copy with norm
for(i <- 0 until imgCnt){
for(cnt <- 1 to 20){
val width = nextInt(200) + 300
val height = nextInt(200) + 300
val imgSrc: String = images(i).getAbsolutePath
val imgName: String = "img/%s_%d_%d_%d.JPEG".format(splitFilename(images(i).getName), width, height, cnt)
pool.execute(new ImageWorker(imgSrc, imgName, width, height))
}
}
pool.shutdown()
pool.awaitTermination(Long.MaxValue, TimeUnit.NANOSECONDS)
}
// split file name
def splitFilename(fileName: String) = {
fileName.substring(0, fileName.lastIndexOf("."))
}
}
ImageResizer
复制工作。它将图像读入BufferedImage
,将其大小调整为新的BufferedImage
,最后写入JPEG
文件。
ImageWorker
线程有效。它由ExecuteServive
中的工作线程执行。
ImageGenerate
执行调度工作。它会读取args(0)
(第一个arg)中的所有图像文件,生成新的随机宽度和高度,并将新作业提交给pool
。
编译并运行:scalac ImageGenerate.scala
scala generate.image.ImageGenerate test
。图像的大小平均为150kb。
正在运行,程序抛出java.lang.OutOfMemoryError
。
有时会出现Exception in thread "pool-1-thread-36" java.lang.OutOfMemoryError: GC overhead limit exceeded
错误。
如果我设置参数-J-Xmx2048m
,程序将顺利运行。但是,我只运行了400张图像。我的代码有优化吗?
感谢您分享您的想法,祝福。
答案 0 :(得分:1)
您应该致电dispose()
像这样(未经测试)
val graphics = buffImg.getGraphics()
graphics.drawImage(
srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0,
0, null
)
ImageIO.write(buffImg, "JPEG", new File(distImgPath))
graphics.dispose()