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 java.util.stream.IntStream; 020 021import org.apache.commons.imaging.common.Allocator; 022 023/** 024 * 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 025 * support access to those TIFF files. 026 * <p> 027 * <strong>Note:</strong> The getData() and getIntData() methods can return direct references to the internal arrays stored in instances of this class. Because 028 * 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. 029 * This approach is used for purposes of efficiency when dealing with very large TIFF images. 030 * <p> 031 * <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 032 * 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 033 * 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 034 * 035 * <pre> 036 * index = y * width + x + iSample * width * height; 037 * </pre> 038 */ 039public final class TiffRasterDataFloat extends AbstractTiffRasterData { 040 041 private final float[] data; 042 043 /** 044 * Constructs an instance allocating memory for the specified dimensions. 045 * 046 * @param width a value of 1 or greater 047 * @param height a value of 1 or greater 048 */ 049 public TiffRasterDataFloat(final int width, final int height) { 050 super(width, height, 1); 051 data = Allocator.floatArray(nCells); 052 } 053 054 /** 055 * Constructs an instance allocating memory for the specified dimensions. 056 * 057 * @param width a value of 1 or greater 058 * @param height a value of 1 or greater 059 * @param data the data to be stored in the raster. 060 */ 061 public TiffRasterDataFloat(final int width, final int height, final float[] data) { 062 super(width, height, 1); 063 if (data == null || data.length < nCells) { 064 throw new IllegalArgumentException("Specified data does not contain sufficient elements"); 065 } 066 this.data = data; 067 } 068 069 /** 070 * Constructs 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 samplesPerPixel a value of 1 or greater 075 */ 076 public TiffRasterDataFloat(final int width, final int height, final int samplesPerPixel) { 077 super(width, height, samplesPerPixel); 078 data = Allocator.floatArray(nCells); 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 samplesPerCell the number of samples per pixel 087 * @param data the data to be stored in the raster. 088 */ 089 public TiffRasterDataFloat(final int width, final int height, final int samplesPerCell, final float[] data) { 090 super(width, height, samplesPerCell); 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 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 099 * 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 100 * performance and memory conservation. TIFF images that contain floating-point data are often quite large. Sizes of 100 million raster cells are common. 101 * Making a redundant copy of such a large in-memory object might exceed the resources available to a Java application. 102 * <p> 103 * See the class API documentation above for notes on accessing array elements. 104 * 105 * @return a direct reference to the data array stored in this instance. 106 */ 107 @Override 108 public float[] getData() { 109 return data; 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.FLOAT; 120 } 121 122 /** 123 * Returns an array of integer approximations for the floating-point content stored as an array in this instance. 124 * <p> 125 * See the class API documentation above for notes on accessing array elements. 126 * 127 * @return the integer equivalents to the data content stored in this instance. 128 */ 129 @Override 130 public int[] getIntData() { 131 return IntStream.range(0, nCells).map(i -> (int) data[i]).toArray(); 132 } 133 134 /** 135 * Gets the value stored at the specified raster coordinates. 136 * 137 * @param x integer coordinate in the columnar direction 138 * @param y integer coordinate in the row direction 139 * @return the value stored at the specified location 140 */ 141 @Override 142 public int getIntValue(final int x, final int y) { 143 return (int) data[checkCoordinatesAndComputeIndex(x, y, 0)]; 144 } 145 146 /** 147 * Gets the value stored at the specified raster coordinates. 148 * 149 * @param x integer coordinate in the columnar direction 150 * @param y integer coordinate in the row direction 151 * @param i integer sample index (for data sets giving multiple samples per raster cell). 152 * @return the value stored at the specified location 153 */ 154 @Override 155 public int getIntValue(final int x, final int y, final int i) { 156 return (int) data[checkCoordinatesAndComputeIndex(x, y, 0)]; 157 } 158 159 /** 160 * Tabulates simple statistics for the raster and returns an instance containing general metadata. 161 * 162 * @return a valid instance containing a safe copy of the current simple statistics for the raster. 163 */ 164 @Override 165 public TiffRasterStatistics getSimpleStatistics() { 166 return new TiffRasterStatistics(this, Float.NaN); 167 } 168 169 /** 170 * Tabulates simple statistics for the raster excluding the specified value and returns an instance containing general metadata. 171 * 172 * @param valueToExclude exclude samples with this specified value. 173 * @return a valid instance. 174 */ 175 @Override 176 public TiffRasterStatistics getSimpleStatistics(final float valueToExclude) { 177 return new TiffRasterStatistics(this, valueToExclude); 178 } 179 180 /** 181 * Gets the value stored at the specified raster coordinates. 182 * 183 * @param x integer coordinate in the columnar direction 184 * @param y integer coordinate in the row direction 185 * @return the value stored at the specified location; potentially a Float.NaN. 186 */ 187 @Override 188 public float getValue(final int x, final int y) { 189 return data[checkCoordinatesAndComputeIndex(x, y, 0)]; 190 } 191 192 /** 193 * Gets the value stored at the specified raster coordinates. 194 * 195 * @param x integer coordinate in the columnar direction 196 * @param y integer coordinate in the row direction 197 * @param i integer sample index (for data sets giving multiple samples per raster cell). 198 * @return the value stored at the specified location; potentially a Float.NaN. 199 */ 200 @Override 201 public float getValue(final int x, final int y, final int i) { 202 return data[checkCoordinatesAndComputeIndex(x, y, i)]; 203 } 204 205 /** 206 * Sets the value stored at the specified raster coordinates. 207 * 208 * @param x integer coordinate in the columnar direction 209 * @param y integer coordinate in the row direction 210 * @param value the value to be stored at the specified location 211 */ 212 @Override 213 public void setIntValue(final int x, final int y, final int value) { 214 data[checkCoordinatesAndComputeIndex(x, y, 0)] = value; 215 } 216 217 /** 218 * Sets the value stored at the specified raster coordinates. 219 * 220 * @param x integer coordinate in the columnar direction 221 * @param y integer coordinate in the row direction 222 * @param i integer sample index (for data sets giving multiple samples per raster cell). 223 * @param value the value to be stored at the specified location 224 */ 225 @Override 226 public void setIntValue(final int x, final int y, final int i, final int value) { 227 data[checkCoordinatesAndComputeIndex(x, y, 0)] = value; 228 } 229 230 /** 231 * Sets the value stored at the specified raster coordinates. 232 * 233 * @param x integer coordinate in the columnar direction 234 * @param y integer coordinate in the row direction 235 * @param value the value to be stored at the specified location; potentially a Float.NaN. 236 */ 237 @Override 238 public void setValue(final int x, final int y, final float value) { 239 data[checkCoordinatesAndComputeIndex(x, y, 0)] = value; 240 } 241 242 /** 243 * Sets the value stored at the specified raster coordinates. 244 * 245 * @param x integer coordinate in the columnar direction 246 * @param y integer coordinate in the row direction 247 * @param i integer sample index (for data sets giving multiple samples per raster cell). 248 * @param value the value to be stored at the specified location; potentially a Float.NaN. 249 */ 250 @Override 251 public void setValue(final int x, final int y, final int i, final float value) { 252 data[checkCoordinatesAndComputeIndex(x, y, i)] = value; 253 } 254 255}