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
019/**
020 * Provides a simple container for numeric-raster data. Some TIFF files are used to store floating-point or integer data rather than images. This class is
021 * intended to support access to those TIFF files.
022 * <p>
023 * <strong>Note:</strong> The getData() and getIntData() methods can return direct references to the internal arrays stored in instances of this class. Because
024 * these are not safe copies of the data, an application that modified the arrays returned by these methods will change the content of the associated instance.
025 * This approach is used for purposes of efficiency when dealing with very large TIFF images.
026 * <p>
027 * <strong>Data layout:</strong> The elements in the returned array are stored in row-major order. In cases where the data contains multiple samples per raster
028 * cell (pixel), the data is organized into blocks of data one sample at a time. The first block contains width*height values for the first sample for each
029 * cell, the second block contains width*height values for the second sample for each cell, etc. Thus, the array index for a particular value is computed as
030 *
031 * <pre>
032 * index = y * width + x + iSample * width * height;
033 * </pre>
034 */
035public abstract class AbstractTiffRasterData {
036
037    protected final int width;
038    protected final int height;
039    protected final int samplesPerPixel;
040    protected final int nCells;
041    protected final int planarOffset;
042
043    /**
044     * Constructs an instance allocating memory for the specified dimensions.
045     *
046     * @param width           a value of 1 or greater
047     * @param height          a value of 1 or greater
048     * @param samplesPerPixel a value of 1 or greater
049     */
050    public AbstractTiffRasterData(final int width, final int height, final int samplesPerPixel) {
051        if (width <= 0 || height <= 0) {
052            throw new IllegalArgumentException("Raster dimensions less than or equal to zero are not supported");
053        }
054        if (samplesPerPixel <= 0) {
055            throw new IllegalArgumentException("Raster samples-per-pixel specification must be at least 1");
056        }
057        this.width = width;
058        this.height = height;
059        this.samplesPerPixel = samplesPerPixel;
060        nCells = width * height * samplesPerPixel;
061        planarOffset = width * height;
062    }
063
064    protected final int checkCoordinatesAndComputeIndex(final int x, final int y, final int i) {
065        if (x < 0 || x >= width || y < 0 || y >= height) {
066            throw new IllegalArgumentException("Coordinates out of range (" + x + ", " + y + ")");
067        }
068        if (i < 0 || i >= samplesPerPixel) {
069            throw new IllegalArgumentException("Sample index out of range, value " + i + " where valid range is (0," + (samplesPerPixel - 1) + ")");
070        }
071        return y * width + x + i * planarOffset;
072    }
073
074    /**
075     * Returns the content stored as an array in this instance. Note that in many cases, the returned array is <strong>not</strong> a safe copy of the data but
076     * a direct reference to the member element. In such cases, modifying it would directly affect the content of the instance. While this design approach
077     * carries some risk in terms of data security, it was chosen for reasons of performance and memory conservation. TIFF images that contain floating-point
078     * data are often quite large. Sizes of 100 million raster cells are common. Making a redundant copy of such a large in-memory object might exceed the
079     * resources available to a Java application.
080     * <p>
081     * See the class API documentation above for notes on accessing array elements.
082     *
083     * @return the data content stored in this instance.
084     */
085    public abstract float[] getData();
086
087    /**
088     * Gets the raster data type from the instance.
089     *
090     * @return a valid enumeration value.
091     */
092    public abstract TiffRasterDataType getDataType();
093
094    /**
095     * Gets the height (number of rows) of the raster.
096     *
097     * @return the height of the raster.
098     */
099    public final int getHeight() {
100        return height;
101    }
102
103    /**
104     * Returns the content stored as an array in this instance. Note that in many cases, the returned array is <strong>not</strong> a safe copy of the data but
105     * a direct reference to the member element. In such cases, modifying it would directly affect the content of the instance. While this design approach
106     * carries some risk in terms of data security, it was chosen for reasons of performance and memory conservation. TIFF images that contain floating-point
107     * data are often quite large. Sizes of 100 million raster cells are common. Making a redundant copy of such a large in-memory object might exceed the
108     * resources available to a Java application.
109     * <p>
110     * See the class API documentation above for notes on accessing array elements.
111     *
112     * @return the data content stored in this instance.
113     */
114    public abstract int[] getIntData();
115
116    /**
117     * Gets the value stored at the specified raster coordinates.
118     *
119     * @param x integer coordinate in the columnar direction
120     * @param y integer coordinate in the row direction
121     * @return the value stored at the specified location
122     */
123    public abstract int getIntValue(int x, int y);
124
125    /**
126     * Gets the value stored at the specified raster coordinates.
127     *
128     * @param x integer coordinate in the columnar direction
129     * @param y integer coordinate in the row direction
130     * @param i integer sample index (for data sets giving multiple samples per raster cell).
131     * @return the value stored at the specified location
132     */
133    public abstract int getIntValue(int x, int y, int i);
134
135    /**
136     * Gets the number of samples per pixel.
137     *
138     * @return a value of 1 or greater.
139     */
140    public final int getSamplesPerPixel() {
141        return samplesPerPixel;
142    }
143
144    /**
145     * Tabulates simple statistics for the raster and returns an instance containing general metadata.
146     *
147     * @return a valid instance containing a safe copy of the current simple statistics for the raster.
148     */
149    public abstract TiffRasterStatistics getSimpleStatistics();
150
151    /**
152     * Tabulates simple statistics for the raster excluding the specified value and returns an instance containing general metadata.
153     *
154     * @param valueToExclude exclude samples with this specified value.
155     * @return a valid instance.
156     */
157    public abstract TiffRasterStatistics getSimpleStatistics(float valueToExclude);
158
159    /**
160     * Gets the value stored at the specified raster coordinates.
161     *
162     * @param x integer coordinate in the columnar direction
163     * @param y integer coordinate in the row direction
164     * @return the value stored at the specified location; potentially a Float&#46;NaN.
165     */
166    public abstract float getValue(int x, int y);
167
168    /**
169     * Gets the value stored at the specified raster coordinates.
170     *
171     * @param x integer coordinate in the columnar direction
172     * @param y integer coordinate in the row direction
173     * @param i integer sample index
174     * @return the value stored at the specified location; potentially a Float&#46;NaN.
175     */
176    public abstract float getValue(int x, int y, int i);
177
178    /**
179     * Gets the width (number of columns) of the raster.
180     *
181     * @return the width of the raster
182     */
183    public final int getWidth() {
184        return width;
185    }
186
187    /**
188     * Sets the value stored at the specified raster coordinates.
189     *
190     * @param x     integer coordinate in the columnar direction
191     * @param y     integer coordinate in the row direction
192     * @param value the value to be stored at the specified location.
193     */
194    public abstract void setIntValue(int x, int y, int value);
195
196    /**
197     * Sets the value stored at the specified raster coordinates.
198     *
199     * @param x     integer coordinate in the columnar direction
200     * @param y     integer coordinate in the row direction
201     * @param i     integer sample index (for data sets giving multiple samples per raster cell).
202     * @param value the value to be stored at the specified location.
203     */
204    public abstract void setIntValue(int x, int y, int i, int value);
205
206    /**
207     * Sets the value stored at the specified raster coordinates.
208     *
209     * @param x     integer coordinate in the columnar direction
210     * @param y     integer coordinate in the row direction
211     * @param value the value to be stored at the specified location; potentially a Float&#46;NaN.
212     */
213    public abstract void setValue(int x, int y, float value);
214
215    /**
216     * Sets the value stored at the specified raster coordinates.
217     *
218     * @param x     integer coordinate in the columnar direction
219     * @param y     integer coordinate in the row direction
220     * @param i     integer sample index (for data sets giving multiple samples per raster cell).
221     * @param value the value to be stored at the specified location; potentially a Float&#46;NaN.
222     */
223    public abstract void setValue(int x, int y, int i, float value);
224}