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 final class TiffRasterDataInt extends AbstractTiffRasterData { 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 if (data == null || data.length < nCells) { 075 throw new IllegalArgumentException("Specified data does not contain sufficient elements"); 076 } 077 this.data = data; 078 } 079 080 /** 081 * Constructs an instance allocating memory for the specified dimensions. 082 * 083 * @param width a value of 1 or greater 084 * @param height a value of 1 or greater 085 * @param data the data to be stored in the raster. 086 */ 087 public TiffRasterDataInt(final int width, final int height, final int[] data) { 088 super(width, height, 1); 089 if (data == null || data.length < nCells) { 090 throw new IllegalArgumentException("Specified data does not contain sufficient elements"); 091 } 092 this.data = data; 093 } 094 095 /** 096 * 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 097 * in the source data is cast to a float. 098 * 099 * @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.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.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.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.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.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}