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 019import org.apache.commons.imaging.common.Allocator; 020 021/** 022 * 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 023 * support access to those TIFF files. 024 * <p> 025 * <strong>Note:</strong> The getData() and getIntData() methods can return direct references to the internal arrays stored in instances of this class. Because 026 * 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. 027 * This approach is used for purposes of efficiency when dealing with very large TIFF images. 028 * <p> 029 * <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 030 * 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 031 * 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 032 * 033 * <pre> 034 * index = y * width + x + iSample * width * height; 035 * </pre> 036 */ 037public class TiffRasterDataInt extends TiffRasterData { 038 039 private final int[] data; 040 041 /** 042 * Constructs an instance allocating memory for the specified dimensions. 043 * 044 * @param width a value of 1 or greater 045 * @param height a value of 1 or greater 046 */ 047 public TiffRasterDataInt(final int width, final int height) { 048 super(width, height, 1); 049 data = Allocator.intArray(nCells); 050 } 051 052 /** 053 * Constructs an instance allocating memory for the specified dimensions. 054 * 055 * @param width a value of 1 or greater 056 * @param height a value of 1 or greater 057 * @param samplesPerPixel a value of 1 or greater 058 */ 059 public TiffRasterDataInt(final int width, final int height, final int samplesPerPixel) { 060 super(width, height, samplesPerPixel); 061 data = Allocator.intArray(nCells); 062 } 063 064 /** 065 * Constructs an instance allocating memory for the specified dimensions. 066 * 067 * @param width a value of 1 or greater 068 * @param height a value of 1 or greater 069 * @param samplesPerPixel a value of 1 or greater 070 * @param data the data to be stored in the raster. 071 */ 072 public TiffRasterDataInt(final int width, final int height, final int samplesPerPixel, final int[] data) { 073 super(width, height, samplesPerPixel); 074 075 if (data == null || data.length < nCells) { 076 throw new IllegalArgumentException("Specified data does not contain sufficient elements"); 077 } 078 this.data = data; 079 } 080 081 /** 082 * Constructs an instance allocating memory for the specified dimensions. 083 * 084 * @param width a value of 1 or greater 085 * @param height a value of 1 or greater 086 * @param data the data to be stored in the raster. 087 */ 088 public TiffRasterDataInt(final int width, final int height, final int[] data) { 089 super(width, height, 1); 090 091 if (data == null || data.length < nCells) { 092 throw new IllegalArgumentException("Specified data does not contain sufficient elements"); 093 } 094 this.data = data; 095 } 096 097 /** 098 * 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 099 * 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}