Program: 33386
Project: 33386
Buggy source:
/** 
 * Merges a list of TIFF images into one regardless of the original bit depth
 * @param merged RandomAccessOutputStream for the merged TIFF
 * @param images input TIFF image files to be merged
 * @throws IOException
 */
public static void mergeTiffImagesEx(RandomAccessOutputStream merged,File... images) throws IOException {
  if (images != null && images.length > 1) {
    FileInputStream fis1=new FileInputStream(images[0]);
    RandomAccessInputStream image1=new FileCacheRandomAccessInputStream(fis1);
    List<IFD> ifds1=new ArrayList<IFD>();
    int offset1=copyHeader(image1,merged);
    readIFDs(null,null,TiffTag.class,ifds1,offset1,image1);
    for (int i=0; i < ifds1.size(); i++) {
      ifds1.get(i).removeField(TiffTag.PAGE_NUMBER.getValue());
      ifds1.get(i).addField(new ShortField(TiffTag.PAGE_NUMBER.getValue(),new short[]{0,0}));
    }
    int offset=copyPages(ifds1,FIRST_WRITE_OFFSET,image1,merged);
    image1.close();
    fis1.close();
    short writeEndian=merged.getEndian();
    for (int i=1; i < images.length; i++) {
      List<IFD> ifds2=new ArrayList<IFD>();
      FileInputStream fis2=new FileInputStream(images[i]);
      RandomAccessInputStream image2=new FileCacheRandomAccessInputStream(fis2);
      readIFDs(ifds2,image2);
      for (int j=0; j < ifds2.size(); j++) {
        ifds2.get(j).removeField(TiffTag.PAGE_NUMBER.getValue());
        ifds2.get(j).addField(new ShortField(TiffTag.PAGE_NUMBER.getValue(),new short[]{0,0}));
      }
      short readEndian=image2.getEndian();
      if (readEndian == writeEndian)       offset=copyPages(ifds2,offset,image2,merged);
 else {
        IFD prevIFD=null;
        for (int j=0; j < ifds2.size(); j++) {
          IFD currIFD=ifds2.get(j);
          int bitsPerSample=currIFD.getField(TiffTag.BITS_PER_SAMPLE.getValue()).getDataAsLong()[0];
          if (bitsPerSample <= 8) {
            offset=copyPageData(currIFD,offset,image2,merged);
          }
 else {
            ImageDecoder decoder=null;
            ImageEncoder encoder=null;
            TiffField<?> stripOffSets=currIFD.removeField(TiffTag.STRIP_OFFSETS.getValue());
            if (stripOffSets == null)             stripOffSets=currIFD.removeField(TiffTag.TILE_OFFSETS.getValue());
            TiffField<?> stripByteCounts=currIFD.getField(TiffTag.STRIP_BYTE_COUNTS.getValue());
            if (stripByteCounts == null)             stripByteCounts=currIFD.getField(TiffTag.TILE_BYTE_COUNTS.getValue());
            TiffField<?> f_rowsPerStrip=currIFD.getField(TiffTag.ROWS_PER_STRIP.getValue());
            int imageWidth=currIFD.getField(TiffTag.IMAGE_WIDTH.getValue()).getDataAsLong()[0];
            int imageHeight=currIFD.getField(TiffTag.IMAGE_LENGTH.getValue()).getDataAsLong()[0];
            TiffField<?> f_tileLength=currIFD.getField(TiffTag.TILE_LENGTH.getValue());
            TiffField<?> f_tileWidth=currIFD.getField(TiffTag.TILE_WIDTH.getValue());
            int samplesPerPixel=currIFD.getField(TiffTag.SAMPLES_PER_PIXEL.getValue()).getDataAsLong()[0];
            int rowsPerStrip=imageHeight;
            if (f_rowsPerStrip != null)             rowsPerStrip=f_rowsPerStrip.getDataAsLong()[0];
            int tileWidth=-1;
            int tileLength=-1;
            if (f_tileWidth != null) {
              tileWidth=f_tileWidth.getDataAsLong()[0];
              tileLength=f_tileLength.getDataAsLong()[0];
            }
            int maximumLen=(imageWidth * rowsPerStrip * samplesPerPixel* bitsPerSample + 7) / 8;
            if (tileWidth > 0) {
              maximumLen=(tileWidth * tileLength * samplesPerPixel* bitsPerSample + 7) / 8;
            }
            if (stripOffSets != null) {
              int[] counts=stripByteCounts.getDataAsLong();
              int[] off=stripOffSets.getDataAsLong();
              int[] temp=new int[off.length];
              merged.seek(offset);
              TiffField<?> tiffField=currIFD.getField(TiffTag.COMPRESSION.getValue());
              TiffFieldEnum.Compression compression=TiffFieldEnum.Compression.fromValue(tiffField.getDataAsLong()[0]);
switch (compression) {
case LZW:
                decoder=new LZWTreeDecoder(8,true);
              encoder=new LZWTreeEncoder(merged,8,4096,null);
            break;
case DEFLATE:
case DEFLATE_ADOBE:
          decoder=new DeflateDecoder();
        encoder=new DeflateEncoder(merged,4096,4,null);
      break;
case PACKBITS:
    int rowsRemain=imageHeight;
  int bytesPerScanLine=(imageWidth * samplesPerPixel * bitsPerSample + 7) / 8;
for (int k=0; k < off.length; k++) {
  int rows2Read=Math.min(rowsPerStrip,rowsRemain);
  image2.seek(off[k]);
  byte[] buf=new byte[counts[k]];
  image2.readFully(buf);
  int bytesRead=rows2Read * bytesPerScanLine;
  byte[] buf2=new byte[tileWidth > 0 ? maximumLen : bytesRead];
  Packbits.unpackbits(buf,buf2);
  rowsRemain-=rows2Read;
  short[] sbuf=ArrayUtils.byteArrayToShortArray(buf2,0,buf2.length,readEndian == IOUtils.BIG_ENDIAN);
  buf=ArrayUtils.shortArrayToByteArray(sbuf,writeEndian == IOUtils.BIG_ENDIAN);
  buf2=new byte[buf.length + (buf.length + 127) / 128];
  int bytesCompressed=Packbits.packbits(buf,buf2);
  merged.write(buf2,0,bytesCompressed);
  temp[k]=offset;
  offset+=bytesCompressed;
}
break;
case NONE:
for (int k=0; k < off.length; k++) {
image2.seek(off[k]);
byte[] buf=new byte[counts[k]];
image2.readFully(buf);
short[] sbuf=ArrayUtils.byteArrayToShortArray(buf,readEndian == IOUtils.BIG_ENDIAN);
buf=ArrayUtils.shortArrayToByteArray(sbuf,writeEndian == IOUtils.BIG_ENDIAN);
merged.write(buf);
temp[k]=offset;
offset+=buf.length;
}
break;
default :
for (int l=0; l < off.length; l++) {
image2.seek(off[l]);
byte[] buf=new byte[counts[l]];
image2.readFully(buf);
merged.write(buf);
temp[l]=offset;
offset+=buf.length;
}
break;
}
if (decoder != null) {
for (int k=0; k < off.length; k++) {
image2.seek(off[k]);
byte[] buf=new byte[counts[k]];
image2.readFully(buf);
decoder.setInput(buf);
int bytesDecompressed=0;
byte[] decompressed=new byte[maximumLen];
try {
bytesDecompressed=decoder.decode(decompressed,0,maximumLen);
}
 catch (Exception e) {
e.printStackTrace();
}
short[] sbuf=ArrayUtils.byteArrayToShortArray(decompressed,0,bytesDecompressed,readEndian == IOUtils.BIG_ENDIAN);
buf=ArrayUtils.shortArrayToByteArray(sbuf,writeEndian == IOUtils.BIG_ENDIAN);
try {
encoder.initialize();
encoder.encode(buf,0,buf.length);
encoder.finish();
}
 catch (Exception e) {
e.printStackTrace();
}
temp[k]=offset;
offset+=encoder.getCompressedDataLen();
}
}
if (currIFD.getField(TiffTag.STRIP_BYTE_COUNTS.getValue()) != null) stripOffSets=new LongField(TiffTag.STRIP_OFFSETS.getValue(),temp);
 else stripOffSets=new LongField(TiffTag.TILE_OFFSETS.getValue(),temp);
currIFD.addField(stripOffSets);
}
}
if (prevIFD != null) prevIFD.setNextIFDOffset(merged,offset);
offset=currIFD.write(merged,offset);
prevIFD=currIFD;
}
}
ifds1.get(ifds1.size() - 1).setNextIFDOffset(merged,ifds2.get(0).getStartOffset());
ifds1.addAll(ifds2);
image2.close();
fis2.close();
}
int maxPageNumber=ifds1.size();
for (int i=0; i < ifds1.size(); i++) {
offset=ifds1.get(i).getField(TiffTag.PAGE_NUMBER.getValue()).getDataOffset();
merged.seek(offset);
merged.writeShort((short)i);
merged.writeShort((short)maxPageNumber);
}
int firstIFDOffset=ifds1.get(0).getStartOffset();
writeToStream(merged,firstIFDOffset);
}
}

