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  /**
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 TiffRasterData {
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 TiffRasterData(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&#46;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&#46;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&#46;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&#46;NaN.
222      */
223     public abstract void setValue(int x, int y, int i, float value);
224 }