    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.ImagingConstants;
    024import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
    025import org.apache.commons.imaging.formats.tiff.constants.TiffPlanarConfiguration;
    026import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
    027import org.apache.commons.imaging.formats.tiff.datareaders.DataReaderStrips;
    028import org.apache.commons.imaging.formats.tiff.datareaders.DataReaderTiled;
    029import org.apache.commons.imaging.formats.tiff.datareaders.ImageDataReader;
    030import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreter;
    031
    032public abstract class TiffImageData {
    033    public static class Tiles extends TiffImageData {
    034        public final TiffElement.DataElement[] tiles;
    035
    036        // public final byte tiles[][];
    037        private final int tileWidth;
    038        private final int tileLength;
    039
    040        public Tiles(final TiffElement.DataElement[] tiles, final int tileWidth, final int tileLength) {
    041            this.tiles = tiles;
    042            this.tileWidth = tileWidth;
    043            this.tileLength = tileLength;
    044        }
    045
    046        @Override
    047        public TiffElement.DataElement[] getImageData() {
    048            return tiles;
    049        }
    050
    051        @Override
    052        public boolean stripsNotTiles() {
    053            return false;
    054        }
    055
    056        @Override
    057        public ImageDataReader getDataReader(final TiffDirectory directory,
    058          final PhotometricInterpreter photometricInterpreter,
    059          final int bitsPerPixel, final int[] bitsPerSample, final int predictor,
    060          final int samplesPerPixel, final int width, final int height,
    061          final int compression,
    062          final TiffPlanarConfiguration planarConfiguration,
    063          final ByteOrder byteOrder) throws IOException, ImageReadException {
    064            final int sampleFormat = extractSampleFormat(directory);
    065            return new DataReaderTiled(directory, photometricInterpreter,
    066              tileWidth, tileLength, bitsPerPixel, bitsPerSample,
    067              predictor, samplesPerPixel, sampleFormat, width, height, compression,
    068              planarConfiguration, byteOrder, this);
    069        }
    070
    071        /**
    072         * Get the width of individual tiles.  Note that if the overall
    073         * image width is not a multiple of the tile width, then
    074         * the last column of tiles may extend beyond the image width.
    075         * @return an integer value greater than zero
    076         */
    077        public int getTileWidth() {
    078            return tileWidth;
    079        }
    080
    081        /**
    082         * Get the height of individual tiles.  Note that if the overall
    083         * image height is not a multiple of the tile height, then
    084         * the last row of tiles may extend beyond the image height.
    085         * @return an integer value greater than zero
    086         */
    087        public int getTileHeight() {
    088            return tileLength;
    089        }
    090
    091        // public TiffElement[] getElements()
    092        // {
    093        // return tiles;
    094        // }
    095    }
    096
    097    public static class Strips extends TiffImageData {
    098        private final TiffElement.DataElement[] strips;
    099        // public final byte strips[][];
    100        public final int rowsPerStrip;
    101
    102        public Strips(final TiffElement.DataElement[] strips, final int rowsPerStrip) {
    103            this.strips = strips;
    104            this.rowsPerStrip = rowsPerStrip;
    105        }
    106
    107        @Override
    108        public TiffElement.DataElement[] getImageData() {
    109            return strips;
    110        }
    111
    112        public TiffElement.DataElement getImageData(final int offset) {
    113            return strips[offset];
    114        }
    115
    116        public int getImageDataLength() {
    117            return strips.length;
    118        }
    119
    120        @Override
    121        public boolean stripsNotTiles() {
    122            return true;
    123        }
    124
    125        @Override
    126        public ImageDataReader getDataReader(final TiffDirectory directory,
    127          final PhotometricInterpreter photometricInterpreter,
    128          final int bitsPerPixel, final int[] bitsPerSample, final int predictor,
    129          final int samplesPerPixel, final int width, final int height,
    130          final int compression,
    131          final TiffPlanarConfiguration planarConfiguration,
    132          final ByteOrder byteorder) throws IOException, ImageReadException {
    133            final int sampleFormat = extractSampleFormat(directory);
    134            return new DataReaderStrips(directory, photometricInterpreter,
    135              bitsPerPixel, bitsPerSample, predictor,
    136              samplesPerPixel, sampleFormat, width, height,
    137              compression, planarConfiguration, byteorder, rowsPerStrip, this);
    138        }
    139
    140    }
    141
    142    public abstract TiffElement.DataElement[] getImageData();
    143
    144    public abstract boolean stripsNotTiles();
    145
    146    public abstract ImageDataReader getDataReader(TiffDirectory directory,
    147      PhotometricInterpreter photometricInterpreter, int bitsPerPixel,
    148      int[] bitsPerSample, int predictor, int samplesPerPixel, int width,
    149      int height, int compression,
    150      TiffPlanarConfiguration planarConfiguration,
    151      ByteOrder byteOrder) throws IOException, ImageReadException;
    152
    153    public static class Data extends TiffElement.DataElement {
    154        public Data(final long offset, final int length, final byte[] data) {
    155            super(offset, length, data);
    156        }
    157
    158        @Override
    159        public String getElementDescription() {
    160            return "Tiff image data: " + getDataLength() + " bytes";
    161        }
    162
    163    }
    164
    165    public static class ByteSourceData extends Data {
    166        final ByteSourceFile byteSourceFile;
    167
    168        public ByteSourceData(final long offset, final int length, final ByteSourceFile byteSource) {
    169            super(offset, length, ImagingConstants.EMPTY_BYTE_ARRAY);
    170            byteSourceFile = byteSource;
    171        }
    172
    173        @Override
    174        public String getElementDescription() {
    175            return "Tiff image data: " + getDataLength() + " bytes";
    176        }
    177
    178        @Override
    179        public byte[] getData() {
    180            try {
    181                return byteSourceFile.getBlock(offset, length);
    182            } catch (final IOException ioex) {
    183                return ImagingConstants.EMPTY_BYTE_ARRAY;
    184            }
    185        }
    186    }
    187
    188    private static int extractSampleFormat(final TiffDirectory directory) throws ImageReadException {
    189        final short[] sSampleFmt = directory.getFieldValue(
    190            TiffTagConstants.TIFF_TAG_SAMPLE_FORMAT, false);
    191        if (sSampleFmt != null && sSampleFmt.length > 0) {
    192            return sSampleFmt[0];
    193        }
    194        return 0;  // unspecified format
    195    }
    196}