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 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&#46;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&#46;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&#46;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&#46;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&#46;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 }