Skip to content

Commit

Permalink
[IMAGING-311]: revised support for multivariable rasters
Browse files Browse the repository at this point in the history
  • Loading branch information
gwlucastrig authored and kinow committed Oct 22, 2021
1 parent f3bd32c commit fdc3d2d
Show file tree
Hide file tree
Showing 11 changed files with 1,089 additions and 305 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -911,18 +911,19 @@ TiffRasterData getRasterData(
}
}

if (sSampleFmt[0] == TiffTagConstants.SAMPLE_FORMAT_VALUE_IEEE_FLOATING_POINT) {

if (samplesPerPixel != 1) {
throw new ImageReadException(
"TIFF floating-point data uses unsupported samples per pixel: "
+ samplesPerPixel);
}
// Obtain the planar configuration
final TiffField pcField = directory.findField(
TiffTagConstants.TIFF_TAG_PLANAR_CONFIGURATION);
final TiffPlanarConfiguration planarConfiguration
= pcField == null
? TiffPlanarConfiguration.CHUNKY
: TiffPlanarConfiguration.lenientValueOf(pcField.getIntValue());

if (bitsPerPixel != 32 && bitsPerPixel != 64) {
if (sSampleFmt[0] == TiffTagConstants.SAMPLE_FORMAT_VALUE_IEEE_FLOATING_POINT) {
if (bitsPerSample[0] != 32 && bitsPerSample[0] != 64) {
throw new ImageReadException(
"TIFF floating-point data uses unsupported bits-per-pixel: "
+ bitsPerPixel);
"TIFF floating-point data uses unsupported bits-per-sample: "
+ bitsPerSample[0]);
}

if (predictor != -1
Expand Down Expand Up @@ -966,7 +967,7 @@ TiffRasterData getRasterData(
final ImageDataReader dataReader = imageData.getDataReader(directory,
photometricInterpreter, bitsPerPixel, bitsPerSample, predictor,
samplesPerPixel, width, height, compression,
TiffPlanarConfiguration.CHUNKY, byteOrder);
planarConfiguration, byteOrder);

return dataReader.readRasterData(subImage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,66 @@
* <p>
* <strong>Note:</strong> The getData() and getIntData() methods can return
* direct references to the internal arrays stored in instances of this class.
* Because 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. This approach is used for purposes of efficiency
* when dealing with very large TIFF images.
* Because 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. This approach is used for purposes of efficiency when
* dealing with very large TIFF images.
* <p>
* <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 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 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
* <pre>
* index = y*width + x + iSample * width *height;
* </pre>
*/
public abstract class TiffRasterData {

protected final int width;
protected final int height;
protected final int samplesPerPixel;
protected final int nCells;
protected final int planarOffset;


/**
* Construct an instance allocating memory for the specified dimensions.
*
* @param width a value of 1 or greater
* @param height a value of 1 or greater
* @param samplesPerPixel a value of 1 or greater
*/
public TiffRasterData(final int width, final int height) {
public TiffRasterData(final int width, final int height, int samplesPerPixel) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException(
"Raster dimensions less than or equal to zero are not supported");
}
if(samplesPerPixel <= 0){
throw new IllegalArgumentException(
"Raster samples-per-pixel specification must be at least 1");
}
this.width = width;
this.height = height;
this.samplesPerPixel = samplesPerPixel;
nCells = width*height*samplesPerPixel;
planarOffset = width * height;
}

protected final int checkCoordinatesAndComputeIndex(final int x, final int y) {
protected final int checkCoordinatesAndComputeIndex(final int x, final int y, int i) {
if (x < 0 || x >= width || y < 0 || y >= height) {
throw new IllegalArgumentException(
"Coordinates out of range (" + x + ", " + y + ")");
}
return y * width + x;
if (i < 0 || i >= samplesPerPixel) {
throw new IllegalArgumentException(
"Sample index out of range, value " + i
+ " where valid range is (0,"
+ (samplesPerPixel - 1) + ")");
}
return y * width + x + i * planarOffset;
}

/**
Expand All @@ -74,6 +103,15 @@ public final int getHeight() {
return height;
}

/**
* Gets the number of samples per pixel.
*
* @return a value of 1 or greater.
*/
public final int getSamplesPerPixel() {
return samplesPerPixel;
}

/**
* Gets the raster data type from the instance.
*
Expand All @@ -91,6 +129,18 @@ public final int getHeight() {
*/
public abstract void setValue(int x, int y, float value);

/**
* Sets the value stored at the specified raster coordinates.
*
* @param x integer coordinate in the columnar direction
* @param y integer coordinate in the row direction
* @param i integer sample index (for data sets giving multiple samples per
* raster cell).
* @param value the value to be stored at the specified location;
* potentially a Float&#46;NaN.
*/
public abstract void setValue(int x, int y, int i, float value);

/**
* Gets the value stored at the specified raster coordinates.
*
Expand All @@ -101,6 +151,17 @@ public final int getHeight() {
*/
public abstract float getValue(int x, int y);

/**
* Gets the value stored at the specified raster coordinates.
*
* @param x integer coordinate in the columnar direction
* @param y integer coordinate in the row direction
* @param i integer sample index
* @return the value stored at the specified location; potentially a
* Float&#46;NaN.
*/
public abstract float getValue(int x, int y, int i);

/**
* Sets the value stored at the specified raster coordinates.
*
Expand All @@ -110,6 +171,17 @@ public final int getHeight() {
*/
public abstract void setIntValue(int x, int y, int value);

/**
* Sets the value stored at the specified raster coordinates.
*
* @param x integer coordinate in the columnar direction
* @param y integer coordinate in the row direction
* @param i integer sample index (for data sets giving multiple samples per
* raster cell).
* @param value the value to be stored at the specified location.
*/
public abstract void setIntValue(int x, int y, int i, int value);

/**
* Gets the value stored at the specified raster coordinates.
*
Expand All @@ -119,6 +191,17 @@ public final int getHeight() {
*/
public abstract int getIntValue(int x, int y);

/**
* Gets the value stored at the specified raster coordinates.
*
* @param x integer coordinate in the columnar direction
* @param y integer coordinate in the row direction
* @param i integer sample index (for data sets giving multiple samples per
* raster cell).
* @return the value stored at the specified location
*/
public abstract int getIntValue(int x, int y, int i);

/**
* Tabulates simple statistics for the raster and returns an instance
* containing general metadata.
Expand Down Expand Up @@ -148,6 +231,9 @@ public final int getHeight() {
* million raster cells are common. Making a redundant copy of such a large
* in-memory object might exceed the resources available to a Java
* application.
* <p>
* See the class API documentation above for notes on accessing array
* elements.
*
* @return the data content stored in this instance.
*/
Expand All @@ -164,6 +250,9 @@ public final int getHeight() {
* million raster cells are common. Making a redundant copy of such a large
* in-memory object might exceed the resources available to a Java
* application.
* <p>
* See the class API documentation above for notes on accessing array
* elements.
*
* @return the data content stored in this instance.
*/
Expand Down

0 comments on commit fdc3d2d

Please sign in to comment.