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.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.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.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.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.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 }