Сжатие многостраничного изображения в формате TIFF с потерями в формате JPEG - PullRequest
0 голосов
/ 27 мая 2018

Мне нужно сжать TIF-файл, содержащий несколько серых 16-битных изображений (многостраничный).Я попытался работать с ImageIO, как здесь: Сжатие TIFF с использованием Java ImageIO Первоначально каждое изображение, которое будет в TIF-файле, происходит из другого TIFF-файла.Когда я хочу использовать компрессоры, у меня есть следующие опции:

  1. CCITT RLE, CCITT T.4, CCITT T.6: они дают мне ошибку: "javax.imageio.IIOException: I/ O ошибка записи файла TIFF! "
  2. LZW.Я не могу использовать это.Мои изображения 16-битные, и LZW увеличивает размер 16-битных изображений
  3. JPEG.Невозможно для 16-битных изображений.
  4. ZLIB.Это только уменьшает 10%, даже если я указываю setCompressionQuality (0.0f);
  5. PackBits.Не сжимает.
  6. Сдувать.Как ZLIB.
  7. EXIF ​​JPEG.Это дает мне ошибку: «javax.imageio.IIOException: старое сжатие JPEG не поддерживается!»

Кто-нибудь знает какую-либо другую альтернативу?Я видел библиотеку изображений Apache, но сжатие TIF поддерживает только вышеуказанные или менее опции.Кто-нибудь знает про компрессор JPEG2000?Любой другой вид альтернативы?

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Уменьшение изображения с 16 бит до 8 бит.Учтите, что у вас есть переменная plane16 byte [], где у вас есть все пиксели вашего изображения.

Примечание : Мой байт [] plane16 получает данные из 16-битного изображения, но байт составляет 8 бит = 1 байт.Следовательно, 2 элемента в строке этого массива имеют размер 2 байта = 16 бит.Вот почему я конвертирую его в короткий [] перед началом работы.Если вы начинаете с короткого [], пропустите "ByteBuffer.wrap (plane16) .order (ByteOrder.LITTLE_ENDIAN) .asShortBuffer (). Get (shorts);"

byte[] plane16; //Fill it with your image!!!

//Do stuff with imageIO. Set writer and compresion method
ImageIO.scanForPlugins();
TIFFImageWriterSpi tiffspi = new TIFFImageWriterSpi();
javax.imageio.ImageWriter writerIO = tiffspi.createWriterInstance();
ImageWriteParam param = writerIO.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType("ZLib");
param.setCompressionQuality(0.5f);
File fOutputFile = new File(route+".tif");
ImageOutputStream ios = ImageIO.createImageOutputStream(fOutputFile);
writerIO.setOutput(ios);

//Reducing 16bit to 8bit
short[] shorts = new short[plane16.length/2];
ByteBuffer.wrap(plane16).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);

int max = 0;
int min = 999999;
for (int v = 0; v<shorts.length;v++){
    if (max<shorts[v]) max = shorts[v];
    if (min>shorts[v]) min = shorts[v];
}

double range = 255./(max-min);
byte[] plane8 = new byte[shorts.length];
for (int v = 0; v<plane8.length;v++){
    plane8[v] = (byte) ((shorts[v]+min)*range - 128);   
}                       
//16bit:    
/*BufferedImage convertedGrayscale = new BufferedImage(width,
                            heigth, BufferedImage.TYPE_USHORT_GRAY);    
  convertedGrayscale.getRaster().setDataElements(0, 0, width,
                            heigth, shorts);*/

//8bit:
BufferedImage convertedGrayscale = new BufferedImage(width,
                            heigth, BufferedImage.TYPE_BYTE_GRAY);  
convertedGrayscale.getRaster().setDataElements(0, 0, width,
                            heigth, plane8);

//Save image
//If you have a stack of images in tiff, do this trick. "image" is the image number you are setting inside the tiff. If you only have 1 image, remove the if and take the expression from the else.
if (image!=0){
    writerIO.writeInsert(image, new IIOImage(convertedGrayscale, null, null), param);                   
}else{
    writerIO.write(null, new IIOImage(convertedGrayscale, null, null), param);
}

//do the next only after the last image to be saved
writerIO.dispose();
ios.flush();
ios.close();
0 голосов
/ 28 мая 2018

PNG сжимает 16-битные изображения без потерь.Библиотеки и утилиты широко доступны.JPEG2000 имеет 16-битный режим с потерями, но вам нужно найти программное обеспечение, которое его поддерживает. Открыть JPEG может.

Однако я должен спросить: каковы ваши критерии, когда у вас приемлемое качество изображения, а когда нет?Если это визуально, то вы, скорее всего, в конечном итоге получите обычный JPEG с хорошим битом менее 8 бит на пиксель.

...