Fixed version (ground truth):
/** 
 * Merges a list of TIFF images into one regardless of the original bit depth
 * @param merged RandomAccessOutputStream for the merged TIFF
 * @param images input TIFF image files to be merged
 * @throws IOException
 */
public static void mergeTiffImagesEx(RandomAccessOutputStream merged,File... images) throws IOException {
  if (images != null && images.length > 1) {
    FileInputStream fis1=new FileInputStream(images[0]);
    RandomAccessInputStream image1=new FileCacheRandomAccessInputStream(fis1);
    List<IFD> ifds1=new ArrayList<IFD>();
    int offset1=copyHeader(image1,merged);
    readIFDs(null,null,TiffTag.class,ifds1,offset1,image1);
    for (int i=0; i < ifds1.size(); i++) {
      ifds1.get(i).removeField(TiffTag.PAGE_NUMBER.getValue());
      ifds1.get(i).addField(new ShortField(TiffTag.PAGE_NUMBER.getValue(),new short[]{0,0}));
    }
    int offset=copyPages(ifds1,FIRST_WRITE_OFFSET,image1,merged);
    image1.close();
    fis1.close();
    short writeEndian=merged.getEndian();
    for (int i=1; i < images.length; i++) {
      List<IFD> ifds2=new ArrayList<IFD>();
      FileInputStream fis2=new FileInputStream(images[i]);
      RandomAccessInputStream image2=new FileCacheRandomAccessInputStream(fis2);
      readIFDs(ifds2,image2);
      for (int j=0; j < ifds2.size(); j++) {
        ifds2.get(j).removeField(TiffTag.PAGE_NUMBER.getValue());
        ifds2.get(j).addField(new ShortField(TiffTag.PAGE_NUMBER.getValue(),new short[]{0,0}));
      }
      short readEndian=image2.getEndian();
      if (readEndian == writeEndian)       offset=copyPages(ifds2,offset,image2,merged);
 else {
        IFD prevIFD=null;
        for (int j=0; j < ifds2.size(); j++) {
          IFD currIFD=ifds2.get(j);
          int bitsPerSample=1;
          TiffField<?> f_bitsPerSample=currIFD.getField(TiffTag.BITS_PER_SAMPLE.getValue());
          if (f_bitsPerSample != null)           bitsPerSample=f_bitsPerSample.getDataAsLong()[0];
          if (bitsPerSample <= 8) {
            offset=copyPageData(currIFD,offset,image2,merged);
          }
 else {
            ImageDecoder decoder=null;
            ImageEncoder encoder=null;
            TiffField<?> stripOffSets=currIFD.removeField(TiffTag.STRIP_OFFSETS.getValue());
            if (stripOffSets == null)             stripOffSets=currIFD.removeField(TiffTag.TILE_OFFSETS.getValue());
            TiffField<?> stripByteCounts=currIFD.getField(TiffTag.STRIP_BYTE_COUNTS.getValue());
            if (stripByteCounts == null)             stripByteCounts=currIFD.getField(TiffTag.TILE_BYTE_COUNTS.getValue());
            TiffField<?> f_rowsPerStrip=currIFD.getField(TiffTag.ROWS_PER_STRIP.getValue());
            int imageWidth=currIFD.getField(TiffTag.IMAGE_WIDTH.getValue()).getDataAsLong()[0];
            int imageHeight=currIFD.getField(TiffTag.IMAGE_LENGTH.getValue()).getDataAsLong()[0];
            TiffField<?> f_tileLength=currIFD.getField(TiffTag.TILE_LENGTH.getValue());
            TiffField<?> f_tileWidth=currIFD.getField(TiffTag.TILE_WIDTH.getValue());
            int samplesPerPixel=1;
            TiffField<?> f_samplesPerPixel=currIFD.getField(TiffTag.SAMPLES_PER_PIXEL.getValue());
            if (f_samplesPerPixel != null)             samplesPerPixel=f_samplesPerPixel.getDataAsLong()[0];
            int rowsPerStrip=imageHeight;
            if (f_rowsPerStrip != null)             rowsPerStrip=f_rowsPerStrip.getDataAsLong()[0];
            int tileWidth=-1;
            int tileLength=-1;
            if (f_tileWidth != null) {
              tileWidth=f_tileWidth.getDataAsLong()[0];
              tileLength=f_tileLength.getDataAsLong()[0];
            }
            int maximumLen=(imageWidth * rowsPerStrip * samplesPerPixel* bitsPerSample + 7) / 8;
            if (tileWidth > 0) {
              maximumLen=(tileWidth * tileLength * samplesPerPixel* bitsPerSample + 7) / 8;
            }
            if (stripOffSets != null) {
              int[] counts=stripByteCounts.getDataAsLong();
              int[] off=stripOffSets.getDataAsLong();
              int[] temp=new int[off.length];
              merged.seek(offset);
              TiffField<?> tiffField=currIFD.getField(TiffTag.COMPRESSION.getValue());
              TiffFieldEnum.Compression compression=TiffFieldEnum.Compression.fromValue(tiffField.getDataAsLong()[0]);
switch (compression) {
case LZW:
                decoder=new LZWTreeDecoder(8,true);
              encoder=new LZWTreeEncoder(merged,8,4096,null);
            break;
case DEFLATE:
case DEFLATE_ADOBE:
          decoder=new DeflateDecoder();
        encoder=new DeflateEncoder(merged,4096,4,null);
      break;
case PACKBITS:
    int rowsRemain=imageHeight;
  int bytesPerScanLine=(imageWidth * samplesPerPixel * bitsPerSample + 7) / 8;
for (int k=0; k < off.length; k++) {
  int rows2Read=Math.min(rowsPerStrip,rowsRemain);
  image2.seek(off[k]);
  byte[] buf=new byte[counts[k]];
  image2.readFully(buf);
  int bytesRead=rows2Read * bytesPerScanLine;
  byte[] buf2=new byte[tileWidth > 0 ? maximumLen : bytesRead];
  Packbits.unpackbits(buf,buf2);
  rowsRemain-=rows2Read;
  short[] sbuf=ArrayUtils.byteArrayToShortArray(buf2,0,buf2.length,readEndian == IOUtils.BIG_ENDIAN);
  buf=ArrayUtils.shortArrayToByteArray(sbuf,writeEndian == IOUtils.BIG_ENDIAN);
  buf2=new byte[buf.length + (buf.length + 127) / 128];
  int bytesCompressed=Packbits.packbits(buf,buf2);
  merged.write(buf2,0,bytesCompressed);
  temp[k]=offset;
  offset+=bytesCompressed;
}
break;
case NONE:
for (int k=0; k < off.length; k++) {
image2.seek(off[k]);
byte[] buf=new byte[counts[k]];
image2.readFully(buf);
short[] sbuf=ArrayUtils.byteArrayToShortArray(buf,readEndian == IOUtils.BIG_ENDIAN);
buf=ArrayUtils.shortArrayToByteArray(sbuf,writeEndian == IOUtils.BIG_ENDIAN);
merged.write(buf);
temp[k]=offset;
offset+=buf.length;
}
break;
default :
for (int l=0; l < off.length; l++) {
image2.seek(off[l]);
byte[] buf=new byte[counts[l]];
image2.readFully(buf);
merged.write(buf);
temp[l]=offset;
offset+=buf.length;
}
break;
}
if (decoder != null) {
for (int k=0; k < off.length; k++) {
image2.seek(off[k]);
byte[] buf=new byte[counts[k]];
image2.readFully(buf);
decoder.setInput(buf);
int bytesDecompressed=0;
byte[] decompressed=new byte[maximumLen];
try {
bytesDecompressed=decoder.decode(decompressed,0,maximumLen);
}
 catch (Exception e) {
e.printStackTrace();
}
short[] sbuf=ArrayUtils.byteArrayToShortArray(decompressed,0,bytesDecompressed,readEndian == IOUtils.BIG_ENDIAN);
buf=ArrayUtils.shortArrayToByteArray(sbuf,writeEndian == IOUtils.BIG_ENDIAN);
try {
encoder.initialize();
encoder.encode(buf,0,buf.length);
encoder.finish();
}
 catch (Exception e) {
e.printStackTrace();
}
temp[k]=offset;
offset+=encoder.getCompressedDataLen();
}
}
if (currIFD.getField(TiffTag.STRIP_BYTE_COUNTS.getValue()) != null) stripOffSets=new LongField(TiffTag.STRIP_OFFSETS.getValue(),temp);
 else stripOffSets=new LongField(TiffTag.TILE_OFFSETS.getValue(),temp);
currIFD.addField(stripOffSets);
}
}
if (prevIFD != null) prevIFD.setNextIFDOffset(merged,offset);
offset=currIFD.write(merged,offset);
prevIFD=currIFD;
}
}
ifds1.get(ifds1.size() - 1).setNextIFDOffset(merged,ifds2.get(0).getStartOffset());
ifds1.addAll(ifds2);
image2.close();
fis2.close();
}
int maxPageNumber=ifds1.size();
for (int i=0; i < ifds1.size(); i++) {
offset=ifds1.get(i).getField(TiffTag.PAGE_NUMBER.getValue()).getDataOffset();
merged.seek(offset);
merged.writeShort((short)i);
merged.writeShort((short)maxPageNumber);
}
int firstIFDOffset=ifds1.get(0).getStartOffset();
writeToStream(merged,firstIFDOffset);
}
}