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