2017-03-24 3 views
0

com.sun.media.imageioimpl.plugins.tiff.TIFFPackBitsCompressor를 사용하여 PackBits를 사용하는 tiff 바이트 배열을 인코딩하려고합니다. 나는이 수업에 익숙하지 않고 그것을 사용하는 방법에 대한 많은 예제를 발견하지 못했다. 그러나 javadoc을 따라갈 때마다 데이터 인코딩을 시도 할 때마다 NPE를 얻었습니다. 지금까지 내가 볼 수있는 한, 내 가치 중 하나도 null입니다. 나는이 시점에서 여러 값으로 테스트를 해봤지만 아래에있는 내 가장 최근의 반복은 다음과 같습니다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); 

사람이 무슨 일이야에 관해서는 어떤 통찰력을 가지고 있습니까? 또한, 가능하다면 누구든지 Java 프로그램에서 PackBits를 사용하여 TIFF 파일을 인코딩하는 더 좋은 방법을 알고 있습니까?

제 질문을 명확하게 해줄 수 있는지 알려주세요.

감사합니다.

+2

스택 트레이스는 어디에 있습니까? 어쨌든, 나는 당신이 압축기를 직접 사용한다고 생각하지 않는다. 대신에 ImageWriteParam에서 압축 유형으로 "PackBits"를 지정할 때 JAI ImageIO TIFF 플러그인 ('TIFFImageWriter')이 사용한다. 'TIFFImageWriteParam'로 먼저 캐스팅하면, 압축기 인스턴스를 매개 변수로 전달할 수 있습니다. 그러나 이것은 플러그인이 알지 못하는 사용자 정의 압축에 더 유용합니다. – haraldK

답변

1

으로는 코멘트, 당신은 당신이 ImageWriteParam에서 압축 형식으로 "팩 비트"를 지정하면 직접, 대신이 JAI ImageIO에서의 TIFF 플러그인합니다 (TIFFImageWriter)에 의해 내부적으로 사용 년대 TIFFPackBitsCompressor 사용 안되어있다. 매개 변수를 먼저 TIFFImageWriteParam으로 캐스팅하면 압축기 인스턴스를 전달할 수 있지만이 방법은 플러그인에서 알 수없는 사용자 정의 압축에 더 유용합니다.

컴프레서는 PackBits 압축 된 픽셀 데이터 만 기록하므로 이 아니며 전체 TIFF 파일을 생성합니다.

팩 비트 압축 TIFF 파일을 작성하는 일반적인 방법은 다음과 같습니다

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(); 

위의 코드는 JAI ImageIO에서와 TwelveMonkeys ImageIO에서의 TIFF 플러그인을 모두 사용하여 잘 작동합니다.


PS : PackBitsrun-length encoding바이트의 데이터에 기초하여 매우 간단한 압축 알고리즘이다. 16 비트 데이터는 단일 샘플의 상위 바이트와 하위 바이트간에 크게 다를 수 있으므로 일반적으로 PackBits는 이러한 데이터의 압축에 적합하지 않습니다. 나는 다음과 같은 결과를 얻었다 완전히 임의의 값을 사용하여, 내 의견에 명시된 바와 같이

는 : 완전히 임의의 데이터 (데이터 손실없이) 일반적으로 압축 할 수없는 것처럼

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 

이것은 매우 놀라운 일이 아니다. 에 "사진"이미지 데이터 I 완전히 다른 결과를 가지고 더 유사 할 수 있습니다 선형 그라디언트의 경우 : 보시다시피

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 

, 여기에 LZW 및 (예측 단계와) 공기를 빼다/Zlib의 알고리즘은 훨씬 더 나은 수행합니다. "실제"데이터의 경우 노이즈가 더 많으므로 결과가 이러한 극단 사이의 어딘가에있을 수 있습니다.

+0

파일이 쓰여지고 tiff 형식 인 동안 원본 파일의 크기의 대략 두 배입니다. 도움이되면, short []는 16 비트 이미지에 대해 랩핑 된 바이트를 보유합니다.이미지는 1760x2140 픽셀이며 원본 이미지 크기는 7,532,800 바이트입니다 (메타 데이터 없음, 픽셀 바이트 만). 이 코드로 인해 생성 된 파일은 15,119,390 바이트입니다 (tiff 메타 데이터 포함). – Sarah

+0

@Sarah PackBits가 데이터에 매우 비효율적 인 압축 알고리즘이라는 것을 알게되었습니다 (일반적으로 16 비트 데이터는 비효율적입니다). 위의 코드를 사용하여 검은 색 이미지 (여전히 1760x2140 16 비트/픽셀)를 120KB로 압축했습니다. 랜덤 노이즈로 이미지를 채우면 파일 크기는 7,5 MB가됩니다. LZW 또는 ZLib를 예측기와 함께 사용하면 약 10MB 크기가되지만 데이터가 무작위가 아니기 때문에 더 나은 결과를 얻을 수 있습니다. – haraldK