001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.imaging.formats.tiff; 018 019/** 020 * Provides a simple container for floating-point data. Some TIFF files are used 021 * to store floating-point data rather than images. This class is intended to 022 * support access to those TIFF files. 023 * <p> 024 * <strong>Note:</strong> The getData() and getIntData() methods can return 025 * direct references to the internal arrays stored in instances of this class. 026 * Because these are not safe copies of the data, an application that modified 027 * the arrays returned by these methods will change the content of the 028 * associated instance. This approach is used for purposes of efficiency when 029 * dealing with very large TIFF images. 030 * <p> 031 * <strong>Data layout:</strong> The elements in the returned array are stored 032 * in row-major order. In cases where the data contains multiple samples per 033 * raster cell (pixel), the data is organized into blocks of data one sample at 034 * a time. The first block contains width*height values for the first sample for 035 * each cell, the second block contains width*height values for the second 036 * sample for each cell, etc. Thus, the array index for a particular value is 037 * computed as 038 * <pre> 039 * index = y * width + x + iSample * width * height; 040 * </pre> 041 */ 042public class TiffRasterDataInt extends TiffRasterData { 043 044 private final int[] data; 045 046 /** 047 * Construct an instance allocating memory for the specified dimensions. 048 * 049 * @param width a value of 1 or greater 050 * @param height a value of 1 or greater 051 */ 052 public TiffRasterDataInt(final int width, final int height) { 053 super(width, height, 1); 054 data = new int[nCells]; 055 } 056 057 /** 058 * Construct an instance allocating memory for the specified dimensions. 059 * 060 * @param width a value of 1 or greater 061 * @param height a value of 1 or greater 062 * @param samplesPerPixel a value of 1 or greater 063 */ 064 public TiffRasterDataInt(final int width, final int height, int samplesPerPixel) { 065 super(width, height, samplesPerPixel); 066 data = new int[nCells]; 067 } 068 069 /** 070 * Construct an instance allocating memory for the specified dimensions. 071 * 072 * @param width a value of 1 or greater 073 * @param height a value of 1 or greater 074 * @param data the data to be stored in the raster. 075 */ 076 public TiffRasterDataInt(final int width, final int height, final int[] data) { 077 super(width, height, 1); 078 079 if (data == null || data.length < nCells) { 080 throw new IllegalArgumentException( 081 "Specified data does not contain sufficient elements"); 082 } 083 this.data = data; 084 } 085 086 /** 087 * Construct an instance allocating memory for the specified dimensions. 088 * 089 * @param width a value of 1 or greater 090 * @param height a value of 1 or greater 091 * @param samplesPerPixel a value of 1 or greater 092 * @param data the data to be stored in the raster. 093 */ 094 public TiffRasterDataInt(final int width, final int height, int samplesPerPixel, final int[] data) { 095 super(width, height, samplesPerPixel); 096 097 if (data == null || data.length < nCells) { 098 throw new IllegalArgumentException( 099 "Specified data does not contain sufficient elements"); 100 } 101 this.data = data; 102 } 103 104 /** 105 * Gets the raster data type from the instance. 106 * 107 * @return a value of TiffRasterDataType.FLOAT. 108 */ 109 @Override 110 public TiffRasterDataType getDataType() { 111 return TiffRasterDataType.INTEGER; 112 } 113 114 /** 115 * Sets the value stored at the specified raster coordinates. 116 * 117 * @param x integer coordinate in the columnar direction 118 * @param y integer coordinate in the row direction 119 * @param value the value to be stored at the specified location; 120 * potentially a Float.NaN. 121 */ 122 @Override 123 public void setValue(final int x, final int y, final float value) { 124 int index = checkCoordinatesAndComputeIndex(x, y, 0); 125 data[index] = (int) value; 126 } 127 128 /** 129 * Sets the value stored at the specified raster coordinates. 130 * 131 * @param x integer coordinate in the columnar direction 132 * @param y integer coordinate in the row direction 133 * @param i integer sample index (for data sets giving multiple samples per 134 * raster cell). 135 * @param value the value to be stored at the specified location; 136 * potentially a Float.NaN. 137 */ 138 @Override 139 public void setValue(final int x, final int y, int i, final float value) { 140 int index = checkCoordinatesAndComputeIndex(x, y, i); 141 data[index] = (int) value; 142 } 143 144 /** 145 * Gets the value stored at the specified raster coordinates. 146 * 147 * @param x integer coordinate in the columnar direction 148 * @param y integer coordinate in the row direction 149 * @return the value stored at the specified location; potentially a 150 * Float.NaN. 151 */ 152 @Override 153 public float getValue(final int x, final int y) { 154 int index = checkCoordinatesAndComputeIndex(x, y, 0); 155 return data[index]; 156 } 157 158 /** 159 * Gets the value stored at the specified raster coordinates. 160 * 161 * @param x integer coordinate in the columnar direction 162 * @param y integer coordinate in the row direction 163 * @param i integer sample index (for data sets giving multiple samples per 164 * raster cell. 165 * @return the value stored at the specified location; potentially a 166 * Float.NaN. 167 */ 168 @Override 169 public float getValue(final int x, final int y, int i) { 170 int index = checkCoordinatesAndComputeIndex(x, y, i); 171 return data[index]; 172 } 173 174 /** 175 * Sets the value stored at the specified raster coordinates. 176 * 177 * @param x integer coordinate in the columnar direction 178 * @param y integer coordinate in the row direction 179 * @param value the value to be stored at the specified location 180 */ 181 @Override 182 public void setIntValue(final int x, final int y, final int value) { 183 int index = checkCoordinatesAndComputeIndex(x, y, 0); 184 data[index] = value; 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 i integer sample index (for data sets giving multiple samples per 193 * raster cell). 194 * @param value the value to be stored at the specified location 195 */ 196 @Override 197 public void setIntValue(final int x, final int y, int i, final int value) { 198 int index = checkCoordinatesAndComputeIndex(x, y, i); 199 data[index] = value; 200 } 201 202 /** 203 * Gets the value stored at the specified raster coordinates. 204 * 205 * @param x integer coordinate in the columnar direction 206 * @param y integer coordinate in the row direction 207 * @return the value stored at the specified location 208 */ 209 @Override 210 public int getIntValue(final int x, final int y) { 211 int index = checkCoordinatesAndComputeIndex(x, y, 0); 212 return data[index]; 213 } 214 215 /** 216 * Gets 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 221 * raster cell). 222 * @return the value stored at the specified location 223 */ 224 @Override 225 public int getIntValue(final int x, final int y, int i) { 226 int index = checkCoordinatesAndComputeIndex(x, y, i); 227 return data[index]; 228 } 229 230 /** 231 * Tabulates simple statistics for the raster and returns an instance 232 * containing general metadata. 233 * 234 * @return a valid instance containing a safe copy of the current simple 235 * statistics for the raster. 236 */ 237 @Override 238 public TiffRasterStatistics getSimpleStatistics() { 239 return new TiffRasterStatistics(this, Float.NaN); 240 } 241 242 /** 243 * Tabulates simple statistics for the raster excluding the specified value 244 * and returns an instance containing general metadata. 245 * 246 * @param valueToExclude exclude samples with this specified value. 247 * @return a valid instance. 248 */ 249 @Override 250 public TiffRasterStatistics getSimpleStatistics(final float valueToExclude) { 251 return new TiffRasterStatistics(this, valueToExclude); 252 } 253 254 /** 255 * Returns a reference to the data array stored in this instance. Note that 256 * the array returned is <strong>not</strong> a safe copy and that modifying 257 * it directly affects the content of the instance. While this design 258 * approach carries some risk in terms of data security, it was chosen for 259 * reasons of performance and memory conservation. TIFF images that contain 260 * floating-point data are often quite large. Sizes of 100 million raster 261 * cells are common. Making a redundant copy of such a large in-memory 262 * object might exceed the resources available to a Java application. 263 * 264 * @return a direct reference to the data array stored in this instance. 265 */ 266 @Override 267 public int[] getIntData() { 268 return data; 269 } 270 271 /** 272 * Returns an array of floating-point equivalents to the integer values 273 * stored in this instance. To do so, a float array is allocated and each 274 * integer value in the source data is cast to a float. 275 * 276 * @return the floating-point equivalents of the content stored in this 277 * instance. 278 */ 279 @Override 280 public float[] getData() { 281 final float[] result = new float[nCells]; 282 for (int i = 0; i < nCells; i++) { 283 result[i] = (int) data[i]; 284 } 285 return result; 286 } 287}