    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.imaging.formats.tiff;
    018
    019import java.io.IOException;
    020import java.nio.ByteOrder;
    021
    022import org.apache.commons.imaging.ImageReadException;
    023import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
    024import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
    025import org.apache.commons.imaging.formats.tiff.datareaders.ImageDataReader;
    026import org.apache.commons.imaging.formats.tiff.datareaders.DataReaderStrips;
    027import org.apache.commons.imaging.formats.tiff.datareaders.DataReaderTiled;
    028import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreter;
    029
    030public abstract class TiffImageData {
    031    public static class Tiles extends TiffImageData {
    032        public final TiffElement.DataElement[] tiles;
    033
    034        // public final byte tiles[][];
    035        private final int tileWidth;
    036        private final int tileLength;
    037
    038        public Tiles(final TiffElement.DataElement[] tiles, final int tileWidth, final int tileLength) {
    039            this.tiles = tiles;
    040            this.tileWidth = tileWidth;
    041            this.tileLength = tileLength;
    042        }
    043
    044        @Override
    045        public TiffElement.DataElement[] getImageData() {
    046            return tiles;
    047        }
    048
    049        @Override
    050        public boolean stripsNotTiles() {
    051            return false;
    052        }
    053
    054        @Override
    055        public ImageDataReader getDataReader(final TiffDirectory directory,
    056                final PhotometricInterpreter photometricInterpreter,
    057                final int bitsPerPixel, final int[] bitsPerSample, final int predictor,
    058                final int samplesPerPixel, final int width, final int height, final int compression,
    059            final ByteOrder byteOrder) throws IOException, ImageReadException {
    060            int sampleFormat = extractSampleFormat(directory);
    061            return new DataReaderTiled(directory, photometricInterpreter,
    062                    tileWidth, tileLength, bitsPerPixel, bitsPerSample,
    063                predictor, samplesPerPixel, sampleFormat, width, height, compression,                    byteOrder, this);
    064        }
    065
    066        /**
    067         * Get the width of individual tiles.  Note that if the overall
    068         * image width is not a multiple of the tile width, then
    069         * the last column of tiles may extend beyond the image width.
    070         * @return an integer value greater than zero
    071         */
    072        public int getTileWidth() {
    073            return tileWidth;
    074        }
    075
    076        /**
    077         * Get the height of individual tiles.  Note that if the overall
    078         * image height is not a multiple of the tile height, then
    079         * the last row of tiles may extend beyond the image height.
    080         * @return an integer value greater than zero
    081         */
    082        public int getTileHeight() {
    083            return tileLength;
    084        }
    085
    086        // public TiffElement[] getElements()
    087        // {
    088        // return tiles;
    089        // }
    090    }
    091
    092    public static class Strips extends TiffImageData {
    093        private final TiffElement.DataElement[] strips;
    094        // public final byte strips[][];
    095        public final int rowsPerStrip;
    096
    097        public Strips(final TiffElement.DataElement[] strips, final int rowsPerStrip) {
    098            this.strips = strips;
    099            this.rowsPerStrip = rowsPerStrip;
    100        }
    101
    102        @Override
    103        public TiffElement.DataElement[] getImageData() {
    104            return strips;
    105        }
    106
    107        public TiffElement.DataElement getImageData(final int offset) {
    108            return strips[offset];
    109        }
    110
    111        public int getImageDataLength() {
    112            return strips.length;
    113        }
    114
    115        @Override
    116        public boolean stripsNotTiles() {
    117            return true;
    118        }
    119
    120        @Override
    121        public ImageDataReader getDataReader(final TiffDirectory directory,
    122                final PhotometricInterpreter photometricInterpreter,
    123                final int bitsPerPixel, final int[] bitsPerSample, final int predictor,
    124                final int samplesPerPixel, final int width, final int height, final int compression,
    125            final ByteOrder byteorder) throws IOException, ImageReadException {
    126            int sampleFormat = extractSampleFormat(directory);
    127            return new DataReaderStrips(directory, photometricInterpreter,
    128                bitsPerPixel, bitsPerSample, predictor, samplesPerPixel, sampleFormat,
    129                width, height, compression, byteorder, rowsPerStrip, this);
    130        }
    131
    132    }
    133
    134    // public abstract TiffElement[] getElements();
    135
    136    public abstract TiffElement.DataElement[] getImageData();
    137
    138    public abstract boolean stripsNotTiles();
    139
    140    public abstract ImageDataReader getDataReader(TiffDirectory directory,
    141            PhotometricInterpreter photometricInterpreter, int bitsPerPixel,
    142            int[] bitsPerSample, int predictor, int samplesPerPixel, int width,
    143            int height, int compression, ByteOrder byteOrder) throws IOException,
    144            ImageReadException;
    145
    146    public static class Data extends TiffElement.DataElement {
    147        public Data(final long offset, final int length, final byte[] data) {
    148            super(offset, length, data);
    149        }
    150
    151        @Override
    152        public String getElementDescription() {
    153            return "Tiff image data: " + getDataLength() + " bytes";
    154        }
    155
    156    }
    157
    158    public static class ByteSourceData extends Data {
    159        ByteSourceFile byteSourceFile;
    160
    161        public ByteSourceData(final long offset, final int length, final ByteSourceFile byteSource) {
    162            super(offset, length, new byte[0]);
    163            byteSourceFile = byteSource;
    164        }
    165
    166        @Override
    167        public String getElementDescription() {
    168            return "Tiff image data: " + getDataLength() + " bytes";
    169        }
    170
    171        @Override
    172        public byte[] getData() {
    173            try {
    174                return byteSourceFile.getBlock(offset, length);
    175            } catch (final IOException ioex) {
    176                return new byte[0];
    177            }
    178        }
    179    }
    180
    181    private static int extractSampleFormat(TiffDirectory directory) throws ImageReadException {
    182        short[] sSampleFmt = directory.getFieldValue(
    183            TiffTagConstants.TIFF_TAG_SAMPLE_FORMAT, false);
    184        if (sSampleFmt != null && sSampleFmt.length > 0) {
    185            return (int) sSampleFmt[0];
    186        }
    187        return 0;  // unspecified format
    188    }
    189}