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}