    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 numeric-raster data. Some TIFF files are used to store floating-point or integer data rather than images. This class is
    021 * intended to support access to those TIFF files.
    022 * <p>
    023 * <strong>Note:</strong> The getData() and getIntData() methods can return direct references to the internal arrays stored in instances of this class. Because
    024 * 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.
    025 * This approach is used for purposes of efficiency when dealing with very large TIFF images.
    026 * <p>
    027 * <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
    028 * 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
    029 * 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
    030 *
    031 * <pre>
    032 * index = y * width + x + iSample * width * height;
    033 * </pre>
    034 */
    035public abstract class AbstractTiffRasterData {
    036
    037    protected final int width;
    038    protected final int height;
    039    protected final int samplesPerPixel;
    040    protected final int nCells;
    041    protected final int planarOffset;
    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     * @param samplesPerPixel a value of 1 or greater
    049     */
    050    public AbstractTiffRasterData(final int width, final int height, final int samplesPerPixel) {
    051        if (width <= 0 || height <= 0) {
    052            throw new IllegalArgumentException("Raster dimensions less than or equal to zero are not supported");
    053        }
    054        if (samplesPerPixel <= 0) {
    055            throw new IllegalArgumentException("Raster samples-per-pixel specification must be at least 1");
    056        }
    057        this.width = width;
    058        this.height = height;
    059        this.samplesPerPixel = samplesPerPixel;
    060        nCells = width * height * samplesPerPixel;
    061        planarOffset = width * height;
    062    }
    063
    064    protected final int checkCoordinatesAndComputeIndex(final int x, final int y, final int i) {
    065        if (x < 0 || x >= width || y < 0 || y >= height) {
    066            throw new IllegalArgumentException("Coordinates out of range (" + x + ", " + y + ")");
    067        }
    068        if (i < 0 || i >= samplesPerPixel) {
    069            throw new IllegalArgumentException("Sample index out of range, value " + i + " where valid range is (0," + (samplesPerPixel - 1) + ")");
    070        }
    071        return y * width + x + i * planarOffset;
    072    }
    073
    074    /**
    075     * Returns the content stored as an array in this instance. Note that in many cases, the returned array is <strong>not</strong> a safe copy of the data but
    076     * a direct reference to the member element. In such cases, modifying it would directly affect the content of the instance. While this design approach
    077     * carries some risk in terms of data security, it was chosen for reasons of performance and memory conservation. TIFF images that contain floating-point
    078     * data are often quite large. Sizes of 100 million raster cells are common. Making a redundant copy of such a large in-memory object might exceed the
    079     * resources available to a Java application.
    080     * <p>
    081     * See the class API documentation above for notes on accessing array elements.
    082     *
    083     * @return the data content stored in this instance.
    084     */
    085    public abstract float[] getData();
    086
    087    /**
    088     * Gets the raster data type from the instance.
    089     *
    090     * @return a valid enumeration value.
    091     */
    092    public abstract TiffRasterDataType getDataType();
    093
    094    /**
    095     * Gets the height (number of rows) of the raster.
    096     *
    097     * @return the height of the raster.
    098     */
    099    public final int getHeight() {
    100        return height;
    101    }
    102
    103    /**
    104     * Returns the content stored as an array in this instance. Note that in many cases, the returned array is <strong>not</strong> a safe copy of the data but
    105     * a direct reference to the member element. In such cases, modifying it would directly affect the content of the instance. While this design approach
    106     * carries some risk in terms of data security, it was chosen for reasons of performance and memory conservation. TIFF images that contain floating-point
    107     * data are often quite large. Sizes of 100 million raster cells are common. Making a redundant copy of such a large in-memory object might exceed the
    108     * resources available to a Java application.
    109     * <p>
    110     * See the class API documentation above for notes on accessing array elements.
    111     *
    112     * @return the data content stored in this instance.
    113     */
    114    public abstract int[] getIntData();
    115
    116    /**
    117     * Gets the value stored at the specified raster coordinates.
    118     *
    119     * @param x integer coordinate in the columnar direction
    120     * @param y integer coordinate in the row direction
    121     * @return the value stored at the specified location
    122     */
    123    public abstract int getIntValue(int x, int y);
    124
    125    /**
    126     * Gets the value stored at the specified raster coordinates.
    127     *
    128     * @param x integer coordinate in the columnar direction
    129     * @param y integer coordinate in the row direction
    130     * @param i integer sample index (for data sets giving multiple samples per raster cell).
    131     * @return the value stored at the specified location
    132     */
    133    public abstract int getIntValue(int x, int y, int i);
    134
    135    /**
    136     * Gets the number of samples per pixel.
    137     *
    138     * @return a value of 1 or greater.
    139     */
    140    public final int getSamplesPerPixel() {
    141        return samplesPerPixel;
    142    }
    143
    144    /**
    145     * Tabulates simple statistics for the raster and returns an instance containing general metadata.
    146     *
    147     * @return a valid instance containing a safe copy of the current simple statistics for the raster.
    148     */
    149    public abstract TiffRasterStatistics getSimpleStatistics();
    150
    151    /**
    152     * Tabulates simple statistics for the raster excluding the specified value and returns an instance containing general metadata.
    153     *
    154     * @param valueToExclude exclude samples with this specified value.
    155     * @return a valid instance.
    156     */
    157    public abstract TiffRasterStatistics getSimpleStatistics(float valueToExclude);
    158
    159    /**
    160     * Gets the value stored at the specified raster coordinates.
    161     *
    162     * @param x integer coordinate in the columnar direction
    163     * @param y integer coordinate in the row direction
    164     * @return the value stored at the specified location; potentially a Float&#46;NaN.
    165     */
    166    public abstract float getValue(int x, int y);
    167
    168    /**
    169     * Gets the value stored at the specified raster coordinates.
    170     *
    171     * @param x integer coordinate in the columnar direction
    172     * @param y integer coordinate in the row direction
    173     * @param i integer sample index
    174     * @return the value stored at the specified location; potentially a Float&#46;NaN.
    175     */
    176    public abstract float getValue(int x, int y, int i);
    177
    178    /**
    179     * Gets the width (number of columns) of the raster.
    180     *
    181     * @return the width of the raster
    182     */
    183    public final int getWidth() {
    184        return width;
    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 value the value to be stored at the specified location.
    193     */
    194    public abstract void setIntValue(int x, int y, int value);
    195
    196    /**
    197     * Sets 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     * @param value the value to be stored at the specified location.
    203     */
    204    public abstract void setIntValue(int x, int y, int i, int value);
    205
    206    /**
    207     * Sets the value stored at the specified raster coordinates.
    208     *
    209     * @param x     integer coordinate in the columnar direction
    210     * @param y     integer coordinate in the row direction
    211     * @param value the value to be stored at the specified location; potentially a Float&#46;NaN.
    212     */
    213    public abstract void setValue(int x, int y, float value);
    214
    215    /**
    216     * Sets 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 raster cell).
    221     * @param value the value to be stored at the specified location; potentially a Float&#46;NaN.
    222     */
    223    public abstract void setValue(int x, int y, int i, float value);
    224}