You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ki...@apache.org on 2022/01/16 02:03:16 UTC

[commons-imaging] 16/24: [IMAGING-159] TIFF parameters implement single call to specify sub-image

This is an automated email from the ASF dual-hosted git repository.

kinow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-imaging.git

commit fe3199e9f1b78940119e1b66778066771b9f9095
Author: gwlucastrig <co...@gmail.com>
AuthorDate: Sun Aug 1 23:25:07 2021 -0400

    [IMAGING-159] TIFF parameters implement single call to specify sub-image
---
 .../imaging/formats/tiff/TiffImageParser.java      |  41 +++------
 .../formats/tiff/TiffImagingParameters.java        | 102 ++++++++++++++++-----
 .../formats/tiff/TiffFloatingPointReadTest.java    |   5 +-
 .../imaging/formats/tiff/TiffSubImageTest.java     |  22 +----
 4 files changed, 102 insertions(+), 68 deletions(-)

diff --git a/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java b/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java
index 45fd84f..733f628 100644
--- a/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java
+++ b/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java
@@ -354,6 +354,9 @@ public class TiffImageParser extends ImageParser<TiffImagingParameters> implemen
                         byteSource, params, formatCompliance);
 
                 final List<TiffDirectory> directories = contents.directories;
+                if (directories == null) {
+                    return false;
+                }
 
                 for (int d = 0; d < directories.size(); d++) {
                     final TiffDirectory directory = directories.get(d);
@@ -494,34 +497,20 @@ public class TiffImageParser extends ImageParser<TiffImagingParameters> implemen
     private Rectangle checkForSubImage(
             final TiffImagingParameters params)
             throws ImageReadException {
-        final Integer ix0 = params.getSubImageX();
-        final Integer iy0 = params.getSubImageY();
-        final Integer iwidth = params.getSubImageWidth();
-        final Integer iheight = params.getSubImageHeight();
-
-        if (ix0 == null && iy0 == null && iwidth == null && iheight == null) {
+        // the params class enforces a correct specification for the
+        // sub-image, but does not have knowledge of the actual
+        // dimensions of the image that is being read.  This method
+        // returns the sub-image specification, if any, and leaves
+        // further tests to the calling module.
+        if (params.isSubImageSet()) {
+            final int ix0 = params.getSubImageX();
+            final int iy0 = params.getSubImageY();
+            final int iwidth = params.getSubImageWidth();
+            final int iheight = params.getSubImageHeight();
+            return new Rectangle(ix0, iy0, iwidth, iheight);
+        } else {
             return null;
         }
-
-        final StringBuilder sb = new StringBuilder(32);
-        if (ix0 == null) {
-            sb.append(" x0,");
-        }
-        if (iy0 == null) {
-            sb.append(" y0,");
-        }
-        if (iwidth == null) {
-            sb.append(" width,");
-        }
-        if (iheight == null) {
-            sb.append(" height,");
-        }
-        if (sb.length() > 0) {
-            sb.setLength(sb.length() - 1);
-            throw new ImageReadException("Incomplete subimage parameters, missing" + sb.toString());
-        }
-
-        return new Rectangle(ix0, iy0, iwidth, iheight);
     }
 
     protected BufferedImage getBufferedImage(final TiffDirectory directory,
diff --git a/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImagingParameters.java b/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImagingParameters.java
index b0d83c0..058e41e 100644
--- a/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImagingParameters.java
+++ b/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImagingParameters.java
@@ -40,22 +40,22 @@ public class TiffImagingParameters extends XmpImagingParameters {
     /**
      * X-coordinate of a sub-image.
      */
-    private Integer subImageX = null;
+    private int subImageX;
 
     /**
      * Y-coordinate of a sub-image.
      */
-    private Integer subImageY = null;
+    private int subImageY;
 
     /**
      * Width of a sub-image.
      */
-    private Integer subImageWidth = null;
+    private int subImageWidth;
 
     /**
      * Height of a sub-image.
      */
-    private Integer subImageHeight = null;
+    private int subImageHeight;
 
     /**
      * Specifies that an application-specified photometric interpreter
@@ -114,38 +114,98 @@ public class TiffImagingParameters extends XmpImagingParameters {
         this.exif = exif;
     }
 
-    public Integer getSubImageX() {
-        return subImageX;
+    /**
+     * Sets parameters for performing a partial read operation on an image. This
+     * method is useful for reducing memory and run-time overhead when accessing
+     * large source images.
+     * <p>
+     * Note that the corner x and y coordinates must be positive integers (zero
+     * or greater). The width and height must be greater than zero.
+     *
+     * @param x pixel coordinate of the upper-left corner of the source image,
+     * must be zero or greater.
+     * @param y pixel coordinate of the upper-left corner of the source image,
+     * must be zero or greater.
+     * @param width width of the image subset to be read, must be greater than
+     * zero.
+     * @param height height of the image subset to be read, must be greater than
+     * zero.
+     */
+    public void setSubImage(int x, int y, int width, int height) {
+        if (x < 0 || y < 0) {
+            throw new IllegalArgumentException(
+                    "Invalid sub-image specification: negative x and y values not allowed");
+        }
+        if (width <= 0 || height <= 0) {
+            throw new IllegalArgumentException(
+                    "Invalid sub-image specification width and height must be greater than zero");
+        }
+        subImageX = x;
+        subImageY = y;
+        subImageWidth = width;
+        subImageHeight = height;
     }
 
-    public void setSubImageX(Integer subImageX) {
-        this.subImageX = subImageX;
+    /**
+     * Clears settings for sub-image. Subsequent read operations will retrieve
+     * the entire image.
+     */
+    public void clearSubImage() {
+        subImageWidth = 0;
+        subImageHeight = 0;
     }
 
-    public Integer getSubImageY() {
-        return subImageY;
+    /**
+     * Indicates whether the application has set sub-image parameters.
+     *
+     * @return true if the sub-image parameters are set; otherwise, false.
+     */
+    public boolean isSubImageSet() {
+        return subImageWidth > 0 && subImageHeight > 0;
     }
 
-    public void setSubImageY(Integer subImageY) {
-        this.subImageY = subImageY;
+    /**
+     * Gets the X coordinate of a sub-image. This setting is meaningful only if
+     * a sub-image is set.
+     *
+     * @return a positive integer
+     */
+    public int getSubImageX() {
+        return subImageX;
     }
 
-    public Integer getSubImageWidth() {
-        return subImageWidth;
+    /**
+     * Gets the Y coordinate of a sub-image. This setting is meaningful only if
+     * a sub-image is set.
+     *
+     * @return a positive integer
+     */
+    public int getSubImageY() {
+        return subImageY;
     }
 
-    public void setSubImageWidth(Integer subImageWidth) {
-        this.subImageWidth = subImageWidth;
+    /**
+     * Gets the width for a sub-image setting. For a sub-image setting to be
+     * meaningful, both the width and height must be set.
+     *
+     * @return if the sub-image feature is enabled, a value greater than zero;
+     * otherwise, zero.
+     */
+    public int getSubImageWidth() {
+        return subImageWidth;
     }
 
-    public Integer getSubImageHeight() {
+    /**
+     * Gets the height for a sub-image setting. For a sub-image setting to be
+     * meaningful, both the width and height must be set.
+     *
+     * @return if the sub-image feature is enabled, a value greater than zero;
+     * otherwise, zero.
+     */
+    public int getSubImageHeight() {
         return subImageHeight;
     }
 
-    public void setSubImageHeight(Integer subImageHeight) {
-        this.subImageHeight = subImageHeight;
-    }
-
     public PhotometricInterpreter getCustomPhotometricInterpreter() {
         return customPhotometricInterpreter;
     }
diff --git a/src/test/java/org/apache/commons/imaging/formats/tiff/TiffFloatingPointReadTest.java b/src/test/java/org/apache/commons/imaging/formats/tiff/TiffFloatingPointReadTest.java
index 2fbf933..644ff66 100644
--- a/src/test/java/org/apache/commons/imaging/formats/tiff/TiffFloatingPointReadTest.java
+++ b/src/test/java/org/apache/commons/imaging/formats/tiff/TiffFloatingPointReadTest.java
@@ -223,10 +223,7 @@ public class TiffFloatingPointReadTest {
     private void checkSubImage(final File target, final TiffRasterData fullRaster, final int x0, final int y0, final int width, final int height){
         try{
             final TiffImagingParameters params = new TiffImagingParameters();
-            params.setSubImageX(x0);
-            params.setSubImageY(y0);
-            params.setSubImageWidth(width);
-            params.setSubImageHeight(height);
+            params.setSubImage(x0, y0, width, height);
             final TiffRasterData partRaster = readRasterFromTIFF(target, params);
             assertEquals(width, partRaster.getWidth(), "Invalid width in partial for " + target.getName());
             assertEquals(height, partRaster.getHeight(), "Invalid height in partial for " + target.getName());
diff --git a/src/test/java/org/apache/commons/imaging/formats/tiff/TiffSubImageTest.java b/src/test/java/org/apache/commons/imaging/formats/tiff/TiffSubImageTest.java
index 9316f35..1f52ab0 100644
--- a/src/test/java/org/apache/commons/imaging/formats/tiff/TiffSubImageTest.java
+++ b/src/test/java/org/apache/commons/imaging/formats/tiff/TiffSubImageTest.java
@@ -42,10 +42,7 @@ public class TiffSubImageTest extends TiffBaseTest {
         final BufferedImage src = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
         final TiffImagingParameters params = new TiffImagingParameters();
         final byte[] imageBytes = Imaging.writeImageToBytes(src, ImageFormats.TIFF, params);
-        params.setSubImageX(0);
-        params.setSubImageY(0);
-        params.setSubImageWidth(2);
-        params.setSubImageHeight(3);
+        params.setSubImage(0, 0, 2, 3);
         final BufferedImage image = Imaging.getBufferedImage(imageBytes, params);
         assertEquals(image.getWidth(), 2);
         assertEquals(image.getHeight(), 3);
@@ -59,10 +56,7 @@ public class TiffSubImageTest extends TiffBaseTest {
         final int height = referenceImage.getHeight();
 
         final TiffImagingParameters params = new TiffImagingParameters();
-        params.setSubImageX(0);
-        params.setSubImageY(0);
-        params.setSubImageWidth(width);
-        params.setSubImageHeight(height);
+        params.setSubImage(0, 0, width, height);
 
         final BufferedImage image = Imaging.getBufferedImage(target, params);
         assertEquals(image.getWidth(), width, "Improper width when sub-imaging entire image");
@@ -79,13 +73,10 @@ public class TiffSubImageTest extends TiffBaseTest {
     private void processBadParams(final File target, final int x, final int y, final int width, final int height, final String comment) throws IOException{
         try{
             final TiffImagingParameters params = new TiffImagingParameters();
-            params.setSubImageX(x);
-            params.setSubImageY(y);
-            params.setSubImageWidth(width);
-            params.setSubImageHeight(height);
+            params.setSubImage(x, y, width, height);
             final BufferedImage image = Imaging.getBufferedImage(target, params);
             fail("Reading TIFF sub-image failed to detect bad parameter: "+comment);
-        }catch(final ImageReadException ire){
+        }catch(final ImageReadException | IllegalArgumentException ire){
             // the test passed
         }
     }
@@ -102,10 +93,7 @@ public class TiffSubImageTest extends TiffBaseTest {
             final int []rArgb = new int[rW*rH];
             referenceImage.getRGB(0, 0, rW, rH, rArgb, 0, rW);
             final TiffImagingParameters params = new TiffImagingParameters();
-            params.setSubImageX(1);
-            params.setSubImageY(1);
-            params.setSubImageWidth(rW - 2);
-            params.setSubImageHeight(rH - 2);
+            params.setSubImage(1, 1, rW-2, rH-2);
             final BufferedImage image = Imaging.getBufferedImage(target, params);
             final int iW = image.getWidth();
             final int iH = image.getHeight();