Skip to content

Commit

Permalink
Issue jai-imageio#37 support for LSB LWZ compressed TIFF
Browse files Browse the repository at this point in the history
  • Loading branch information
lbellonda committed May 20, 2017
1 parent 20a9a77 commit 0d6b4ca
Show file tree
Hide file tree
Showing 24 changed files with 269 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1528,5 +1528,20 @@ protected static BufferedImage getDestination(ImageReadParam param,
}

return imageType.createBufferedImage(destWidth, destHeight);
}
}

protected boolean isLsb()
{
boolean isLsb = false;
if( null != imageMetadata ) {
// Get the fillOrder field.
TIFFField fillOrderField =
imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER);

if(fillOrderField != null && fillOrderField.getAsInt(0) == 2) {
isLsb = true ;
}
}
return isLsb ;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,18 @@
package com.github.jaiimageio.impl.plugins.tiff;

import java.io.IOException;
import java.nio.ByteOrder;

import javax.imageio.IIOException;

import com.github.jaiimageio.plugins.tiff.BaselineTIFFTagSet;
import com.github.jaiimageio.plugins.tiff.TIFFDecompressor;
import com.github.jaiimageio.plugins.tiff.TIFFField;

public class TIFFLZWDecompressor extends TIFFDecompressor {

private static final boolean DEBUG = false;
private static final boolean TRACE = false;

private static final int andTable[] = {
511,
Expand All @@ -75,6 +78,8 @@ public class TIFFLZWDecompressor extends TIFFDecompressor {

int nextData = 0;
int nextBits = 0;

boolean isLSB = false;

public TIFFLZWDecompressor(int predictor) throws IIOException {
super();
Expand Down Expand Up @@ -142,72 +147,89 @@ public void decodeRaw(byte[] b,
}
}
}

public int decode(byte[] sdata, int srcOffset,
byte[] ddata, int dstOffset)
throws IOException {
if (sdata[0] == (byte)0x00 && sdata[1] == (byte)0x01) {
throw new IIOException
("TIFF 5.0-style LZW compression is not supported!");
}

this.srcData = sdata;
this.dstData = ddata;

this.srcIndex = srcOffset;
this.dstIndex = dstOffset;

this.nextData = 0;
this.nextBits = 0;

initializeStringTable();

int code, oldCode = 0;
byte[] string;

while ((code = getNextCode()) != 257) {
if (code == 256) {
initializeStringTable();
code = getNextCode();
if (code == 257) {
break;
}

writeString(stringTable[code]);
oldCode = code;
} else {
if (code < tableIndex) {
string = stringTable[code];

writeString(string);
addStringToTable(stringTable[oldCode], string[0]);
oldCode = code;
} else {
string = stringTable[oldCode];
string = composeString(string, string[0]);
writeString(string);
addStringToTable(string);
oldCode = code;
}
}
}

if (predictor ==
BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) {

for (int j = 0; j < srcHeight; j++) {

int count = dstOffset + samplesPerPixel * (j * srcWidth + 1);

for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {

dstData[count] += dstData[count - samplesPerPixel];
count++;
}
}
}

return dstIndex - dstOffset;
byte[] ddata, int dstOffset)
throws IOException {
if (sdata[0] == (byte)0x00 && sdata[1] == (byte)0x01) {
throw new IIOException
("TIFF 5.0-style LZW compression is not supported!");
}

this.srcData = sdata;
this.dstData = ddata;

this.srcIndex = srcOffset;
this.dstIndex = dstOffset;

this.nextData = 0;
this.nextBits = 0;

isLSB = false ;
if(null != reader ) {
if( reader instanceof TIFFImageReader) {
isLSB = ((TIFFImageReader)reader).isLsb();
}
}
initializeStringTable();

int code, oldCode = 0;
byte[] string;
if(TRACE) {
System.out.println("start: ");
}
while ((code = getNextCode()) != 257) {
if(TRACE) {
System.out.println("Code: "+code);
}
if (code == 256) {
if(TRACE) {
System.out.println("reset");
}
initializeStringTable();
code = getNextCode();
if(TRACE) {
System.out.println("Code2: "+code);
}
if (code == 257) {
break;
}

writeString(stringTable[code]);
oldCode = code;
} else {
if (code < tableIndex) {
string = stringTable[code];

writeString(string);
addStringToTable(stringTable[oldCode], string[0]);
oldCode = code;
} else {
string = stringTable[oldCode];
string = composeString(string, string[0]);
writeString(string);
addStringToTable(string);
oldCode = code;
}
}
}

if (predictor ==
BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) {

for (int j = 0; j < srcHeight; j++) {

int count = dstOffset + samplesPerPixel * (j * srcWidth + 1);

for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {

dstData[count] += dstData[count - samplesPerPixel];
count++;
}
}
}

return dstIndex - dstOffset;
}

/**
Expand All @@ -223,6 +245,7 @@ public void initializeStringTable() {

tableIndex = 258;
bitsToGet = 9;

}

/**
Expand Down Expand Up @@ -287,6 +310,22 @@ public byte[] composeString(byte oldString[], byte newString) {

return string;
}

private int reverseBits(int inp)
{
int iz = 0 ;
int po2 = 1;
int rev = 0x80;
for( int i = 0 ; i < 8 ; i++) {
if( (inp & po2 ) != 0 ) {
iz += rev;
}
po2 <<= 1 ;
rev >>= 1;

}
return iz;
}

// Returns the next 9, 10, 11 or 12 bits
public int getNextCode() {
Expand All @@ -296,23 +335,44 @@ public int getNextCode() {
// in practice.

try {
nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff);
nextBits += 8;

if (nextBits < bitsToGet) {
nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff);
nextBits += 8;
}

int code =
(nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet - 9];
nextBits -= bitsToGet;

return code;
if(!isLSB) {
int iz = srcData[srcIndex++] &0x00FF;
nextData = (nextData << 8) | (iz& 0xff);
nextBits += 8;

if (nextBits < bitsToGet) {
iz = srcData[srcIndex++] &0x00FF;
nextData = (nextData << 8) | (iz & 0xff);
nextBits += 8;
}

int code =
(nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet - 9];
nextBits -= bitsToGet;

return code;
} else {
int iz = reverseBits( srcData[srcIndex++] &0x00FF);
nextData = (nextData << 8) | (iz& 0xff);
nextBits += 8;

if (nextBits < bitsToGet) {
iz = reverseBits( srcData[srcIndex++] &0x00FF);
nextData = (nextData << 8) | (iz & 0xff);
nextBits += 8;
}

int code =
(nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet - 9];
nextBits -= bitsToGet;

return code;
}
} catch (ArrayIndexOutOfBoundsException e) {
// Strip not terminated as expected: return EndOfInformation code.
return 257;
}
}

}

Loading

0 comments on commit 0d6b4ca

Please sign in to comment.