use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.
the class WritePrecompressedPlanes method main.
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();
}
use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.
the class MinimalTiffReader method close.
/* @see loci.formats.IFormatReader#close(boolean) */
@Override
public void close(boolean fileOnly) throws IOException {
super.close(fileOnly);
if (!fileOnly) {
if (ifds != null) {
for (IFD ifd : ifds) {
try {
if (ifd.getOnDemandStripOffsets() != null) {
ifd.getOnDemandStripOffsets().close();
}
} catch (FormatException e) {
LOGGER.debug("", e);
}
}
}
ifds = null;
thumbnailIFDs = null;
subResolutionIFDs = null;
lastPlane = 0;
tiffParser = null;
resolutionLevels = null;
j2kCodecOptions = null;
seriesToIFD = false;
}
}
use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.
the class MinimalTiffReader method get8BitLookupTable.
/* @see loci.formats.IFormatReader#get8BitLookupTable() */
@Override
public byte[][] get8BitLookupTable() throws FormatException, IOException {
FormatTools.assertId(currentId, true, 1);
if (ifds == null || lastPlane < 0 || lastPlane >= ifds.size())
return null;
IFD lastIFD = ifds.get(lastPlane);
int[] bits = lastIFD.getBitsPerSample();
if (bits[0] <= 8) {
int[] colorMap = tiffParser.getColorMap(lastIFD);
if (colorMap == null) {
// it's possible that the LUT is only present in the first IFD
if (lastPlane != 0) {
lastIFD = ifds.get(0);
colorMap = tiffParser.getColorMap(lastIFD);
if (colorMap == null)
return null;
} else
return null;
}
byte[][] table = new byte[3][colorMap.length / 3];
int next = 0;
for (int j = 0; j < table.length; j++) {
for (int i = 0; i < table[0].length; i++) {
if (colorMap[next] > 255) {
table[j][i] = (byte) ((colorMap[next++] >> 8) & 0xff);
} else {
table[j][i] = (byte) (colorMap[next++] & 0xff);
}
}
}
return table;
}
return null;
}
use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.
the class MinimalTiffReader method initFile.
// -- Internal FormatReader API methods --
/* @see loci.formats.FormatReader#initFile(String) */
@Override
protected void initFile(String id) throws FormatException, IOException {
super.initFile(id);
in = new RandomAccessInputStream(id, 16);
initTiffParser();
Boolean littleEndian = tiffParser.checkHeader();
if (littleEndian == null) {
throw new FormatException("Invalid TIFF file: " + id);
}
boolean little = littleEndian.booleanValue();
in.order(little);
LOGGER.info("Reading IFDs");
IFDList allIFDs = tiffParser.getIFDs();
if (allIFDs == null || allIFDs.size() == 0) {
throw new FormatException("No IFDs found");
}
ifds = new IFDList();
thumbnailIFDs = new IFDList();
subResolutionIFDs = new ArrayList<IFDList>();
for (IFD ifd : allIFDs) {
tiffParser.fillInIFD(ifd);
Number subfile = (Number) ifd.getIFDValue(IFD.NEW_SUBFILE_TYPE);
int subfileType = subfile == null ? 0 : subfile.intValue();
if (subfileType != 1 || allIFDs.size() <= 1) {
ifds.add(ifd);
} else if (subfileType == 1) {
thumbnailIFDs.add(ifd);
}
}
LOGGER.info("Populating metadata");
CoreMetadata ms0 = core.get(0);
ms0.imageCount = ifds.size();
tiffParser.setAssumeEqualStrips(equalStrips);
for (IFD ifd : ifds) {
if ((ifd.getCompression() == TiffCompression.JPEG_2000 || ifd.getCompression() == TiffCompression.JPEG_2000_LOSSY) && ifd.getImageWidth() == ifds.get(0).getImageWidth()) {
LOGGER.debug("Found IFD with JPEG 2000 compression");
long[] stripOffsets = ifd.getStripOffsets();
long[] stripByteCounts = ifd.getStripByteCounts();
if (stripOffsets.length > 0) {
long stripOffset = stripOffsets[0];
in.seek(stripOffset);
JPEG2000MetadataParser metadataParser = new JPEG2000MetadataParser(in, stripOffset + stripByteCounts[0]);
resolutionLevels = metadataParser.getResolutionLevels();
if (resolutionLevels != null && !noSubresolutions) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Original resolution IFD Levels %d %dx%d Tile %dx%d", resolutionLevels, ifd.getImageWidth(), ifd.getImageLength(), ifd.getTileWidth(), ifd.getTileLength()));
}
IFDList theseSubResolutionIFDs = new IFDList();
subResolutionIFDs.add(theseSubResolutionIFDs);
for (int level = 1; level <= resolutionLevels; level++) {
IFD newIFD = new IFD(ifd);
long imageWidth = ifd.getImageWidth();
long imageLength = ifd.getImageLength();
long tileWidth = ifd.getTileWidth();
long tileLength = ifd.getTileLength();
long factor = (long) Math.pow(2, level);
long newTileWidth = Math.round((double) tileWidth / factor);
newTileWidth = newTileWidth < 1 ? 1 : newTileWidth;
long newTileLength = Math.round((double) tileLength / factor);
newTileLength = newTileLength < 1 ? 1 : newTileLength;
long evenTilesPerRow = imageWidth / tileWidth;
long evenTilesPerColumn = imageLength / tileLength;
double remainingWidth = ((double) (imageWidth - (evenTilesPerRow * tileWidth))) / factor;
remainingWidth = remainingWidth < 1 ? Math.ceil(remainingWidth) : Math.round(remainingWidth);
double remainingLength = ((double) (imageLength - (evenTilesPerColumn * tileLength))) / factor;
remainingLength = remainingLength < 1 ? Math.ceil(remainingLength) : Math.round(remainingLength);
long newImageWidth = (long) ((evenTilesPerRow * newTileWidth) + remainingWidth);
long newImageLength = (long) ((evenTilesPerColumn * newTileLength) + remainingLength);
int resolutionLevel = Math.abs(level - resolutionLevels);
newIFD.put(IFD.IMAGE_WIDTH, newImageWidth);
newIFD.put(IFD.IMAGE_LENGTH, newImageLength);
newIFD.put(IFD.TILE_WIDTH, newTileWidth);
newIFD.put(IFD.TILE_LENGTH, newTileLength);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Added JPEG 2000 sub-resolution IFD Level %d %dx%d " + "Tile %dx%d", resolutionLevel, newImageWidth, newImageLength, newTileWidth, newTileLength));
}
theseSubResolutionIFDs.add(newIFD);
}
}
} else {
LOGGER.warn("IFD has no strip offsets!");
}
}
}
IFD firstIFD = ifds.get(0);
PhotoInterp photo = firstIFD.getPhotometricInterpretation();
int samples = firstIFD.getSamplesPerPixel();
ms0.rgb = samples > 1 || photo == PhotoInterp.RGB;
ms0.interleaved = false;
ms0.littleEndian = firstIFD.isLittleEndian();
ms0.sizeX = (int) firstIFD.getImageWidth();
ms0.sizeY = (int) firstIFD.getImageLength();
ms0.sizeZ = 1;
ms0.sizeC = isRGB() ? samples : 1;
ms0.sizeT = ifds.size();
ms0.pixelType = firstIFD.getPixelType();
ms0.metadataComplete = true;
ms0.indexed = photo == PhotoInterp.RGB_PALETTE && (get8BitLookupTable() != null || get16BitLookupTable() != null);
if (isIndexed()) {
ms0.sizeC = 1;
ms0.rgb = false;
for (IFD ifd : ifds) {
ifd.putIFDValue(IFD.PHOTOMETRIC_INTERPRETATION, PhotoInterp.RGB_PALETTE);
}
}
if (getSizeC() == 1 && !isIndexed())
ms0.rgb = false;
ms0.dimensionOrder = "XYCZT";
ms0.bitsPerPixel = firstIFD.getBitsPerSample()[0];
// New core metadata now that we know how many sub-resolutions we have.
if (resolutionLevels != null && subResolutionIFDs.size() > 0) {
IFDList ifds = subResolutionIFDs.get(0);
int seriesCount = ifds.size() + 1;
if (!hasFlattenedResolutions()) {
ms0.resolutionCount = seriesCount;
}
ms0.sizeT = subResolutionIFDs.size();
ms0.imageCount = ms0.sizeT;
if (ms0.sizeT <= 0) {
ms0.sizeT = 1;
}
if (ms0.imageCount <= 0) {
ms0.imageCount = 1;
}
for (IFD ifd : ifds) {
CoreMetadata ms = new CoreMetadata(this, 0);
core.add(ms);
ms.sizeX = (int) ifd.getImageWidth();
ms.sizeY = (int) ifd.getImageLength();
ms.sizeT = ms0.sizeT;
ms.imageCount = ms0.imageCount;
ms.thumbnail = true;
ms.resolutionCount = 1;
}
}
MetadataStore store = makeFilterMetadata();
MetadataTools.populatePixels(store, this);
}
use of loci.formats.tiff.IFD in project bioformats by openmicroscopy.
the class MinimalTiffReader method openBytes.
/**
* @see loci.formats.FormatReader#openBytes(int, byte[], int, int, int, int)
*/
@Override
public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) throws FormatException, IOException {
FormatTools.checkPlaneParameters(this, no, buf.length, x, y, w, h);
IFD firstIFD = ifds.get(0);
lastPlane = no;
IFD ifd;
if (seriesToIFD) {
ifd = ifds.get(getSeries());
} else {
ifd = ifds.get(no);
}
if ((firstIFD.getCompression() == TiffCompression.JPEG_2000 || firstIFD.getCompression() == TiffCompression.JPEG_2000_LOSSY) && resolutionLevels != null) {
if (getCoreIndex() > 0) {
ifd = subResolutionIFDs.get(no).get(getCoreIndex() - 1);
}
setResolutionLevel(ifd);
}
if (tiffParser == null) {
initTiffParser();
}
tiffParser.getSamples(ifd, buf, x, y, w, h);
boolean float16 = getPixelType() == FormatTools.FLOAT && firstIFD.getBitsPerSample()[0] == 16;
boolean float24 = getPixelType() == FormatTools.FLOAT && firstIFD.getBitsPerSample()[0] == 24;
if (float16 || float24) {
int nPixels = w * h * getRGBChannelCount();
int nBytes = float16 ? 2 : 3;
int mantissaBits = float16 ? 10 : 16;
int exponentBits = float16 ? 5 : 7;
int maxExponent = (int) Math.pow(2, exponentBits) - 1;
int bits = (nBytes * 8) - 1;
byte[] newBuf = new byte[buf.length];
for (int i = 0; i < nPixels; i++) {
int v = DataTools.bytesToInt(buf, i * nBytes, nBytes, isLittleEndian());
int sign = v >> bits;
int exponent = (v >> mantissaBits) & (int) (Math.pow(2, exponentBits) - 1);
int mantissa = v & (int) (Math.pow(2, mantissaBits) - 1);
if (exponent == 0) {
if (mantissa != 0) {
while ((mantissa & (int) Math.pow(2, mantissaBits)) == 0) {
mantissa <<= 1;
exponent--;
}
exponent++;
mantissa &= (int) (Math.pow(2, mantissaBits) - 1);
exponent += 127 - (Math.pow(2, exponentBits - 1) - 1);
}
} else if (exponent == maxExponent) {
exponent = 255;
} else {
exponent += 127 - (Math.pow(2, exponentBits - 1) - 1);
}
mantissa <<= (23 - mantissaBits);
int value = (sign << 31) | (exponent << 23) | mantissa;
DataTools.unpackBytes(value, newBuf, i * 4, 4, isLittleEndian());
}
System.arraycopy(newBuf, 0, buf, 0, newBuf.length);
}
return buf;
}
Aggregations