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