2013-06-18 25 views
4

我正在尝试创建一个Grails应用程序,它可以显示TIFF文件和其他图像的预览。如何将TIFF ImageReader添加到在Grails中注册的人

背景

图像是从一个SOAP服务构造的,该服务给了我图像的字节。在服务方法中,我使用byte [],从中构建一个ByteArrayInputStream,然后从中创建一个BufferedImage。

def inputStream = new ByteArrayInputStream(bytes) 
BufferedImage originalImage = ImageIO.read(inputStream) 
ImageIO.write(originalImage, 'png', response.outputStream) 

对于JPG,我可以很容易地将图像作为img标签的src流式传输到浏览器。 TIFFs,但是,我需要将图像转换为其他格式(最好是JPG或PNG),以使它们成为标签的src。

的问题

我知道I need JAI in order to read the TIFF files。 jai_core.jar,jai_codec.jar文件位于我的类路径中。事实上,因为我在Mac OSX上,它们会自动安装。然而,当我运行Grails应用程序,并尝试构建从SOAP服务接收的字节的TIFF图像,我得到这个错误:

| Error 2013-06-18 15:23:38,135 [http-bio-8080-exec-10] ERROR errors.GrailsExceptionResolver - IllegalArgumentException occurred when processing request: [GET] /BDMPlugin/BDMPlugin/displayImageFromRef - parameters: 
pageRef: 28:22072FBCA0A8889D9C041D76A588BCF4DCB40376A23B5FD5C301378C8E66EB9F4933A5DFCA46365F927D9E91B337B6E1E980FB4406644801 
type: TIFF 
im == null!. Stacktrace follows: 
Message: im == null! 
    Line | Method 
->> 1457 | write    in javax.imageio.ImageIO 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 1571 | write    in  '' 
|  28 | writeImageToResponse in edu.missouristate.bdmplugin.ImageService 
|  44 | bytesToPng   in  '' 
|  39 | displayImageFromRef in edu.missouristate.bdmplugin.BDMPluginController 
| 895 | runTask    in java.util.concurrent.ThreadPoolExecutor$Worker 
| 918 | run . . . . . . . . in  '' 
^ 680 | run     in java.lang.Thread 

我尝试以下script找出安装了哪些图像阅读器:

IIORegistry reg = IIORegistry.getDefaultInstance(); 
Iterator spIt = reg.getServiceProviders(ImageReaderSpi.class, false); 
spIt.each(){ 
println it.getVendorName() << " | " << it.getVersion() << " | "<< it.getDescription() ; 
} 

此输出以下:

Sun Microsystems, Inc. | 1.0 | Standard BMP Image Reader 
Sun Microsystems, Inc. | 1.0 | Standard GIF image reader 
Sun Microsystems, Inc. | 1.0 | Standard WBMP Image Reader 
Sun Microsystems, Inc. | 1.0 | Standard PNG image reader 
Sun Microsystems, Inc. | 0.5 | Standard JPEG Image Reader 

但是,如果我跑,在Groovy的控制台相同的Groovy脚本,我得到这个输出:

Sun Microsystems, Inc. | 0.5 | Standard JPEG Image Reader 
Sun Microsystems, Inc. | 1.0 | Standard BMP Image Reader 
Sun Microsystems, Inc. | 1.0 | Standard WBMP Image Reader 
Sun Microsystems, Inc. | 1.0 | Standard PNG image reader 
Sun Microsystems, Inc. | 1.0 | Standard GIF image reader 
Apple computer Inc. | 1.0 | Standard TIFF image reader 

同一套阅读器,但它也包括苹果的TIFF阅读器。为什么GroovyConsole能够找到它而不是我的Grails环境,即使它们都使用相同的JRE?有没有一种方法可以通过从导入com.sun.media.jaicom.sun.media.imageio.plugins.tiff进口的某些导入手动添加TIFF阅读器?

我尝试添加了TIFFImageReaderSpi的手工登记到我的服务方法:

import com.sun.imageio.plugins.tiff.TIFFImageReaderSpi 
... 
IIORegistry reg = IIORegistry.getDefaultInstance() 
reg.registerServiceProvider(new TIFFImageReaderSpi()) 

