ImageIO - 读取不同的文件并发问题?
ImageIO - Read diferent files concurrency issue?
我目前正在编写一个程序,可以批量处理不同的图像。所以我认为并行执行操作(缩放/添加水印)可能会很聪明。
问题是我收到以下错误:
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:62)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:19)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.SequencesKt___SequencesKt.count(_Sequences.kt:1006)
at eu.reisihub.soft.watermarking.Main.main(Main.kt:66)
Caused by: java.lang.NullPointerException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
... 7 more
Caused by: java.lang.NullPointerException
at java.desktop/java.awt.color.ICC_Profile.intFromBigEndian(ICC_Profile.java:1784)
at java.desktop/java.awt.color.ICC_Profile.getNumComponents(ICC_Profile.java:1476)
at java.desktop/sun.java2d.cmm.lcms.LCMSTransform.<init>(LCMSTransform.java:93)
at java.desktop/sun.java2d.cmm.lcms.LCMS.createTransform(LCMS.java:173)
at java.desktop/java.awt.color.ICC_ColorSpace.fromRGB(ICC_ColorSpace.java:230)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.setImageData(JPEGImageReader.java:808)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:723)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:493)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:716)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1173)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1153)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1468)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1363)
at eu.reisihub.shot.UtilsKt.readImage(Utils.kt:19)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:18)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:8)
at eu.reisihub.soft.watermarking.Main$sam$java_util_concurrent_Callable[=10=].call(Main.kt)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
请注意,我知道 java.desktop/java.awt.color.ICC_Profile.intFromBigEndian(ICC_Profile.java:1784)
中有一个 NPE。相信我,这不是图片。
我尝试了 Java 8 和 Java 10 的两种方法。我有一个固定大小的线程池,其中 6 个线程用于 4 个内核。我使用 Kotlin 来实现并创建了一个扩展函数 fun Path.readImage(): BufferedImage
。对于不了解 Kotlin 的人,仅出于本示例的目的,大致对应于 public BufferedImage readImage(Path this)
.
天真的方法
使用 Files.newInputStream(this, StandardOpenOption.READ).use { ImageIO.read(it) }
读取文件。这从 Path 打开一个新的 InputStream 并告诉 ImageIO 从这个 InputStream 读取图像。看起来不错?在 Java 8 上每四次不工作,在 Java 10 上大约 90%。顺便说一句:如果我围绕它包装一个同步块,它会工作——总是。用 13 秒处理 17 张图像,而不是 7 秒。
与此同时,我将 Gradle 从 4.4 更新到 4.7。在我配置 IntelliJ 使用 Java 10 和 Gradle 使用 Java 8 之前。可能是上面突出显示的差异的原因。边注。我一直用 synchronized(System.err)
!
复杂的方法
知道它在同步所有内容时有效,我的方法现在看起来更复杂,像这样:
fun Path.readImage(): BufferedImage = Files.newInputStream(this, StandardOpenOption.READ).buffered().use {
var nStream: ImageInputStream? = null
var nReader: ImageReader? = null
synchronized(System.err) {
nStream = ImageIO.createImageInputStream(it) ?: throw IIOException("Can't create an ImageInputStream!")
val iter = ImageIO.getImageReaders(nStream)
if (!iter.hasNext()) {
throw IIOException("No image nReader found!")
}
nReader = iter.next()
}
nStream!!.let { stream ->
nReader!!.let { reader ->
reader.setInput(stream, true, true)
try {
println(reader)
return reader.read(0, null)
} finally {
reader.dispose()
stream.close()
}
}
}
}
看到代码中的println
了吗?我知道对于每个图像,一个新的 com.sun.imageio.plugins.jpeg.JPEGImageReader
对象是 created.This 将性能提高到我正在与之交谈的 7 秒。一般不工作2-4次然后工作6-10次
复杂版本的堆栈跟踪如下:
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:64)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:20)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.SequencesKt___SequencesKt.count(_Sequences.kt:1006)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:68)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:20)
at eu.reisihub.shot.UtilsKt.measured(Utils.kt:54)
at eu.reisihub.soft.watermarking.Main.main(Main.kt:24)
Caused by: java.lang.NullPointerException
at java.awt.color.ICC_Profile.intFromBigEndian(ICC_Profile.java:1782)
at java.awt.color.ICC_Profile.getNumComponents(ICC_Profile.java:1474)
at sun.java2d.cmm.lcms.LCMSTransform.<init>(LCMSTransform.java:98)
at sun.java2d.cmm.lcms.LCMS.createTransform(LCMS.java:173)
at java.awt.color.ICC_ColorSpace.fromRGB(ICC_ColorSpace.java:218)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.setImageData(JPEGImageReader.java:694)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:609)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:481)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:602)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1059)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039)
at eu.reisihub.shot.UtilsKt.readImage(Utils.kt:39)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:16)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:8)
at eu.reisihub.soft.watermarking.Main$sam$java_util_concurrent_Callable[=12=].call(Main.kt)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
其中 Main:64
是 Future#get
Main:68
是 kotlin.Sequence#count
我已经尝试改进代码几个小时了,现在我的脑子已经停止产生新的想法了。我知道错误也发生在 2 张图片上。由于它并不总是失败,因此 ICC 配置文件必须正确。我 - 老实说 - 考虑到我的硬盘驱动器不正常,偶尔会出现问题。我还尝试从我的 SSD 读取文件。根据 ,读取方法应该是线程安全的。我不知道发生了什么事。磁盘上的每个图像(由路径表示)都有自己的 Callable<Task>
。我只是阅读这些图像并将其写入不同的文件夹。因此,对于每个任务,一个文件被读取,一个文件被写入。这两个文件不一样,每个任务都有自己的文件。
他们唯一共享的是PNG格式的BufferedImage,绘制在读取图像(水印)上。但那是后来发生的。从堆栈跟踪中可以看出,它发生在读取 JPEG 图像时。
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039)
at eu.reisihub.shot.UtilsKt.readImage(Utils.kt:39)
创建主应用程序需要的路径的JSON设置
感谢任何意见。目前我不知道哪里出了问题...
顺便说一句:对于我正在使用的一些任务:https://github.com/coobird/thumbnailator
OpenJDK 有一个 bug report,标题为 'NullPointerException from ICC_Profile.getInstance() in multi-thread application'。在撰写本文时没有解决方案。
更新 2018-05-23
@haraldK 在评论中提到之前加载图像配置文件
代码:
import java.awt.color.ColorSpace
import java.awt.color.ICC_Profile
import java.awt.image.BufferedImage
import java.nio.file.Path
import javax.imageio.ImageIO
object ImgLoadUtils {
init {
// Load deferred color space profiles to avoid
// ConcurrentModificationException due to JDK
// Use in public static main void or prior to application initialization
// https://github.com/haraldk/TwelveMonkeys/issues/402
// https://bugs.openjdk.java.net/browse/JDK-6986863
//
ICC_Profile.getInstance(ColorSpace.CS_sRGB).getData();
ICC_Profile.getInstance(ColorSpace.CS_PYCC).getData();
ICC_Profile.getInstance(ColorSpace.CS_GRAY).getData();
ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ).getData();
ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB).getData();
}
fun loadImage(p: Path): BufferedImage = ImageIO.read(p.toFile())
}
感谢@Alex Taylor 解决 OpenJDK 错误 link。这让我确信我不是一个彻头彻尾的白痴。
而不是
fun Path.readImage(): BufferedImage =
Files.newInputStream(this, StandardOpenOption.READ).use { ImageIO.read(it) }
我现在正在使用
fun Path.readImage(): BufferedImage =
ImageIcon(toUri().toURL()).let {
BufferedImage(it.iconWidth, it.iconHeight, BufferedImage.TYPE_INT_ARGB).apply {
it.paintIcon(null, createGraphics(), 0, 0)
}
}
这是根据 https://aacsinia.wordpress.com/2010/12/21/java-how-to-create-buffered-image-from-inputstream/。速度达到标准,错误消失 [20+ runs]!恕我直言 ImageIO.read
因此不应在多线程环境中使用....
我目前正在编写一个程序,可以批量处理不同的图像。所以我认为并行执行操作(缩放/添加水印)可能会很聪明。
问题是我收到以下错误:
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:62)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:19)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.SequencesKt___SequencesKt.count(_Sequences.kt:1006)
at eu.reisihub.soft.watermarking.Main.main(Main.kt:66)
Caused by: java.lang.NullPointerException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
... 7 more
Caused by: java.lang.NullPointerException
at java.desktop/java.awt.color.ICC_Profile.intFromBigEndian(ICC_Profile.java:1784)
at java.desktop/java.awt.color.ICC_Profile.getNumComponents(ICC_Profile.java:1476)
at java.desktop/sun.java2d.cmm.lcms.LCMSTransform.<init>(LCMSTransform.java:93)
at java.desktop/sun.java2d.cmm.lcms.LCMS.createTransform(LCMS.java:173)
at java.desktop/java.awt.color.ICC_ColorSpace.fromRGB(ICC_ColorSpace.java:230)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.setImageData(JPEGImageReader.java:808)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:723)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:493)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:716)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1173)
at java.desktop/com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1153)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1468)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1363)
at eu.reisihub.shot.UtilsKt.readImage(Utils.kt:19)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:18)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:8)
at eu.reisihub.soft.watermarking.Main$sam$java_util_concurrent_Callable[=10=].call(Main.kt)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1448)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
请注意,我知道 java.desktop/java.awt.color.ICC_Profile.intFromBigEndian(ICC_Profile.java:1784)
中有一个 NPE。相信我,这不是图片。
我尝试了 Java 8 和 Java 10 的两种方法。我有一个固定大小的线程池,其中 6 个线程用于 4 个内核。我使用 Kotlin 来实现并创建了一个扩展函数 fun Path.readImage(): BufferedImage
。对于不了解 Kotlin 的人,仅出于本示例的目的,大致对应于 public BufferedImage readImage(Path this)
.
天真的方法
使用 Files.newInputStream(this, StandardOpenOption.READ).use { ImageIO.read(it) }
读取文件。这从 Path 打开一个新的 InputStream 并告诉 ImageIO 从这个 InputStream 读取图像。看起来不错?在 Java 8 上每四次不工作,在 Java 10 上大约 90%。顺便说一句:如果我围绕它包装一个同步块,它会工作——总是。用 13 秒处理 17 张图像,而不是 7 秒。
与此同时,我将 Gradle 从 4.4 更新到 4.7。在我配置 IntelliJ 使用 Java 10 和 Gradle 使用 Java 8 之前。可能是上面突出显示的差异的原因。边注。我一直用 synchronized(System.err)
!
复杂的方法 知道它在同步所有内容时有效,我的方法现在看起来更复杂,像这样:
fun Path.readImage(): BufferedImage = Files.newInputStream(this, StandardOpenOption.READ).buffered().use {
var nStream: ImageInputStream? = null
var nReader: ImageReader? = null
synchronized(System.err) {
nStream = ImageIO.createImageInputStream(it) ?: throw IIOException("Can't create an ImageInputStream!")
val iter = ImageIO.getImageReaders(nStream)
if (!iter.hasNext()) {
throw IIOException("No image nReader found!")
}
nReader = iter.next()
}
nStream!!.let { stream ->
nReader!!.let { reader ->
reader.setInput(stream, true, true)
try {
println(reader)
return reader.read(0, null)
} finally {
reader.dispose()
stream.close()
}
}
}
}
看到代码中的println
了吗?我知道对于每个图像,一个新的 com.sun.imageio.plugins.jpeg.JPEGImageReader
对象是 created.This 将性能提高到我正在与之交谈的 7 秒。一般不工作2-4次然后工作6-10次
复杂版本的堆栈跟踪如下:
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:64)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:20)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.TransformingSequence$iterator.next(Sequences.kt:149)
at kotlin.sequences.SequencesKt___SequencesKt.count(_Sequences.kt:1006)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:68)
at eu.reisihub.soft.watermarking.Main$main.invoke(Main.kt:20)
at eu.reisihub.shot.UtilsKt.measured(Utils.kt:54)
at eu.reisihub.soft.watermarking.Main.main(Main.kt:24)
Caused by: java.lang.NullPointerException
at java.awt.color.ICC_Profile.intFromBigEndian(ICC_Profile.java:1782)
at java.awt.color.ICC_Profile.getNumComponents(ICC_Profile.java:1474)
at sun.java2d.cmm.lcms.LCMSTransform.<init>(LCMSTransform.java:98)
at sun.java2d.cmm.lcms.LCMS.createTransform(LCMS.java:173)
at java.awt.color.ICC_ColorSpace.fromRGB(ICC_ColorSpace.java:218)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.setImageData(JPEGImageReader.java:694)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:609)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:481)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:602)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1059)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039)
at eu.reisihub.shot.UtilsKt.readImage(Utils.kt:39)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:16)
at eu.reisihub.soft.watermarking.WatermarkUtils$create.invoke(WatermarkUtils.kt:8)
at eu.reisihub.soft.watermarking.Main$sam$java_util_concurrent_Callable[=12=].call(Main.kt)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
其中 Main:64
是 Future#get
Main:68
是 kotlin.Sequence#count
我已经尝试改进代码几个小时了,现在我的脑子已经停止产生新的想法了。我知道错误也发生在 2 张图片上。由于它并不总是失败,因此 ICC 配置文件必须正确。我 - 老实说 - 考虑到我的硬盘驱动器不正常,偶尔会出现问题。我还尝试从我的 SSD 读取文件。根据 ,读取方法应该是线程安全的。我不知道发生了什么事。磁盘上的每个图像(由路径表示)都有自己的 Callable<Task>
。我只是阅读这些图像并将其写入不同的文件夹。因此,对于每个任务,一个文件被读取,一个文件被写入。这两个文件不一样,每个任务都有自己的文件。
他们唯一共享的是PNG格式的BufferedImage,绘制在读取图像(水印)上。但那是后来发生的。从堆栈跟踪中可以看出,它发生在读取 JPEG 图像时。
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039)
at eu.reisihub.shot.UtilsKt.readImage(Utils.kt:39)
创建主应用程序需要的路径的JSON设置
感谢任何意见。目前我不知道哪里出了问题...
顺便说一句:对于我正在使用的一些任务:https://github.com/coobird/thumbnailator
OpenJDK 有一个 bug report,标题为 'NullPointerException from ICC_Profile.getInstance() in multi-thread application'。在撰写本文时没有解决方案。
更新 2018-05-23
@haraldK 在评论中提到之前加载图像配置文件 代码:
import java.awt.color.ColorSpace
import java.awt.color.ICC_Profile
import java.awt.image.BufferedImage
import java.nio.file.Path
import javax.imageio.ImageIO
object ImgLoadUtils {
init {
// Load deferred color space profiles to avoid
// ConcurrentModificationException due to JDK
// Use in public static main void or prior to application initialization
// https://github.com/haraldk/TwelveMonkeys/issues/402
// https://bugs.openjdk.java.net/browse/JDK-6986863
//
ICC_Profile.getInstance(ColorSpace.CS_sRGB).getData();
ICC_Profile.getInstance(ColorSpace.CS_PYCC).getData();
ICC_Profile.getInstance(ColorSpace.CS_GRAY).getData();
ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ).getData();
ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB).getData();
}
fun loadImage(p: Path): BufferedImage = ImageIO.read(p.toFile())
}
感谢@Alex Taylor 解决 OpenJDK 错误 link。这让我确信我不是一个彻头彻尾的白痴。
而不是
fun Path.readImage(): BufferedImage =
Files.newInputStream(this, StandardOpenOption.READ).use { ImageIO.read(it) }
我现在正在使用
fun Path.readImage(): BufferedImage =
ImageIcon(toUri().toURL()).let {
BufferedImage(it.iconWidth, it.iconHeight, BufferedImage.TYPE_INT_ARGB).apply {
it.paintIcon(null, createGraphics(), 0, 0)
}
}
这是根据 https://aacsinia.wordpress.com/2010/12/21/java-how-to-create-buffered-image-from-inputstream/。速度达到标准,错误消失 [20+ runs]!恕我直言 ImageIO.read
因此不应在多线程环境中使用....