Java-Version:
openjdk 版本“11” 2018-09-25
OpenJDK Runtime Environment 18.9(build 11+28)
OpenJDK 64-Bit Server VM 18.9(build 11+28,混合模式)
TwelveMonkeys ImageIO 依赖:
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.7.0</version>
</dependency>
案例:
我正在尝试将子图像保存为带有 dpi 信息的 tif。
有时它有效,有时我得到一个奇怪的例外。
首先,这是我如何创建子图像的代码:
//Reading JPG as BufferedImage
BufferedImage bi = ImageIO.read(new FileImageInputStream(jpg.toFile()));
//Create Subimage (r is an java.awt.Rectangle)
BufferedImage subimage = bi.getSubimage(r.x - 10, r.y - 10, r.width + 20, r.height + 20);
saveImage(subimage, new File("destfile.tif"));
确保该子图像有效。
现在方法“saveImage”,灵感来自这篇文章
https://github.com/haraldk/TwelveMonkeys/issues/439#issue-355278313
public static void saveImage(BufferedImage image, File destFile) throws IOException {
String format = "tif";
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
if (!writers.hasNext()) {
throw new IllegalArgumentException("No writer for: " + format);
}
ImageWriter writer = writers.next();
try {
// Create output stream (in try-with-resource block to avoid leaks)
try (ImageOutputStream output = ImageIO.createImageOutputStream(destFile)) {
writer.setOutput(output);
// set the resolution of the target image to 200 dpi
final List<Entry> entries = new ArrayList<Entry>();
entries.add(new TIFFEntry(TIFF.TAG_X_RESOLUTION, new Rational(200)));
entries.add(new TIFFEntry(TIFF.TAG_Y_RESOLUTION, new Rational(200)));
final IIOMetadata tiffImageMetadata = new TIFFImageMetadata(entries);
writer.write(new IIOImage(image, null, tiffImageMetadata));
}
}
finally {
// Dispose writer in finally block to avoid memory leaks
writer.dispose();
}
}
有时,保存这个 TIF 就像一个魅力,没有任何问题。但在某些情况下,我收到以下异常。在这种情况下,我必须重新启动应用程序并再试一次:
java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 3
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3319)
at java.base/java.lang.String.substring(String.java:1874)
at com.github.jaiimageio.plugins.tiff.TIFFField.initData(TIFFField.java:406)
at com.github.jaiimageio.plugins.tiff.TIFFField.createFromMetadataNode(TIFFField.java:486)
at com.github.jaiimageio.impl.plugins.tiff.TIFFImageMetadata.parseIFD(TIFFImageMetadata.java:1588)
at com.github.jaiimageio.impl.plugins.tiff.TIFFImageMetadata.mergeNativeTree(TIFFImageMetadata.java:1612)
at com.github.jaiimageio.impl.plugins.tiff.TIFFImageMetadata.mergeTree(TIFFImageMetadata.java:1636)
at java.desktop/javax.imageio.metadata.IIOMetadata.setFromTree(IIOMetadata.java:752)
at com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriter.convertNativeImageMetadata(TIFFImageWriter.java:515)
at com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriter.write(TIFFImageWriter.java:2551)
at com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriter.write(TIFFImageWriter.java:2383)
at java.desktop/javax.imageio.ImageWriter.write(ImageWriter.java:595)
at de.buerotex.util.BufferedImageUtil.saveImage(BufferedImageUtil.java:64)
我查看了源代码,发现这个类正在尝试拆分一个值:
在 com.github.jaiimageio.plugins.tiff.TIFFField.initData(TIFFField.java:406)
case TIFFTag.TIFF_RATIONAL:
slashPos = value.indexOf("/");
numerator = value.substring(0, slashPos);
denominator = value.substring(slashPos + 1);
其中“价值”= 200。
我不知道这个常量“TIFF_RATIONAL”在哪里以及为什么被设置。
这个错误来自哪里,为什么?当我通过将第三个参数设置为 null 来禁用在我的保存方法中设置 tiffImageMetadata 时:
writer.write(new IIOImage(image, null, null));
一切正常。但是我的 tif 图像没有设置任何 dpi 值。