    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
    021 * to store floating-point or integer data rather than images. This class is
    022 * intended to 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 abstract class TiffRasterData {
    043
    044    protected final int width;
    045    protected final int height;
    046    protected final int samplesPerPixel;
    047    protected final int nCells;
    048    protected final int planarOffset;
    049
    050
    051    /**
    052     * Construct an instance allocating memory for the specified dimensions.
    053     *
    054     * @param width a value of 1 or greater
    055     * @param height a value of 1 or greater
    056     * @param samplesPerPixel a value of 1 or greater
    057     */
    058    public TiffRasterData(final int width, final int height, int samplesPerPixel) {
    059        if (width <= 0 || height <= 0) {
    060            throw new IllegalArgumentException(
    061                    "Raster dimensions less than or equal to zero are not supported");
    062        }
    063        if(samplesPerPixel <= 0){
    064            throw new IllegalArgumentException(
    065                    "Raster samples-per-pixel specification must be at least 1");
    066        }
    067        this.width = width;
    068        this.height = height;
    069        this.samplesPerPixel = samplesPerPixel;
    070        nCells = width*height*samplesPerPixel;
    071        planarOffset = width * height;
    072    }
    073
    074    protected final int checkCoordinatesAndComputeIndex(final int x, final int y, int i) {
    075        if (x < 0 || x >= width || y < 0 || y >= height) {
    076            throw new IllegalArgumentException(
    077                    "Coordinates out of range (" + x + ", " + y + ")");
    078        }
    079        if (i < 0 || i >= samplesPerPixel) {
    080            throw new IllegalArgumentException(
    081                    "Sample index out of range, value " + i
    082                    + " where valid range is (0,"
    083                    + (samplesPerPixel - 1) + ")");
    084        }
    085        return y * width + x + i * planarOffset;
    086    }
    087
    088    /**
    089     * Gets the width (number of columns) of the raster.
    090     *
    091     * @return the width of the raster
    092     */
    093    public final int getWidth() {
    094        return width;
    095    }
    096
    097    /**
    098     * Gets the height (number of rows) of the raster.
    099     *
    100     * @return the height of the raster.
    101     */
    102    public final int getHeight() {
    103        return height;
    104    }
    105
    106    /**
    107     * Gets the number of samples per pixel.
    108     *
    109     * @return a value of 1 or greater.
    110     */
    111    public final int getSamplesPerPixel() {
    112        return samplesPerPixel;
    113    }
    114
    115    /**
    116     * Gets the raster data type from the instance.
    117     *
    118     * @return a valid enumeration value.
    119     */
    120    public abstract TiffRasterDataType getDataType();
    121
    122    /**
    123     * Sets the value stored at the specified raster coordinates.
    124     *
    125     * @param x integer coordinate in the columnar direction
    126     * @param y integer coordinate in the row direction
    127     * @param value the value to be stored at the specified location;
    128     * potentially a Float&#46;NaN.
    129     */
    130    public abstract void setValue(int x, int y, float value);
    131
    132    /**
    133     * Sets the value stored at the specified raster coordinates.
    134     *
    135     * @param x integer coordinate in the columnar direction
    136     * @param y integer coordinate in the row direction
    137     * @param i integer sample index (for data sets giving multiple samples per
    138     * raster cell).
    139     * @param value the value to be stored at the specified location;
    140     * potentially a Float&#46;NaN.
    141     */
    142    public abstract void setValue(int x, int y, int i, float value);
    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&#46;NaN.
    151     */
    152    public abstract float getValue(int x, int y);
    153
    154    /**
    155     * Gets the value stored at the specified raster coordinates.
    156     *
    157     * @param x integer coordinate in the columnar direction
    158     * @param y integer coordinate in the row direction
    159     * @param i integer sample index
    160     * @return the value stored at the specified location; potentially a
    161     * Float&#46;NaN.
    162     */
    163    public abstract float getValue(int x, int y, int i);
    164
    165    /**
    166     * Sets the value stored at the specified raster coordinates.
    167     *
    168     * @param x integer coordinate in the columnar direction
    169     * @param y integer coordinate in the row direction
    170     * @param value the value to be stored at the specified location.
    171     */
    172    public abstract void setIntValue(int x, int y, int value);
    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 i integer sample index (for data sets giving multiple samples per
    180     * raster cell).
    181     * @param value the value to be stored at the specified location.
    182     */
    183    public abstract void setIntValue(int x, int y, int i, int value);
    184
    185    /**
    186     * Gets the value stored at the specified raster coordinates.
    187     *
    188     * @param x integer coordinate in the columnar direction
    189     * @param y integer coordinate in the row direction
    190     * @return the value stored at the specified location
    191     */
    192    public abstract int getIntValue(int x, int y);
    193
    194    /**
    195     * Gets the value stored at the specified raster coordinates.
    196     *
    197     * @param x integer coordinate in the columnar direction
    198     * @param y integer coordinate in the row direction
    199     * @param i integer sample index (for data sets giving multiple samples per
    200     * raster cell).
    201     * @return the value stored at the specified location
    202     */
    203    public abstract int getIntValue(int x, int y, int i);
    204
    205    /**
    206     * Tabulates simple statistics for the raster and returns an instance
    207     * containing general metadata.
    208     *
    209     * @return a valid instance containing a safe copy of the current simple
    210     * statistics for the raster.
    211     */
    212    public abstract TiffRasterStatistics getSimpleStatistics();
    213
    214    /**
    215     * Tabulates simple statistics for the raster excluding the specified value
    216     * and returns an instance containing general metadata.
    217     *
    218     * @param valueToExclude exclude samples with this specified value.
    219     * @return a valid instance.
    220     */
    221    public abstract TiffRasterStatistics getSimpleStatistics(float valueToExclude);
    222
    223    /**
    224     * Returns the content stored as an array in this instance. Note that in
    225     * many cases, the returned array is <strong>not</strong> a safe copy of the
    226     * data but a direct reference to the member element. In such cases,
    227     * modifying it would directly affect the content of the instance. While
    228     * this design approach carries some risk in terms of data security, it was
    229     * chosen for reasons of performance and memory conservation. TIFF images
    230     * that contain floating-point data are often quite large. Sizes of 100
    231     * million raster cells are common. Making a redundant copy of such a large
    232     * in-memory object might exceed the resources available to a Java
    233     * application.
    234     * <p>
    235     * See the class API documentation above for notes on accessing array
    236     * elements.
    237     *
    238     * @return the data content stored in this instance.
    239     */
    240    public abstract float[] getData();
    241
    242    /**
    243     * Returns the content stored as an array in this instance. Note that in
    244     * many cases, the returned array is <strong>not</strong> a safe copy of the
    245     * data but a direct reference to the member element. In such cases,
    246     * modifying it would directly affect the content of the instance. While
    247     * this design approach carries some risk in terms of data security, it was
    248     * chosen for reasons of performance and memory conservation. TIFF images
    249     * that contain floating-point data are often quite large. Sizes of 100
    250     * million raster cells are common. Making a redundant copy of such a large
    251     * in-memory object might exceed the resources available to a Java
    252     * application.
    253     * <p>
    254     * See the class API documentation above for notes on accessing array
    255     * elements.
    256     *
    257     * @return the data content stored in this instance.
    258     */
    259    public abstract int[] getIntData();
    260}