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 import org.apache.commons.imaging.common.Allocator;
20
21 /**
22 * Provides a simple container for floating-point data. Some TIFF files are used to store floating-point data rather than images. This class is intended to
23 * support access to those TIFF files.
24 * <p>
25 * <strong>Note:</strong> The getData() and getIntData() methods can return direct references to the internal arrays stored in instances of this class. Because
26 * 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.
27 * This approach is used for purposes of efficiency when dealing with very large TIFF images.
28 * <p>
29 * <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
30 * 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
31 * 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
32 *
33 * <pre>
34 * index = y * width + x + iSample * width * height;
35 * </pre>
36 */
37 public final class TiffRasterDataInt extends AbstractTiffRasterData {
38
39 private final int[] data;
40
41 /**
42 * Constructs an instance allocating memory for the specified dimensions.
43 *
44 * @param width a value of 1 or greater
45 * @param height a value of 1 or greater
46 */
47 public TiffRasterDataInt(final int width, final int height) {
48 super(width, height, 1);
49 data = Allocator.intArray(nCells);
50 }
51
52 /**
53 * Constructs an instance allocating memory for the specified dimensions.
54 *
55 * @param width a value of 1 or greater
56 * @param height a value of 1 or greater
57 * @param samplesPerPixel a value of 1 or greater
58 */
59 public TiffRasterDataInt(final int width, final int height, final int samplesPerPixel) {
60 super(width, height, samplesPerPixel);
61 data = Allocator.intArray(nCells);
62 }
63
64 /**
65 * Constructs an instance allocating memory for the specified dimensions.
66 *
67 * @param width a value of 1 or greater
68 * @param height a value of 1 or greater
69 * @param samplesPerPixel a value of 1 or greater
70 * @param data the data to be stored in the raster.
71 */
72 public TiffRasterDataInt(final int width, final int height, final int samplesPerPixel, final int[] data) {
73 super(width, height, samplesPerPixel);
74 if (data == null || data.length < nCells) {
75 throw new IllegalArgumentException("Specified data does not contain sufficient elements");
76 }
77 this.data = data;
78 }
79
80 /**
81 * Constructs an instance allocating memory for the specified dimensions.
82 *
83 * @param width a value of 1 or greater
84 * @param height a value of 1 or greater
85 * @param data the data to be stored in the raster.
86 */
87 public TiffRasterDataInt(final int width, final int height, final int[] data) {
88 super(width, height, 1);
89 if (data == null || data.length < nCells) {
90 throw new IllegalArgumentException("Specified data does not contain sufficient elements");
91 }
92 this.data = data;
93 }
94
95 /**
96 * Returns an array of floating-point equivalents to the integer values stored in this instance. To do so, a float array is allocated and each integer value
97 * in the source data is cast to a float.
98 *
99 * @return the floating-point equivalents of the content stored in this instance.
100 */
101 @Override
102 public float[] getData() {
103 final float[] result = Allocator.floatArray(nCells);
104 for (int i = 0; i < nCells; i++) {
105 result[i] = data[i];
106 }
107 return result;
108 }
109
110 /**
111 * Gets the raster data type from the instance.
112 *
113 * @return a value of TiffRasterDataType.FLOAT.
114 */
115 @Override
116 public TiffRasterDataType getDataType() {
117 return TiffRasterDataType.INTEGER;
118 }
119
120 /**
121 * Returns a reference to the data array stored in this instance. Note that the array returned is <strong>not</strong> a safe copy and that modifying it
122 * directly affects the content of the instance. While this design approach carries some risk in terms of data security, it was chosen for reasons of
123 * performance and memory conservation. TIFF images that contain floating-point data are often quite large. Sizes of 100 million raster cells are common.
124 * Making a redundant copy of such a large in-memory object might exceed the resources available to a Java application.
125 *
126 * @return a direct reference to the data array stored in this instance.
127 */
128 @Override
129 public int[] getIntData() {
130 return data;
131 }
132
133 /**
134 * Gets the value stored at the specified raster coordinates.
135 *
136 * @param x integer coordinate in the columnar direction
137 * @param y integer coordinate in the row direction
138 * @return the value stored at the specified location
139 */
140 @Override
141 public int getIntValue(final int x, final int y) {
142 return data[checkCoordinatesAndComputeIndex(x, y, 0)];
143 }
144
145 /**
146 * Gets the value stored at the specified raster coordinates.
147 *
148 * @param x integer coordinate in the columnar direction
149 * @param y integer coordinate in the row direction
150 * @param i integer sample index (for data sets giving multiple samples per raster cell).
151 * @return the value stored at the specified location
152 */
153 @Override
154 public int getIntValue(final int x, final int y, final int i) {
155 return data[checkCoordinatesAndComputeIndex(x, y, i)];
156 }
157
158 /**
159 * Tabulates simple statistics for the raster and returns an instance containing general metadata.
160 *
161 * @return a valid instance containing a safe copy of the current simple statistics for the raster.
162 */
163 @Override
164 public TiffRasterStatistics getSimpleStatistics() {
165 return new TiffRasterStatistics(this, Float.NaN);
166 }
167
168 /**
169 * Tabulates simple statistics for the raster excluding the specified value and returns an instance containing general metadata.
170 *
171 * @param valueToExclude exclude samples with this specified value.
172 * @return a valid instance.
173 */
174 @Override
175 public TiffRasterStatistics getSimpleStatistics(final float valueToExclude) {
176 return new TiffRasterStatistics(this, valueToExclude);
177 }
178
179 /**
180 * Gets the value stored at the specified raster coordinates.
181 *
182 * @param x integer coordinate in the columnar direction
183 * @param y integer coordinate in the row direction
184 * @return the value stored at the specified location; potentially a Float.NaN.
185 */
186 @Override
187 public float getValue(final int x, final int y) {
188 return data[checkCoordinatesAndComputeIndex(x, y, 0)];
189 }
190
191 /**
192 * Gets the value stored at the specified raster coordinates.
193 *
194 * @param x integer coordinate in the columnar direction
195 * @param y integer coordinate in the row direction
196 * @param i integer sample index (for data sets giving multiple samples per raster cell.
197 * @return the value stored at the specified location; potentially a Float.NaN.
198 */
199 @Override
200 public float getValue(final int x, final int y, final int i) {
201 return data[checkCoordinatesAndComputeIndex(x, y, i)];
202 }
203
204 /**
205 * Sets the value stored at the specified raster coordinates.
206 *
207 * @param x integer coordinate in the columnar direction
208 * @param y integer coordinate in the row direction
209 * @param value the value to be stored at the specified location
210 */
211 @Override
212 public void setIntValue(final int x, final int y, final int value) {
213 data[checkCoordinatesAndComputeIndex(x, y, 0)] = value;
214 }
215
216 /**
217 * Sets the value stored at the specified raster coordinates.
218 *
219 * @param x integer coordinate in the columnar direction
220 * @param y integer coordinate in the row direction
221 * @param i integer sample index (for data sets giving multiple samples per raster cell).
222 * @param value the value to be stored at the specified location
223 */
224 @Override
225 public void setIntValue(final int x, final int y, final int i, final int value) {
226 data[checkCoordinatesAndComputeIndex(x, y, i)] = value;
227 }
228
229 /**
230 * Sets the value stored at the specified raster coordinates.
231 *
232 * @param x integer coordinate in the columnar direction
233 * @param y integer coordinate in the row direction
234 * @param value the value to be stored at the specified location; potentially a Float.NaN.
235 */
236 @Override
237 public void setValue(final int x, final int y, final float value) {
238 data[checkCoordinatesAndComputeIndex(x, y, 0)] = (int) value;
239 }
240
241 /**
242 * Sets the value stored at the specified raster coordinates.
243 *
244 * @param x integer coordinate in the columnar direction
245 * @param y integer coordinate in the row direction
246 * @param i integer sample index (for data sets giving multiple samples per raster cell).
247 * @param value the value to be stored at the specified location; potentially a Float.NaN.
248 */
249 @Override
250 public void setValue(final int x, final int y, final int i, final float value) {
251 data[checkCoordinatesAndComputeIndex(x, y, i)] = (int) value;
252 }
253 }