2017-03-24 5 views
0

J'utilise com.sun.media.imageioimpl.plugins.tiff.TIFFPackBitsCompressor pour essayer de coder un tableau de tiff octets que j'ai en utilisant PackBits. Je ne suis pas familier avec cette classe et je n'ai pas trouvé beaucoup d'exemples sur la façon de l'utiliser. Mais, en suivant le javadoc, j'ai reçu un NPE chaque fois que j'ai essayé d'encoder mes données. Autant que je puisse voir, aucune de mes valeurs n'est nulle. J'ai essayé ces tests avec plusieurs valeurs à ce stade, mais au-dessous est ma plus récente itération:TIFFPackBitsCompressor - NPE?

   TIFFPackBitsCompressor pack = new TIFFPackBitsCompressor(); 
       //bImageFromConvert is a 16-bit BufferedImage with all desired data. 
       short[] bufferHolder = ((DataBufferUShort) bImageFromConvert.getRaster().getDataBuffer()).getData(); 
       //Since bImageFromConvert is 16-bits, the short array isn't the right length. 
       //The below conversion handles tihs issue 
       byte[] byteBuffer = convertShortToByte(bufferHolder); 
       //I'm not entirely sure what this int[] in the parameters should be. 
       //For now, it is a test int[] array containing all 1s 
       int[] testint = new int[byteBuffer.length]; 
       Arrays.fill(testint, 1); 
       //0 offset. dimWidth = 1760, dimHeight = 2140. Not sure what that last param is supposed to be in layman's terms. 
       //npe thrown at this line. 
       int testOut = pack.encode(byteBuffer, 0, dimWidth, dimHeight, testint, 1); 

Quelqu'un at-il aperçu de ce qui se passe? Aussi, si disponible, quelqu'un sait-il un meilleur moyen d'encoder mes fichiers TIFF en utilisant PackBits dans un programme Java? Faites-moi savoir s'il y a quelque chose pour clarifier ma question.

Merci!

+2

Où se trouve la trace de la pile? Quoi qu'il en soit, je ne pense pas que vous soyez supposé utiliser le compresseur vous-même, mais plutôt le plugin JAI ImageIO TIFF (le 'TIFFImageWriter') lorsque vous spécifiez" PackBits "comme type de compression dans le fichier' ImageWriteParam'. Vous pouvez également passer une instance de compresseur dans le paramètre param, si vous l'avez convertie en 'TIFFImageWriteParam' en premier, mais ceci est plus utile pour les compressions personnalisées non connues par le plugin. – haraldK

Répondre

1

Comme dit dans le commentaire, vous n'êtes pas censé utiliser le TIFFPackBitsCompressor directement, au lieu qu'il est utilisé en interne par le plug-in TIFF JAI ImageIO (le TIFFImageWriter) lorsque vous spécifiez « PackBits » comme type de compression dans le ImageWriteParam. Vous pouvez également passer une instance de compresseur dans le paramètre param, si vous l'avez convertie en TIFFImageWriteParam en premier, mais cela est plus utile pour les compressions personnalisées non connues par le plugin.

Notez également que le compresseur n'écrira que des données de pixel compressées PackBits, il créera un fichier TIFF complet.

La façon normale d'écrire un fichier TIFF PackBits compressé est:

BufferedImage image = ...; // Your input image 

ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next(); // Assuming a TIFF plugin is installed 

try (ImageOutputStream out = ImageIO.createImageOutputStream(...)) { // Your output file or stream 
    writer.setOutput(out); 

    ImageWriteParam param = writer.getDefaultWriteParam(); 
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
    param.setCompressionType("PackBits"); 

    writer.write(null, new IIOImage(image, null, null), param); 
} 

writer.dispose(); 

Le code ci-dessus devrait fonctionner correctement en utilisant à la fois et les ImageIO JAI plugins TIFF Twelvemonkeys ImageIO.


PS: PackBits est un algorithme de compression très simple basé sur run-length encoding de octet données. Comme les données 16 bits peuvent varier considérablement entre l'octet haut et l'octet faible d'un seul échantillon, PackBits n'est généralement pas un bon choix pour la compression de ces données.

Comme indiqué dans mes commentaires, en utilisant complètement des valeurs aléatoires j'ai obtenu les résultats suivants:

Compression  | File size 
-----------------|----------------- 
None    | 7 533 680 bytes 
PackBits   | 7 593 551 bytes 
LZW w/predictor | 10 318 091 bytes 
ZLib w/predictor | 10 318 444 bytes 

Ce n'est pas très surprenant, car les données complètement aléatoires ne sont généralement pas compressible (sans perte de données). Pour un gradient linéaire, qui peut être plus semblable à des données d'image « photographique » J'ai obtenu des résultats complètement différents:

Compression  | File size 
-----------------|----------------- 
None    | 7 533 680 bytes 
PackBits   | 7 588 779 bytes 
LZW w/predictor | 200 716 bytes 
ZLib w/predictor | 144 136 bytes 

Comme vous le voyez, ici le LZW et les algorithmes dégonflage/Zlib (avec étape de prédiction) effectue beaucoup mieux. Pour les données «réelles», il y a probablement plus de bruit, donc vos résultats sont probablement entre ces extrêmes.

+0

Pendant qu'un fichier est en cours d'écriture et est au format tiff, il fait à peu près le double de la taille du fichier d'origine. Si cela aide, le short [] contient des octets encapsulés pour une image de 16 bits.L'image fait 1760 x 2140 pixels et la taille de l'image originale est de 7 532 800 octets (pas de métadonnées, juste des pixels). Le fichier résultant de ce code 15 119 390 octets (y compris les métadonnées tiff). – Sarah

+0

@Sarah Vous venez de découvrir que PackBits est un algorithme de compression très inefficace pour vos données (il est inefficace pour les données 16 bits en général). En utilisant le code ci-dessus, j'ai compressé une image noire (encore 1760x2140 16 bits/pixel) à 120 Ko. Remplir l'image avec du bruit aléatoire, la taille du fichier est devenu 7,5 Mbytes. L'utilisation de LZW ou de ZLib avec un prédicteur a donné des tailles d'environ 10 Mo, mais cela peut tout de même donner de meilleurs résultats pour vous, car vos données ne sont pas aléatoires. – haraldK