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 floating-point data. Some TIFF files are used
021 * to store floating-point data rather than images. This class is intended to
022 * support access to those TIFF files.
023 */
024public class TiffRasterData {
025
026
027    private final int width;
028    private final int height;
029    private final float[] data;
030
031    /**
032     * Construct an instance allocating memory for the specified dimensions.
033     *
034     * @param width a value of 1 or greater
035     * @param height a value of 1 or greater
036     */
037    public TiffRasterData(int width, int height) {
038        if (width <= 0 || height <= 0) {
039            throw new IllegalArgumentException(
040                "Raster dimensions less than or equal to zero are not supported");
041        }
042        int nCells = width * height;
043        data = new float[nCells];
044        this.width = width;
045        this.height = height;
046
047    }
048
049    /**
050     * Construct an instance allocating memory for the specified dimensions.
051     *
052     * @param width a value of 1 or greater
053     * @param height a value of 1 or greater
054     * @param data the data to be stored in the raster.
055     */
056    public TiffRasterData(int width, int height, float[] data) {
057        if (width <= 0 || height <= 0) {
058            throw new IllegalArgumentException(
059                "Raster dimensions less than or equal to zero are not supported");
060        }
061        if (data == null || data.length < width * height) {
062            throw new IllegalArgumentException(
063                "Specified data does not contain sufficient elements");
064        }
065        this.width = width;
066        this.height = height;
067        this.data = data;
068
069    }
070
071    /**
072     * Sets the value stored at the specified raster coordinates.
073     *
074     * @param x integer coordinate in the columnar direction
075     * @param y integer coordinate in the row direction
076     * @param value the value to be stored at the specified location;
077     * potentially a Float&#46;NaN.
078     */
079    public void setValue(int x, int y, float value) {
080        if (x < 0 || x >= width || y < 0 || y >= height) {
081            throw new IllegalArgumentException(
082                "Coordinates out of range (" + x + ", " + y + ")");
083        }
084        data[y * width + x] = value;
085    }
086
087    /**
088     * Gets the value stored at the specified raster coordinates.
089     *
090     * @param x integer coordinate in the columnar direction
091     * @param y integer coordinate in the row direction
092     * @return the value stored at the specified location; potentially a
093     * Float&#46;NaN.
094     */
095    public float getValue(int x, int y) {
096        if (x < 0 || x >= width || y < 0 || y >= height) {
097            throw new IllegalArgumentException(
098                "Coordinates out of range (" + x + ", " + y + ")");
099        }
100        return data[y * width + x];
101    }
102
103    /**
104     * Tabulates simple statistics for the raster and returns an instance
105     * containing general metadata.
106     *
107     * @return a valid instance containing a safe copy of the current simple
108   * statistics for the raster.     */
109    public TiffRasterStatistics getSimpleStatistics() {
110        return new TiffRasterStatistics(this, Float.NaN);
111    }
112
113    /**
114     * Tabulates simple statistics for the raster excluding the specified value
115     * and returns an instance containing general metadata.
116     *
117     * @param valueToExclude exclude samples with this specified value.
118     * @return a valid instance.
119     */
120    public TiffRasterStatistics getSimpleStatistics(float valueToExclude) {
121        return new TiffRasterStatistics(this, valueToExclude);
122    }
123
124    /**
125     * Gets the width (number of columns) of the raster.
126     *
127     * @return the width of the raster
128     */
129    public int getWidth() {
130        return width;
131    }
132
133    /**
134     * Gets the height (number of rows) of the raster.
135     *
136     * @return the height of the raster.
137     */
138    public int getHeight() {
139        return height;
140    }
141
142    /**
143     * Returns a reference to the data array stored in this instance. Note that
144     * value is <strong>not</strong> a safe copy and that modifying it would
145     * directly affect the content of the instance. While this design approach
146     * carries some risk in terms of data security, it was chosen for reasons of
147     * performance and memory conservation. TIFF images that contain
148     * floating-point data are often quite large. Sizes of 100 million raster
149     * cells are common. Making a redundant copy of such a large in-memory object
150     * might exceed the resources available to a Java application.
151     *
152     * @return a direct reference to the data array stored in this instance.
153     */
154    public float[] getData() {
155        return data;
156    }
157
158}