//
// WritePrecompressedPlanes.java
//

import java.io.IOException;

import loci.common.RandomAccessInputStream;
import loci.common.RandomAccessOutputStream;
import loci.formats.FormatException;
import loci.formats.FormatTools;
import loci.formats.ImageReader;
import loci.formats.MetadataTools;
import loci.formats.meta.IMetadata;
import loci.formats.tiff.IFD;
import loci.formats.tiff.TiffCompression;
import loci.formats.tiff.TiffSaver;

import ome.xml.model.primitives.PositiveInteger;

/**
 * Writes the pixels from a set of JPEG files to a single TIFF.
 * The pixel data is used as-is, so no decompression or re-compression is
 * performed.
 *
 * <dl><dt><b>Source code:</b></dt>
 * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/bio-formats/utils/WritePrecompressedPlanes.java">Trac</a>,
 * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/bio-formats/utils/WritePrecompressedPlanes.java;hb=HEAD">Gitweb</a></dd></dl>
 */
public class WritePrecompressedPlanes {
  public static void main(String[] args) throws FormatException, IOException {
    // print usage if no args specified
    if (args.length == 0) {
      System.out.println("Usage: java WritePrecompressedPlanes " +
        "[input file 1] ... [input file n] [output file]");
      System.exit(0);
    }

    // first n - 1 args are the input files
    String[] inputFiles = new String[args.length - 1];
    System.arraycopy(args, 0, inputFiles, 0, inputFiles.length);

    // last arg is the output file
    String outputFile = args[args.length - 1];

    // open up one of the input files so that we can read the metadata
    // this assumes that the dimensions of the input files are the same
    ImageReader reader = new ImageReader();
    reader.setId(inputFiles[0]);
    int pixelType = reader.getPixelType();

    // write the pixel data to the output file
    RandomAccessOutputStream out = new RandomAccessOutputStream(outputFile);
    TiffSaver saver = new TiffSaver(out, outputFile);
    saver.setWritingSequentially(true);
    saver.setLittleEndian(reader.isLittleEndian());
    saver.setBigTiff(false);
    saver.writeHeader();

    for (int i=0; i<inputFiles.length; i++) {
      RandomAccessInputStream in = new RandomAccessInputStream(inputFiles[i]);
      byte[] buf = new byte[(int) in.length()];
      in.readFully(buf);
      in.close();

      IFD ifd = new IFD();
      ifd.put(IFD.IMAGE_WIDTH, reader.getSizeX());
      ifd.put(IFD.IMAGE_LENGTH, reader.getSizeY());
      ifd.put(IFD.LITTLE_ENDIAN, reader.isLittleEndian());
      ifd.put(IFD.SAMPLE_FORMAT, FormatTools.isSigned(pixelType) ? 2 :
        FormatTools.isFloatingPoint(pixelType) ? 3 : 1);
      ifd.put(IFD.PLANAR_CONFIGURATION, 1);
      ifd.put(IFD.REUSE, out.length());
      out.seek(out.length());

      // this is very important
      // the data is already compressed in a single chunk, so setting the
      // number of rows per strip to something smaller than the full height
      // will require us to re-compress the data
      ifd.put(IFD.ROWS_PER_STRIP, reader.getSizeY());

      saver.writeImage(buf, ifd, i, pixelType, 0, 0, reader.getSizeX(),
        reader.getSizeY(), i == inputFiles.length - 1,
        reader.getRGBChannelCount(), true);
    }

    reader.close();
    out.close();

    // reset the TIFF file's compression flag
    // you cannot do this before the pixel data is written, otherwise
    // the pixels will be re-compressed

    saver = new TiffSaver(outputFile);
    for (int i=0; i<inputFiles.length; i++) {
      RandomAccessInputStream in = new RandomAccessInputStream(outputFile);
      saver.overwriteLastIFDOffset(in);
      saver.overwriteIFDValue(in, i, IFD.COMPRESSION,
        TiffCompression.JPEG.getCode());
      in.close();
    }
    saver.getStream().close();
  }
}

Add an example that illustrates writing pre-compressed planes.