的originalImage变量仍然回来空。

+0

我有理由确定(至少部分)问题是我需要注册一个可以处理TIFF文件的ImageWriter。然而,在我的JAI课程中似乎没有这样的课程。在寻找它的时候,JAI似乎已经有点像图书馆一样不存在了。如果有人在Grails中取得成功,我可以选择将TIFF转换为更友好的图像。 – jonnybot

+0

+1格式良好的问题。 – dmahapatro

+0

@jonnybot ImageIO使用服务查找机制。通常不需要手动注册'Spi's,只需将相应的JAR放在classpath上即可。此外,您不需要支持TIFF的ImageWriter,因为您只需编写JPEG和PNG。 – haraldK

回答

5

所以似乎有一些问题层出不穷。

首先,import com.sun.imageio.plugins.tiff.TIFFImageReaderSpi声明导入了Apple TIFF阅读器,这显然不符合阅读我的TIFF的工作。

真的需要的是import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi,但这给我带来了几个不同的错误;别担心,我可以修复它们。 :)

首先,导入没有解决。为了获得com.sun.media.imageioimpl软件包,我从https://github.com/stain/jai-imageio-core获得了捆绑JAI的源代码。我将它导入到Eclipse中,然后使用Eclipse的导出工具构建了一个JAR。这我放在我的项目的lib文件夹,但导入仍然没有解决。我必须手动将该jar添加到我的项目的类路径中,然后导入才能解决。

其次,当我跑的应用程序,我会得到这个错误:

| Error 2013-06-19 11:15:27,665 [http-bio-8080-exec-3] ERROR errors.GrailsExceptionResolver - IllegalArgumentException occurred when processing request: [GET] /pluginproject/Controller/action - parameters: 
vendorName == null!. Stacktrace follows: 
Message: vendorName == null! 
    Line | Method 
->> 59 | <init>    in javax.imageio.spi.IIOServiceProvider 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 214 | <init>    in javax.imageio.spi.ImageReaderWriterSpi 
| 192 | <init> . . . . . . in javax.imageio.spi.ImageReaderSpi 
| 88 | <init>    in com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi 
| 31 | bytesToPng . . . . in edu.mystateu.pluginproject.ImageService 

VENDORNAME == NULL?幸运的是,我发现这个question/answer

为jai-imageio-core创建jar文件时,我不得不手动指定清单文件的位置,而不是让Eclipse生成一个新的空白文件。清单文件位于/jai-imageio-core/src/main/resources/META-INF/MANIFEST.MF中,一旦我指定使用该文件,导入的lib就会解析并读取我的映像。

最后,服务方法的代码非常好。我只需要将JAI正确导入到我的项目中。 @haraldK非常感谢,他的反馈让我走上了正轨。

2

一种解决方案可以工作,是创建一个文件

/META-INF/services/ImageReaderSpi 

包含一行

com.sun.imageio.plugins.tiff.TIFFImageReaderSpi 

,并将其放置在classpath。

这应该确保提供商已正确注册。

但是请注意,Apple提供的TIFFImageReader与JAI中的不一样,即使包/类名称相同。

如果您想使用JAI TIFF ImageReader,您将需要jai-imageio.jar。正如你所指出的那样,这个项目目前正在被Oracle抛在一边。

如果因为任何原因不喜欢使用JAI,我已经为GitHub上的ImageIO创建了一个纯Java TIFF插件:Twelvemonkeys TIFF plugin。该插件可用于商业友好的开源许可证(BSD)。

+0

如果你的TIFF插件有与之相关的许可证,它会让我的恶霸们非常高兴。 :) – jonnybot

+1

@jonnybot听起来很合理.. :-)只是推了一个license.txt回购。尽管如此,所有的12个猴子都在BSD许可下。 – haraldK

2

我有同样的问题,同时可以手动注册单个插件,也有注册这这可能是一点点清洁类路径中的所有可用的插件的方法:

ImageIO.scanForPlugins(); 
相关问题