View Javadoc
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 class TiffRasterDataInt extends TiffRasterData {
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  
75          if (data == null || data.length < nCells) {
76              throw new IllegalArgumentException("Specified data does not contain sufficient elements");
77          }
78          this.data = data;
79      }
80  
81      /**
82       * Constructs an instance allocating memory for the specified dimensions.
83       *
84       * @param width  a value of 1 or greater
85       * @param height a value of 1 or greater
86       * @param data   the data to be stored in the raster.
87       */
88      public TiffRasterDataInt(final int width, final int height, final int[] data) {
89          super(width, height, 1);
90  
91          if (data == null || data.length < nCells) {
92              throw new IllegalArgumentException("Specified data does not contain sufficient elements");
93          }
94          this.data = data;
95      }
96  
97      /**
98       * 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
99       * in the source data is cast to a float.
100      *
101      * @return the floating-point equivalents of the content stored in this instance.
102      */
103     @Override
104     public float[] getData() {
105         final float[] result = Allocator.floatArray(nCells);
106         for (int i = 0; i < nCells; i++) {
107             result[i] = data[i];
108         }
109         return result;
110     }
111 
112     /**
113      * Gets the raster data type from the instance.
114      *
115      * @return a value of TiffRasterDataType&#46;FLOAT.
116      */
117     @Override
118     public TiffRasterDataType getDataType() {
119         return TiffRasterDataType.INTEGER;
120     }
121 
122     /**
123      * 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
124      * 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
125      * performance and memory conservation. TIFF images that contain floating-point data are often quite large. Sizes of 100 million raster cells are common.
126      * Making a redundant copy of such a large in-memory object might exceed the resources available to a Java application.
127      *
128      * @return a direct reference to the data array stored in this instance.
129      */
130     @Override
131     public int[] getIntData() {
132         return data;
133     }
134 
135     /**
136      * Gets the value stored at the specified raster coordinates.
137      *
138      * @param x integer coordinate in the columnar direction
139      * @param y integer coordinate in the row direction
140      * @return the value stored at the specified location
141      */
142     @Override
143     public int getIntValue(final int x, final int y) {
144         final int index = checkCoordinatesAndComputeIndex(x, y, 0);
145         return data[index];
146     }
147 
148     /**
149      * Gets the value stored at the specified raster coordinates.
150      *
151      * @param x integer coordinate in the columnar direction
152      * @param y integer coordinate in the row direction
153      * @param i integer sample index (for data sets giving multiple samples per raster cell).
154      * @return the value stored at the specified location
155      */
156     @Override
157     public int getIntValue(final int x, final int y, final int i) {
158         final int index = checkCoordinatesAndComputeIndex(x, y, i);
159         return data[index];
160     }
161 
162     /**
163      * Tabulates simple statistics for the raster and returns an instance containing general metadata.
164      *
165      * @return a valid instance containing a safe copy of the current simple statistics for the raster.
166      */
167     @Override
168     public TiffRasterStatistics getSimpleStatistics() {
169         return new TiffRasterStatistics(this, Float.NaN);
170     }
171 
172     /**
173      * Tabulates simple statistics for the raster excluding the specified value and returns an instance containing general metadata.
174      *
175      * @param valueToExclude exclude samples with this specified value.
176      * @return a valid instance.
177      */
178     @Override
179     public TiffRasterStatistics getSimpleStatistics(final float valueToExclude) {
180         return new TiffRasterStatistics(this, valueToExclude);
181     }
182 
183     /**
184      * Gets the value stored at the specified raster coordinates.
185      *
186      * @param x integer coordinate in the columnar direction
187      * @param y integer coordinate in the row direction
188      * @return the value stored at the specified location; potentially a Float&#46;NaN.
189      */
190     @Override
191     public float getValue(final int x, final int y) {
192         final int index = checkCoordinatesAndComputeIndex(x, y, 0);
193         return data[index];
194     }
195 
196     /**
197      * Gets 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      * @return the value stored at the specified location; potentially a Float&#46;NaN.
203      */
204     @Override
205     public float getValue(final int x, final int y, final int i) {
206         final int index = checkCoordinatesAndComputeIndex(x, y, i);
207         return data[index];
208     }
209 
210     /**
211      * Sets the value stored at the specified raster coordinates.
212      *
213      * @param x     integer coordinate in the columnar direction
214      * @param y     integer coordinate in the row direction
215      * @param value the value to be stored at the specified location
216      */
217     @Override
218     public void setIntValue(final int x, final int y, final int value) {
219         final int index = checkCoordinatesAndComputeIndex(x, y, 0);
220         data[index] = value;
221     }
222 
223     /**
224      * Sets the value stored at the specified raster coordinates.
225      *
226      * @param x     integer coordinate in the columnar direction
227      * @param y     integer coordinate in the row direction
228      * @param i     integer sample index (for data sets giving multiple samples per raster cell).
229      * @param value the value to be stored at the specified location
230      */
231     @Override
232     public void setIntValue(final int x, final int y, final int i, final int value) {
233         final int index = checkCoordinatesAndComputeIndex(x, y, i);
234         data[index] = value;
235     }
236 
237     /**
238      * Sets the value stored at the specified raster coordinates.
239      *
240      * @param x     integer coordinate in the columnar direction
241      * @param y     integer coordinate in the row direction
242      * @param value the value to be stored at the specified location; potentially a Float&#46;NaN.
243      */
244     @Override
245     public void setValue(final int x, final int y, final float value) {
246         final int index = checkCoordinatesAndComputeIndex(x, y, 0);
247         data[index] = (int) value;
248     }
249 
250     /**
251      * Sets the value stored at the specified raster coordinates.
252      *
253      * @param x     integer coordinate in the columnar direction
254      * @param y     integer coordinate in the row direction
255      * @param i     integer sample index (for data sets giving multiple samples per raster cell).
256      * @param value the value to be stored at the specified location; potentially a Float&#46;NaN.
257      */
258     @Override
259     public void setValue(final int x, final int y, final int i, final float value) {
260         final int index = checkCoordinatesAndComputeIndex(x, y, i);
261         data[index] = (int) value;
262     }
263 }