This discussion is archived
1 Reply Latest reply: Nov 2, 2011 11:16 PM by Maxideon RSS

TIFF imageio: how did little endian input files get changed to big?

BanjoMon Newbie
Currently Being Moderated
The program below reads in multiple single page TIFFs with "II" little endian on an Intel computer, adds the metadata tag field, creates a multipage TIFF output. Somehow, it ends up "MM" big endian? How do I fix this? The ByteOrder command doesn't seem to do any good? With multiple classes called imageio, it's very confusing. While I'm looking forward to java7fx, this needs to run with JDK6_27 for now. Thanks in advanced for any suggestions.

Test.java:
package test;

import com.sun.media.imageio.plugins.tiff.TIFFField;
import com.sun.media.imageio.plugins.tiff.TIFFTag;
import com.sun.media.imageioimpl.plugins.tiff.TIFFIFD;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteOrder;
import java.util.Date;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

/**
* Read images, add metadata field then save it as a tiff.
*/
public class Test
{
static final String tagfield = "Testing123";
static final String ext = "tiff";


/**
* Main program.
*
* @param args Command line arguments not used.
*/
public static void main(String[] args)
{
try
{
Test image = new Test();
image.create(tagfield);
}
catch (Exception ex)
{
ex.printStackTrace(System.err);
}
} // end main


/**
* Create a new TIFF.
*
* @param tagfield Metadata.
* @throws Exception
*/
private void create(final String tagfield) throws Exception
{
System.out.println(new Date()); // log start time...

String[] infile =
{
"Test1.tiff", "Test2.tiff"
};

String outfile = "finalAnswer.tiff";

save(tagfield, infile, ext, outfile); // create multi-page TIFF...

System.out.println(new Date() + " output: " + outfile);
} // end create


/**
* Save multi-page image.
*
* @param tagfield Metadata.
* @param filenames Input path and filename of each page.
* @param ext File format extension (tiff).
* @param outputFileName Output filename with extension (tiff).
* @return Negative error code or positive number if successful.
*/
public static int save(String tagfield, String[] filenames, String ext, String outputFileName)
{
int success = 0;

if (ext.equalsIgnoreCase("tiff"))
{
ImageOutputStream outstream = null;
ImageWriter writer = null;
try
{
// verify images exist & create File array from filenames...
File[] files = new File[filenames.length];
for (int i = 0; i < filenames.length; i++)
{
files[i] = new File(filenames);
if (!files[i].exists())
{
System.err.println(i + " Error: file not found, " + filenames[i]);
success = success - 1;
// TODO: throw exception or get out of here...
} // end if
} // end if

// open output file...
File file = new File(outputFileName);
if (file.exists())
{
file.delete();
}
file.createNewFile();
outstream = ImageIO.createImageOutputStream(file);

// find an image writer...
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(ext);
if ((writers == null) || !writers.hasNext())
{
System.err.println("Writer not found: " + ext);
success = -999;
// TODO: throw exception or get out of here...
} // end if

writer = ImageIO.getImageWritersByFormatName(ext).next();
outstream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
writer.setOutput(outstream);

// TODO: set compression parameters for image...get from existing?
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_COPY_FROM_METADATA);
// was explicit mode...
String compressionType = null;
//compressionType = "CCITT RLE";
//compressionType = "CCITT T.4";
//compressionType = "CCITT T.6";
//compressionType = "LZW";
//compressionType = "JPEG";
//compressionType = "ZLib";
//compressionType = "PackBits";
//compressionType = "Deflate";
if (compressionType != null)
{
param.setCompressionType(compressionType);
param.setCompressionQuality(0.9f); // 90%
} // end if
// param.setTilingMode();

// TIFF tag: name, number, datatype
TIFFTag tag = new TIFFTag("testTag", 22, (1 << TIFFTag.TIFF_ASCII));
// wrap metadata in string array to create TIFF field...
String[] array = new String[1];
array[0] = tagfield;
TIFFField field = new TIFFField(tag, TIFFTag.TIFF_ASCII, array.length, array);

// for every image, append page to file...
for (int page = 0; page < files.length; page++)
{
FileInputStream instream = null;
try
{
instream = new FileInputStream(files[page]);
ImageInputStream imageInputStream = ImageIO.createImageInputStream(instream);
imageInputStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
ImageReader reader = ImageIO.getImageReaders(imageInputStream).next();
reader.setInput(imageInputStream, true); // seek forward only
// reading in single page images so index is always zero...
IIOMetadata image_metadata = reader.getImageMetadata(0);
TIFFImageMetadata tiff_metadata = (TIFFImageMetadata) image_metadata;
BufferedImage image = reader.read(0);
// image, thumbnails, metadata
IIOImage img = new IIOImage(image, null, tiff_metadata);

if (img != null)
{
if (page == 0)
{
TIFFIFD ifd = tiff_metadata.getRootIFD();
ifd.addTIFFField(field);
writer.write(tiff_metadata, img, param); // first page
// writer.write(null, img, param);
}
else
{
writer.writeInsert(-1, img, param); // append to end
}
image.flush();
success = page + 1;
}
else
{
success = -9999;
// TODO: throw exception...
} // end if
}
catch (Exception ex)
{
ex.printStackTrace(System.err);
}
finally
{
if (instream != null)
{
instream.close();
} // end if
}
} // end for
outstream.flush();
}
catch (Exception ex)
{
ex.printStackTrace(System.err);
}
finally
{
if (outstream != null)
{
try
{
outstream.close();
}
catch (Exception ex)
{
ex.printStackTrace(System.err);
}
} // end if
if (writer != null)
{
writer.dispose();
} // end if
}
}
else
{
System.err.println(ext + " not supported yet--how about a nice tiff");
} // end if

return success;
} // end save
} // end Test
  • 1. Re: TIFF imageio: how did little endian input files get changed to big?
    Maxideon Explorer
    Currently Being Moderated
    Insert this bit of code after you create the writer.
    String nativeFormat = "com_sun_media_imageio_plugins_tiff_stream_1.0";
    IIOMetadata streamMeta = writer.getDefaultStreamMetadata(null);
    Node root = streamMeta.getAsTree(nativeFormat);
    root.getFirstChild().getAttributes().item(0).setNodeValue("LITTLE_ENDIAN");
    try{
        streamMeta.setFromTree(nativeFormat,root);
    }catch(IIOInvalidTreeException e) {
        //shouldn't happen
        throw new Error(e);
    }
    And then change the line where you write:
    writer.write(tiff_metadata, img, param); 
    to
    writer.write(streamMeta, img, param);
    You can delete the byte order calls. They don't do anything. The ImageWriter handles the byte order. You communicate the byte order you want by changing the stream metadata.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points