Search in sources :

Example 51 with IFD

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();
}
Also used : IFD(loci.formats.tiff.IFD) RandomAccessOutputStream(loci.common.RandomAccessOutputStream) TiffSaver(loci.formats.tiff.TiffSaver) RandomAccessInputStream(loci.common.RandomAccessInputStream) ImageReader(loci.formats.ImageReader)

Example 52 with IFD

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;
    }
}
Also used : IFD(loci.formats.tiff.IFD) FormatException(loci.formats.FormatException)

Example 53 with IFD

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;
}
Also used : IFD(loci.formats.tiff.IFD)

Example 54 with IFD

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);
}
Also used : IFD(loci.formats.tiff.IFD) PhotoInterp(loci.formats.tiff.PhotoInterp) CoreMetadata(loci.formats.CoreMetadata) FormatException(loci.formats.FormatException) MetadataStore(loci.formats.meta.MetadataStore) IFDList(loci.formats.tiff.IFDList) RandomAccessInputStream(loci.common.RandomAccessInputStream)

Example 55 with IFD

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;
}
Also used : IFD(loci.formats.tiff.IFD)

Aggregations

IFD (loci.formats.tiff.IFD)121 TiffParser (loci.formats.tiff.TiffParser)74 RandomAccessInputStream (loci.common.RandomAccessInputStream)51 CoreMetadata (loci.formats.CoreMetadata)33 FormatException (loci.formats.FormatException)32 MetadataStore (loci.formats.meta.MetadataStore)21 IFDList (loci.formats.tiff.IFDList)21 PhotoInterp (loci.formats.tiff.PhotoInterp)18 IOException (java.io.IOException)17 Location (loci.common.Location)15 ArrayList (java.util.ArrayList)14 Timestamp (ome.xml.model.primitives.Timestamp)11 Length (ome.units.quantity.Length)10 Time (ome.units.quantity.Time)8 TiffIFDEntry (loci.formats.tiff.TiffIFDEntry)7 TiffRational (loci.formats.tiff.TiffRational)6 File (java.io.File)5 TiffReader (loci.formats.in.TiffReader)5 NonNegativeInteger (ome.xml.model.primitives.NonNegativeInteger)5 PositiveInteger (ome.xml.model.primitives.PositiveInteger)5