1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.imaging.formats.tiff;
18
19 /**
20 * 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
21 * intended to support access to those TIFF files.
22 * <p>
23 * <strong>Note:</strong> The getData() and getIntData() methods can return direct references to the internal arrays stored in instances of this class. Because
24 * 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.
25 * This approach is used for purposes of efficiency when dealing with very large TIFF images.
26 * <p>
27 * <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
28 * 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
29 * 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
30 *
31 * <pre>
32 * index = y * width + x + iSample * width * height;
33 * </pre>
34 */
35 public abstract class AbstractTiffRasterData {
36
37 protected final int width;
38 protected final int height;
39 protected final int samplesPerPixel;
40 protected final int nCells;
41 protected final int planarOffset;
42
43 /**
44 * Constructs an instance allocating memory for the specified dimensions.
45 *
46 * @param width a value of 1 or greater
47 * @param height a value of 1 or greater
48 * @param samplesPerPixel a value of 1 or greater
49 */
50 public AbstractTiffRasterData(final int width, final int height, final int samplesPerPixel) {
51 if (width <= 0 || height <= 0) {
52 throw new IllegalArgumentException("Raster dimensions less than or equal to zero are not supported");
53 }
54 if (samplesPerPixel <= 0) {
55 throw new IllegalArgumentException("Raster samples-per-pixel specification must be at least 1");
56 }
57 this.width = width;
58 this.height = height;
59 this.samplesPerPixel = samplesPerPixel;
60 nCells = width * height * samplesPerPixel;
61 planarOffset = width * height;
62 }
63
64 protected final int checkCoordinatesAndComputeIndex(final int x, final int y, final int i) {
65 if (x < 0 || x >= width || y < 0 || y >= height) {
66 throw new IllegalArgumentException("Coordinates out of range (" + x + ", " + y + ")");
67 }
68 if (i < 0 || i >= samplesPerPixel) {
69 throw new IllegalArgumentException("Sample index out of range, value " + i + " where valid range is (0," + (samplesPerPixel - 1) + ")");
70 }
71 return y * width + x + i * planarOffset;
72 }
73
74 /**
75 * 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
76 * a direct reference to the member element. In such cases, modifying it would directly affect the content of the instance. While this design approach
77 * carries some risk in terms of data security, it was chosen for reasons of performance and memory conservation. TIFF images that contain floating-point
78 * 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
79 * resources available to a Java application.
80 * <p>
81 * See the class API documentation above for notes on accessing array elements.
82 *
83 * @return the data content stored in this instance.
84 */
85 public abstract float[] getData();
86
87 /**
88 * Gets the raster data type from the instance.
89 *
90 * @return a valid enumeration value.
91 */
92 public abstract TiffRasterDataType getDataType();
93
94 /**
95 * Gets the height (number of rows) of the raster.
96 *
97 * @return the height of the raster.
98 */
99 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.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.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.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.NaN.
222 */
223 public abstract void setValue(int x, int y, int i, float value);
224 }