堆栈:
我们正在阅读大量旧的TIF图像,由于某些原因,读取高度不一致-由于某些原因,在不同的运行中读取同一图像可能会成功,也可能会失败-
javax.imageio.IIOException: Invalid component ID 3 in SOS
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1236)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039)
at com.sun.media.imageioimpl.plugins.tiff.TIFFOldJPEGDecompressor.decodeRaw(TIFFOldJPEGDecompressor.java:654)
at com.sun.media.imageio.plugins.tiff.TIFFDecompressor.decode(TIFFDecompressor.java:2527)
at com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader.decodeTile(TIFFImageReader.java:1137)
at com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader.read(TIFFImageReader.java:1417)
代码如下:
import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
import javax.imageio.ImageIO
def convertToPng(data: Array[Byte]): Array[Byte] = {
val inputStream = new ByteArrayInputStream(data)
val image = ImageIO.read(inputStream)
val outputStream = new ByteArrayOutputStream(inputStream.available())
ImageIO.write(image, "png", outputStream)
outputStream.toByteArray
}
问题是ImageIO同时初始化2个TIFF阅读器
com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader &
it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader
或
it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader
com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader
第一个失败,第二个工作。如何从ImageIO配置中排除com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader?
这里的问题是,ImageIO使用服务提供商接口(SPI)查找在运行时注册插件,在您的设置中,可以找到多个可以读取TIFF的插件。默认情况下,插件没有任何特定的顺序,这就是为什么有时您会得到com。首先是sun(JAI)TIFF插件,有时是它。首先是geosolutions(geosolutions)TIFF插件<代码>图像。读取(…)只会尝试第一个插件,如果失败就放弃。
如果可以,最简单的解决方案就是从类路径中删除一个插件。但是我假设你已经想到了。还有多种其他方法可以解决这个问题(我在Java中给出了代码示例,因为这是我最熟悉的,我相信你可以在Scala中写得更优雅;-))。
需要对代码进行最少更改的是在运行时在“引导”代码中的某个位置注销JAI提供程序(具体位置取决于应用程序,可以是静态初始化程序块或web上下文侦听器或类似程序)。iiOreRegistry有一个用于此目的的取消注册服务提供者(deregisterServiceProvider)方法,将提供者从注册表中删除,并使其不可用于图像IO。
另一种选择是定义提供者的显式顺序。如果出于某种原因(第三方需求/插件间依赖性等),需要为一种格式提供多个提供者,这将非常有用。iOreRegistry有一个用于此目的的setOrdering方法,该方法允许设置两个服务提供商的成对排序,使ImageIO始终优先于一个。
下面的代码显示了上述两个选项:
// Get the global registry
IIORegistry registry = IIORegistry.getDefaultInstance();
// Lookup the known TIFF providers
ImageReaderSpi jaiProvider = lookupProviderByName(registry, "com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi");
ImageReaderSpi geoProvider = lookupProviderByName(registry, "it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReaderSpi");
if (jaiProvider != null && geoProvider != null) {
// If both are found, EITHER
// order the it.geosolutions provider BEFORE the com.sun (JAI) provider
registry.setOrdering(ImageReaderSpi.class, geoProvider, jaiProvider);
// OR
// un-register the JAI provider
registry.deregisterServiceProvider(jaiProvider);
}
// New and improved (shorter) version. :-)
private static <T> T lookupProviderByName(final ServiceRegistry registry, final String providerClassName) {
try {
return (T) registry.getServiceProviderByClass(Class.forName(providerClassName));
}
catch (ClassNotFoundException ignore) {
return null;
}
}
以上代码将确保Geosolutions TIFF插件始终由ImageIO使用。读取(…) ,您现有的代码应该可以正常工作(但现在是稳定的)。
一个完全不同的选择,是尝试使用所有注册的TIFF插件读取数据,并使用第一个成功的插件。这比之前的代码更明确,但需要重写图像读取代码:
byte[] data;
BufferedImage image;
try (ImageInputStream inputStream = ImageIO.createImageInputStream(new ByteArrayInputStream(data))) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(inputStream);
// Try reading the data, using each reader until we succeed (or have no more readers)
while (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(inputStream);
image = reader.read(0);
break; // Image is now correctly decoded
}
catch (Exception e) {
// TODO: Log exception?
e.printStackTrace();
// Reading failed, try the next Reader
inputStream.seek(0);
}
finally {
reader.dispose();
}
}
}
当然,您可以将上述选项结合起来,以实现两全其美(即,稳定的顺序和在一个读卡器出现故障时的回退)。
问题内容: 堆栈: Java-1.8.0_91 Scala-2.11.8 库-it.geosolutions.imageio-ext imageio-ext-tiff 1.1.15 我们正在读取许多旧的TIF图像,并且由于某种原因读取的数据高度不一致-出于某些原因,在不同的运行中读取同一图像可能会成功或失败,但是- 代码是这样的: 问题是ImageIO同时初始化2个TIFF读取器 要么 第一个失败
我已经创建了可执行的jar文件(使用Eclipse),有一组图像(.png)文件要嵌入到jar中。因此,我添加了一个源文件夹,其中包含项目中文件夹中的所有图像。代码必须访问这些文件才能使用
问题内容: 我已经创建了可执行的jar文件(使用Eclipse),在jar中包含一组图像(.png)文件。所以我添加了一个源文件夹,其中所有图像都位于项目的文件夹中。代码必须访问这些文件才能使用创建BufferedImage 较早前,为了获得我使用的路径 在执行jar时,它抛出错误 URI不是分层的 所以现在我正在使用 但是如何使ImageIO从Inputstream读取?我试过如下 抛出错误 I
如何才能缓解这种情况?
问题内容: 我们有一个与已删除的某些需求相关的软件包,但我们不想删除该代码,因为将来可能会再次需要它。因此,在我们现有的ant构建中,我们只是将该包排除在了jar中之外。这些类由于我们还删除了它们的依赖关系而无法编译,因此它们不能包含在构建中。 我正在尝试模仿Gradle中的功能,如下所示: 即使使用上面的exclude调用(并且我也尝试过不带方括号的尝试),gradle仍在尝试编译类,这会导致编
我有一个包含5个字段(列)的csv文件。在5列中,我只想读第二列和第四列,这是进一步处理所需的。现在我正在使用opencsv api的readAll()方法进行读取。通过使用这种方法,我必须处理所有列,以获得第二列和第四列的值。 有没有办法读取所需列的值,即从csv文件中读取第二个和第四个值? 这是正确的方法还是我应该使用其他方法?