2013-06-18 2 views
4

Я пытаюсь создать приложение Grails, которое может отображать превью файлов TIFF и других изображений.Как добавить TIFF ImageReader к зарегистрированным в Grails

фон

Изображения построены из службы SOAP, который дает мне байты изображения. В методе службы я беру байт [], создаю из него ByteArrayInputStream, а затем создаю BufferedImage.

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

Для JPG я могу легко передавать изображения в браузер таким образом, как src тега img. TIFF, однако, мне нужно будет преобразовать изображения в другой формат (желательно JPG или PNG), чтобы сделать их src тега.

Проблема

Я знаю, что I need JAI in order to read the TIFF files. Файлы jai_core.jar, jai_codec.jar находятся в моем пути к классам. Фактически, поскольку я на Mac OSX, они устанавливаются автоматически. Тем не менее, когда я запустить приложение Grails и пытается построить TIFF изображение из полученных байт от службы SOAP, я получаю эту ошибку:

| 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 консоли, я получаю эту OUTP ut:

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 от Apple. Почему GroovyConsole может найти его, а не мою среду Grails, хотя они оба используют одну и ту же JRE? Есть ли способ, который я могу вручную добавить читателя TIFF через некоторый импорт из импорта com.sun.media.jai или com.sun.media.imageio.plugins.tiff?

Я пытался добавить вручную регистрации TIFFImageReaderSpi моему методу обслуживания:

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

Переменная originalImage еще возвращается нуль.

+0

Я достаточно убедитесь, что (по крайней мере, частично) проблема в том, что мне нужно зарегистрировать ImageWriter, который также может обрабатывать файлы TIFF. Однако, похоже, для классов JAI у меня нет класса. При поиске вокруг это похоже на то, что JAI несколько не функционирует как библиотека. Я открыт для альтернатив для преобразования TIFF в более удобные для веб-изображений изображения, если кто-то имел успех с тем, что было в Grails. – jonnybot

+0

+1 для хорошо отформатированного вопроса. – dmahapatro

+0

@jonnybot ImageIO использует механизм поиска службы. Обычно нет необходимости вручную регистрировать 'Spi', просто поместите соответствующие JAR-файлы в classpath. Кроме того, вам не нужен ImageWriter, поддерживающий TIFF, поскольку вы просто хотите писать 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, я получил источник для связанного JAI от https://github.com/stain/jai-imageio-core. Я импортировал это в Eclipse, а затем создал JAR, используя инструмент экспорта Eclipse. Это я разместил в папке lib моего проекта, но импорт все еще не был разрешен. Мне пришлось вручную добавить эту банку в класс пути к проекту, а затем импорт будет разрешен.

Во-вторых, когда я запускал приложение, я получаю эту ошибку:

| 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 

Имя_вендора == NULL? К счастью, я нашел это question/answer.

При создании файла jar для jai-imageio-core мне пришлось вручную указать местоположение файла манифеста, вместо того чтобы позволить 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 

и разместить его на пути к классам.

Необходимо убедиться, что поставщик зарегистрирован правильно.

Однако имейте в виду, что предоставленный Apple TIFFImageReader не совпадает с тем, что у JAI, хотя имена пакетов/классов одинаковы.

Если вы хотите использовать JAI TIFF ImageReader, вам понадобится jai-imageio.jar. В настоящее время проект, как вы отметили, оставлен в неопределенности Oracle.

Если вы не любите использовать JAI по какой-либо причине, я создал чистый плагин Java TIFF для ImageIO, доступный на GitHub: Twelvemonkeys TIFF plugin. Плагин доступен под лицензией для разработчиков с открытым исходным кодом (BSD).

+0

Это сделало бы моих злых повелителей необычайно счастливыми, если бы у вашего TIFF-плагина была лицензия, связанная с ним. :) – jonnybot

+1

@jonnybot Звучит разумно .. :-) Просто нажал лицензионный.txt на репо. Однако все twelvemonkeys находятся под лицензией BSD. – haraldK

2

У меня была такая же проблема, и в то время как можно вручную зарегистрировать одиночные плагины есть также метод, чтобы зарегистрировать все плагины, которые доступны в пути к классам, которые, вероятно, немного чище:

ImageIO.scanForPlugins();