You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2017/07/29 17:13:10 UTC

svn commit: r1803381 - in /sis/branches/JDK8/core/sis-raster/src: main/java/org/apache/sis/image/ test/java/org/apache/sis/image/

Author: desruisseaux
Date: Sat Jul 29 17:13:10 2017
New Revision: 1803381

URL: http://svn.apache.org/viewvc?rev=1803381&view=rev
Log:
Review of TiledImage, and begining review of PixelIterator.

Added:
    sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java
      - copied, changed from r1803380, sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/IteratorTestImage.java
Removed:
    sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/IteratorTestImage.java
Modified:
    sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java
    sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java
    sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java
    sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/PixelIteratorTest.java

Modified: sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java?rev=1803381&r1=1803380&r2=1803381&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/DefaultIterator.java [UTF-8] Sat Jul 29 17:13:10 2017
@@ -141,8 +141,8 @@ class DefaultIterator extends PixelItera
         final int cRMinY       = this.currentRaster.getMinY();
         this.minX = this.x     = Math.max(areaIterate.minx, cRMinX);
         this.y                 = Math.max(areaIterate.miny, cRMinY);
-        this.currentRasterMaxX = Math.min(areaIterate.maxX, cRMinX + tileSize.width);
-        this.currentRasterMaxY = Math.min(areaIterate.maxY, cRMinY + tileSize.height);
+        this.currentRasterMaxX = Math.min(areaIterate.maxX, cRMinX + tileWidth);
+        this.currentRasterMaxY = Math.min(areaIterate.maxY, cRMinY + tileHeight);
         this.rasterNumBand     = this.currentRaster.getNumBands(); //-- ??? what is this attributs
     }
 
@@ -215,8 +215,8 @@ class DefaultIterator extends PixelItera
         if (renderedImage != null) {
             final int riMinX = renderedImage.getMinX();
             final int riMinY = renderedImage.getMinY();
-            final int tmpTX = (x - riMinX) / tileSize.width  + renderedImage.getMinTileX();
-            final int tmpTY = (y - riMinY) / tileSize.height + renderedImage.getMinTileY();
+            final int tmpTX = (x - riMinX) / tileWidth  + renderedImage.getMinTileX();
+            final int tmpTY = (y - riMinY) / tileHeight + renderedImage.getMinTileY();
             if (tmpTX != tX || tmpTY != tY) {
                 tX = tmpTX;
                 tY = tmpTY;

Modified: sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java?rev=1803381&r1=1803380&r2=1803381&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java [UTF-8] Sat Jul 29 17:13:10 2017
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.image;
 
-import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.awt.image.ComponentSampleModel;
 import java.awt.image.DataBuffer;
@@ -34,14 +33,14 @@ import java.awt.image.BandedSampleModel;
 import java.awt.image.WritableRaster;
 import java.awt.image.WritableRenderedImage;
 import java.io.Closeable;
-import org.apache.sis.util.ArgumentChecks;
 import org.opengis.coverage.grid.SequenceType;
+import org.apache.sis.util.ArgumentChecks;
+
 
 /**
- * An iterator over sample values in an image. This iterator make easier to get the values
- * without managing the complexity of various {@linkplain SampleModel sample model} and tiling.
- * Iteration may be done on a full image or only a sub-area of it.
- * Iteration order is implementation specific.
+ * An iterator over sample values in a raster or an image. This iterator simplifies accesses to sample values
+ * by hiding the {@linkplain SampleModel sample model} and tiling complexity. Iteration may be done on a full
+ * image or on only a sub-area of it. Iteration order is implementation specific.
  *
  * @author  Rémi Marechal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
@@ -50,16 +49,15 @@ import org.opengis.coverage.grid.Sequenc
  * @module
  */
 public abstract class PixelIterator implements Closeable {
-
     /**
      * Define boundary, in pixel coordinates, of area traveled by this PixeIterator.
-     * @see #getBoundary(boolean)
+     *
+     * @see #getDomain()
      */
     final RectIter areaIterate;
 
     /**
      * Define boundary, in pixel coordinates, of iterated object.
-     * @see #getBoundary(boolean)
      */
     private final Rectangle objectBoundary;
 
@@ -72,7 +70,7 @@ public abstract class PixelIterator impl
     /**
      * Size of tiles from iterated object.
      */
-    final Dimension tileSize;
+    final int tileWidth, tileHeight;
 
     /**
      * Current raster which is followed by Iterator.
@@ -83,11 +81,11 @@ public abstract class PixelIterator impl
      * RenderedImage which is followed by Iterator.
      */
     final RenderedImage renderedImage;
-//
+
     /**
      * Number of band.
      */
-    final int fixedNumBand;
+    private final int fixedNumBand;
 
     /**
      * Number of raster band.
@@ -103,7 +101,7 @@ public abstract class PixelIterator impl
     /**
      * {@link SampleModel} from the iterate object.
      */
-    final SampleModel currentSampleModel;
+    private final SampleModel currentSampleModel;
 
     //-- Iteration attributs
     /**
@@ -130,9 +128,10 @@ public abstract class PixelIterator impl
     PixelIterator(final Raster raster, final Rectangle subArea) {
         ArgumentChecks.ensureNonNull("raster", raster);
         objectBoundary     = new Rectangle(raster.getMinX(), raster.getMinY(), raster.getWidth(), raster.getHeight());
-        this.currentRaster = raster;
-        this.renderedImage = null;
-        tileSize           = new Dimension(objectBoundary.width, objectBoundary.height);
+        currentRaster      = raster;
+        renderedImage      = null;
+        tileWidth          = objectBoundary.width;
+        tileHeight         = objectBoundary.height;
         currentSampleModel = raster.getSampleModel();
         areaIterate        = new RectIter((subArea != null)
                              ? subArea.intersection(objectBoundary)
@@ -162,7 +161,8 @@ public abstract class PixelIterator impl
         ArgumentChecks.ensureNonNull("renderedImage", renderedImage);
         this.renderedImage = renderedImage;
         objectBoundary     = new Rectangle(renderedImage.getMinX(), renderedImage.getMinY(), renderedImage.getWidth(), renderedImage.getHeight());
-        tileSize           = new Dimension(renderedImage.getTileWidth(), renderedImage.getTileHeight());
+        tileWidth          = renderedImage.getTileWidth();
+        tileHeight         = renderedImage.getTileHeight();
         currentSampleModel = renderedImage.getSampleModel();
         areaIterate        = new RectIter((subArea != null)
                                          ? subArea.intersection(objectBoundary)
@@ -176,10 +176,10 @@ public abstract class PixelIterator impl
         {
             final int offTX = renderedImage.getTileGridXOffset();
             final int offTY = renderedImage.getTileGridYOffset();
-            final int tMinX = (areaIterate.minx - objectBoundary.x) / tileSize.width  + offTX;
-            final int tMinY = (areaIterate.miny - objectBoundary.y) / tileSize.height + offTY;
-            final int tMaxX = (areaIterate.maxX - objectBoundary.x + tileSize.width - 1)  / tileSize.width  + offTX;
-            final int tMaxY = (areaIterate.maxY - objectBoundary.y + tileSize.height - 1) / tileSize.height + offTY;
+            final int tMinX = (areaIterate.minx - objectBoundary.x) / tileWidth  + offTX;
+            final int tMinY = (areaIterate.miny - objectBoundary.y) / tileHeight + offTY;
+            final int tMaxX = (areaIterate.maxX - objectBoundary.x + tileWidth  - 1) / tileWidth  + offTX;
+            final int tMaxY = (areaIterate.maxY - objectBoundary.y + tileHeight - 1) / tileHeight + offTY;
             tileIndexArea = new RectIter(tMinX, tMinY, tMaxX - tMinX, tMaxY - tMinY);
         }
 
@@ -292,22 +292,12 @@ public abstract class PixelIterator impl
     }
 
     /**
-     * Returns {@code Rectangle} which is Image or Raster boundary within this Iterator.
-     *
-     * @param areaIterate true to get area iterate boundary, false to get boundary of object that iterate.
-     * @return {@code Rectangle} which is Image or Raster boundary within this Iterator.
-     */
-    public Rectangle getBoundary(final boolean areaIterate) {
-        return (Rectangle) ((areaIterate) ? this.areaIterate.toRectangle() : objectBoundary.clone());
-    }
-
-    /**
-     * Return {@link RenderedImage} that this iterator travel.
+     * Returns the pixel coordinates of the area in which this iterator is doing the iteration.
      *
-     * @return {@link RenderedImage} that this iterator travel or {@code null} if iterator was built to travel {@link Raster}.
+     * @return pixel coordinates of the iteration area.
      */
-    public RenderedImage getRenderedImage() {
-        return renderedImage;
+    public Rectangle getDomain() {
+        return areaIterate.toRectangle();
     }
 
     //-- TODO : methodes suivantes a refactorer (code duplication) + mettre ailleur + static + package private
@@ -447,16 +437,15 @@ public abstract class PixelIterator impl
      */
     private void getAreaByInterleaved(final Rectangle area, final Object buffer, final int band) {
         rewind();
-        final Rectangle generalArea = getBoundary(false);//-- compute one time
         final int sourceDataType = getSourceDatatype();
 
         final int minTX, minTY, maxTX, maxTY;
 
         if (renderedImage != null) {
-            minTX = tileIndexArea.minx + (area.x - generalArea.x) / tileSize.width;
-            minTY = tileIndexArea.miny + (area.y - generalArea.y) / tileSize.height;
-            maxTX = tileIndexArea.minx + (area.x + area.width + tileSize.width - 1) / tileSize.width;
-            maxTY = tileIndexArea.miny + (area.y + area.height + tileSize.height - 1) / tileSize.height;
+            minTX = tileIndexArea.minx + (area.x - objectBoundary.x) / tileWidth;
+            minTY = tileIndexArea.miny + (area.y - objectBoundary.y) / tileHeight;
+            maxTX = tileIndexArea.minx + (area.x + area.width + tileWidth - 1) / tileWidth;
+            maxTY = tileIndexArea.miny + (area.y + area.height + tileHeight - 1) / tileHeight;
         } else {
             minTX = minTY = 0;
             maxTX = maxTY = 1;
@@ -469,8 +458,8 @@ public abstract class PixelIterator impl
                 final Raster rast = (renderedImage != null) ? renderedImage.getTile(tx, ty) : currentRaster;
                 final int minX = Math.max(rast.getMinX(), area.x);
                 final int minY = Math.max(rast.getMinY(), area.y);
-                final int maxX = Math.min(rast.getMinX() + tileSize.width, area.x + area.width);
-                final int maxY = Math.min(rast.getMinY() + tileSize.height, area.y + area.height);
+                final int maxX = Math.min(rast.getMinX() + tileWidth, area.x + area.width);
+                final int maxY = Math.min(rast.getMinY() + tileHeight, area.y + area.height);
                 if (minX > maxX || minY > maxY) throw new IllegalArgumentException("Expected area don't intersect internal data.");
 
                 final int readLength = (maxX - minX);
@@ -529,16 +518,15 @@ public abstract class PixelIterator impl
      */
     private void getAreaByInterleaved(final Rectangle area, final Object[] buffer) {
         rewind();
-        final Rectangle generalArea = getBoundary(false);//-- compute one time
         final int sourceDataType = getSourceDatatype();
 
         final int minTX, minTY, maxTX, maxTY;
 
         if (renderedImage != null) {
-            minTX = tileIndexArea.minx + (area.x - generalArea.x) / tileSize.width;
-            minTY = tileIndexArea.miny + (area.y - generalArea.y) / tileSize.height;
-            maxTX = tileIndexArea.minx + (area.x + area.width + tileSize.width - 1) / tileSize.width;
-            maxTY = tileIndexArea.miny + (area.y + area.height + tileSize.height - 1) / tileSize.height;
+            minTX = tileIndexArea.minx + (area.x - objectBoundary.x) / tileWidth;
+            minTY = tileIndexArea.miny + (area.y - objectBoundary.y) / tileHeight;
+            maxTX = tileIndexArea.minx + (area.x + area.width + tileWidth - 1) / tileWidth;
+            maxTY = tileIndexArea.miny + (area.y + area.height + tileHeight - 1) / tileHeight;
         } else {
             minTX = minTY = 0;
             maxTX = maxTY = 1;
@@ -551,8 +539,8 @@ public abstract class PixelIterator impl
                 final Raster rast = (renderedImage != null) ? renderedImage.getTile(tx, ty) : currentRaster;
                 final int minX = Math.max(rast.getMinX(), area.x);
                 final int minY = Math.max(rast.getMinY(), area.y);
-                final int maxX = Math.min(rast.getMinX() + tileSize.width, area.x + area.width);
-                final int maxY = Math.min(rast.getMinY() + tileSize.height, area.y + area.height);
+                final int maxX = Math.min(rast.getMinX() + tileWidth, area.x + area.width);
+                final int maxY = Math.min(rast.getMinY() + tileHeight, area.y + area.height);
                 if (minX > maxX || minY > maxY) throw new IllegalArgumentException("Expected area don't intersect internal data.");
 
                 final int readLength = (maxX - minX);
@@ -616,16 +604,15 @@ public abstract class PixelIterator impl
         final int[] bandOffsets = compSM.getBandOffsets();
         assert bandOffsets.length == getNumBands();
 
-        final Rectangle generalArea = getBoundary(false);//-- compute one time
         final int sourceDataType = getSourceDatatype();
 
         final int minTX, minTY, maxTX, maxTY;
 
         if (renderedImage != null) {
-            minTX = tileIndexArea.minx + (area.x - generalArea.x) / tileSize.width;
-            minTY = tileIndexArea.miny + (area.y - generalArea.y) / tileSize.height;
-            maxTX = tileIndexArea.minx + (area.x + area.width + tileSize.width - 1) / tileSize.width;
-            maxTY = tileIndexArea.miny + (area.y + area.height + tileSize.height - 1) / tileSize.height;
+            minTX = tileIndexArea.minx + (area.x - objectBoundary.x) / tileWidth;
+            minTY = tileIndexArea.miny + (area.y - objectBoundary.y) / tileHeight;
+            maxTX = tileIndexArea.minx + (area.x + area.width + tileWidth - 1) / tileWidth;
+            maxTY = tileIndexArea.miny + (area.y + area.height + tileHeight - 1) / tileHeight;
         } else {
             minTX = minTY = 0;
             maxTX = maxTY = 1;
@@ -638,12 +625,12 @@ public abstract class PixelIterator impl
                     final Raster rast = (renderedImage != null) ? renderedImage.getTile(tx, ty) : currentRaster;
                     final int minX = Math.max(rast.getMinX(), area.x);
                     final int minY = Math.max(rast.getMinY(), area.y);
-                    final int maxX = Math.min(rast.getMinX() + tileSize.width, area.x + area.width);
-                    final int maxY = Math.min(rast.getMinY() + tileSize.height, area.y + area.height);
+                    final int maxX = Math.min(rast.getMinX() + tileWidth, area.x + area.width);
+                    final int maxY = Math.min(rast.getMinY() + tileHeight, area.y + area.height);
                     if (minX > maxX || minY > maxY) throw new IllegalArgumentException("Expected area don't intersect internal data.");
 
                     final DataBuffer databuff = rast.getDataBuffer();
-                    int srcRastId = bandOffsets[b] + ((minY - rast.getMinY()) * tileSize.width + minX - rast.getMinX());
+                    int srcRastId = bandOffsets[b] + ((minY - rast.getMinY()) * tileWidth + minX - rast.getMinX());
                     final int readLength = (maxX - minX);
                     int destId = 0;
                     for (int y = minY; y < maxY; y++) {
@@ -683,7 +670,7 @@ public abstract class PixelIterator impl
                                 throw new IllegalStateException("Unknow datatype.");
                             }
                         }
-                        srcRastId += tileSize.width;
+                        srcRastId += tileWidth;
                         destId    += area.width;
                     }
                 }
@@ -759,16 +746,15 @@ public abstract class PixelIterator impl
         final int bankIndices = compSM.getBankIndices()[band];
         final int bandOffsets = compSM.getBandOffsets()[band];
 
-        final Rectangle generalArea = getBoundary(false);//-- compute one time
         final int sourceDataType = getSourceDatatype();
 
         final int minTX, minTY, maxTX, maxTY;
 
         if (renderedImage != null) {
-            minTX = tileIndexArea.minx + (area.x - generalArea.x) / tileSize.width;
-            minTY = tileIndexArea.miny + (area.y - generalArea.y) / tileSize.height;
-            maxTX = tileIndexArea.minx + (area.x + area.width + tileSize.width - 1) / tileSize.width;
-            maxTY = tileIndexArea.miny + (area.y + area.height + tileSize.height - 1) / tileSize.height;
+            minTX = tileIndexArea.minx + (area.x - objectBoundary.x) / tileWidth;
+            minTY = tileIndexArea.miny + (area.y - objectBoundary.y) / tileHeight;
+            maxTX = tileIndexArea.minx + (area.x + area.width + tileWidth - 1) / tileWidth;
+            maxTY = tileIndexArea.miny + (area.y + area.height + tileHeight - 1) / tileHeight;
         } else {
             minTX = minTY = 0;
             maxTX = maxTY = 1;
@@ -780,12 +766,12 @@ public abstract class PixelIterator impl
                 final Raster rast = (renderedImage != null) ? renderedImage.getTile(tx, ty) : currentRaster;
                 final int minX = Math.max(rast.getMinX(), area.x);
                 final int minY = Math.max(rast.getMinY(), area.y);
-                final int maxX = Math.min(rast.getMinX() + tileSize.width, area.x + area.width);
-                final int maxY = Math.min(rast.getMinY() + tileSize.height, area.y + area.height);
+                final int maxX = Math.min(rast.getMinX() + tileWidth, area.x + area.width);
+                final int maxY = Math.min(rast.getMinY() + tileHeight, area.y + area.height);
                 if (minX > maxX || minY > maxY) throw new IllegalArgumentException("Expected area don't intersect internal data.");
 
                 final DataBuffer databuff = rast.getDataBuffer();
-                int srcRastId = bandOffsets + ((minY - rast.getMinY()) * tileSize.width + minX - rast.getMinX());
+                int srcRastId = bandOffsets + ((minY - rast.getMinY()) * tileWidth + minX - rast.getMinX());
                 final int readLength = (maxX - minX);
                 int destId = 0;
                 for (int y = minY; y < maxY; y++) {
@@ -825,7 +811,7 @@ public abstract class PixelIterator impl
                             throw new IllegalStateException("Unknow datatype.");
                         }
                     }
-                    srcRastId += tileSize.width;
+                    srcRastId += tileWidth;
                     destId    += area.width;
                 }
             }
@@ -902,7 +888,7 @@ public abstract class PixelIterator impl
      * @param pixelStride The pixel stride value given by {@link java.awt.image.ComponentSampleModel#getPixelStride()}
      * @return An array whose components are the number of elements to skip until the next sample.
      */
-     public static int[] getBandSteps(final int[] bandOffsets, final int pixelStride) {
+    static int[] getBandSteps(final int[] bandOffsets, final int pixelStride) {
         final int[] bandSteps = new int[bandOffsets.length];
         bandSteps[0] = bandOffsets[0] + pixelStride - bandOffsets[bandOffsets.length-1];
         for (int i = 1 ; i < bandSteps.length ; i++) {

Modified: sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java?rev=1803381&r1=1803380&r2=1803381&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-raster/src/main/java/org/apache/sis/image/package-info.java [UTF-8] Sat Jul 29 17:13:10 2017
@@ -17,8 +17,17 @@
 
 /**
  * Provides helper classes for handling Java2D rendered images together with some operations.
- * This package does not use any geospatial functions; it works only on "pure" images (not necessarily RGB).
- * However this package is used as a basis for georeferenced or georeferenceable <cite>grid coverages</cite>.
+ * This package does not provide any geospatial functionalities;
+ * it works only on sample or pixel values stored in {@link java.awt.image.RenderedImage}s.
+ * Note that Java2D {@code RenderedImage}s have the following capabilities:
+ *
+ * <ul>
+ *   <li>Images may have an arbitrary number of bands (not necessarily RGB).</li>
+ *   <li>Sample values can be bytes, shorts (signed or unsigned), integers or floating-point values.</li>
+ *   <li>Images can be tiled.</li>
+ * </ul>
+ *
+ * This package is used as a basis for georeferenced or georeferenceable <cite>grid coverages</cite>.
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)

Modified: sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/PixelIteratorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/PixelIteratorTest.java?rev=1803381&r1=1803380&r2=1803381&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/PixelIteratorTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/PixelIteratorTest.java [UTF-8] Sat Jul 29 17:13:10 2017
@@ -36,7 +36,8 @@ import static org.junit.Assert.*;
 
 
 /**
- * Base class of {@link PixelIterator} tests.
+ * Base class of {@link PixelIterator} tests. This base class tests the default read-only iterator
+ * on integer values. Subclasses will test variants, for example the read-write iterator.
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
@@ -143,7 +144,7 @@ public strictfp class PixelIteratorTest
         }
         expected = new float[(subMaxX - subMinX) * (subMaxY - subMinY) * numBands];
         final WritableRaster raster = Raster.createWritableRaster(new PixelInterleavedSampleModel(dataType,
-                width, height, numBands, width * numBands, new int[] {0,1,2}), new Point(xmin, ymin));
+                width, height, numBands, width * numBands, TiledImage.bandOffsets(numBands)), new Point(xmin, ymin));
         /*
          * At this point, all data structures have been created an initialized to zero sample values.
          * Now fill the data structures with arbitrary values.
@@ -196,8 +197,7 @@ public strictfp class PixelIteratorTest
             subMaxY = StrictMath.min(ymax, subArea.y + subArea.height);
         }
         expected = new float[(subMaxX - subMinX) * (subMaxY - subMinY) * numBands];
-        final IteratorTestImage image = new IteratorTestImage(xmin, ymin, width, height, tileWidth, tileHeight, xmin+tileWidth, ymin+tileHeight,
-                new PixelInterleavedSampleModel(dataType, tileWidth, tileHeight, numBands, tileWidth * numBands, new int[] {0,1,2}));
+        final TiledImage image = new TiledImage(dataType, numBands, xmin, ymin, width, height, tileWidth, tileHeight, -1, 2);
         /*
          * At this point, all data structures have been created an initialized to zero sample values.
          * Now fill the data structures with arbitrary values. We fill them tile-by-tile.

Copied: sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java (from r1803380, sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/IteratorTestImage.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java?p2=sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java&p1=sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/IteratorTestImage.java&r1=1803380&r2=1803381&rev=1803381&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/IteratorTestImage.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-raster/src/test/java/org/apache/sis/image/TiledImage.java [UTF-8] Sat Jul 29 17:13:10 2017
@@ -16,10 +16,11 @@
  */
 package org.apache.sis.image;
 
-import java.awt.Dimension;
+import java.awt.Image;
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.image.ColorModel;
+import java.awt.image.PixelInterleavedSampleModel;
 import java.awt.image.Raster;
 import java.awt.image.RenderedImage;
 import java.awt.image.SampleModel;
@@ -28,213 +29,212 @@ import java.awt.image.WritableRaster;
 import java.awt.image.WritableRenderedImage;
 import java.util.Vector;
 
+
 /**
+ * A rendered image which can contain an arbitrary number of tiles. Tiles are stored in memory.
+ * We use this class for testing purpose only because tiled images in production need a more
+ * sophisticated implementation capable to store some tiles on disk (for memory consumption reasons).
  *
- * @author Remi Marechal (Geomatys).
+ * @author  Rémi Maréchal (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
  */
-final class IteratorTestImage implements WritableRenderedImage {
-
-    private final int minx;
-    private final int miny;
-//    private final int maxX;
-//    private final int maxY;
-    private final int width;
-    private final int height;
-    private final Dimension tileSize;
-    private final SampleModel sm;
-    private final int numxtile;
-    private final int numytile;
-    private final int tgXo;
-    private final int tgYo;
-    private final int minTx;
-    private final int minTy;
-
+final class TiledImage implements WritableRenderedImage {
+    /**
+     * The minimum X or Y coordinate (inclusive) of the rendered image.
+     */
+    private final int minX, minY;
+
+    /**
+     * Number of pixels along X or Y axis in the whole rendered image.
+     */
+    private final int width, height;
+
+    /**
+     * Number of pixels along X or Y axis in a single tile of the image.
+     * All tiles must have the same size.
+     */
+    private final int tileWidth, tileHeight;
+
+    /**
+     * Number of tiles in the X or Y direction. This is computed from the image size and tile size.
+     */
+    private final int numXTiles, numYTiles;
+
+    /**
+     * The minimum tile index in the X or Y direction.
+     */
+    private final int minTileX, minTileY;
+
+    /**
+     * The tiles, created when first needed.
+     */
     private final WritableRaster[] tiles;
 
-    public IteratorTestImage(final int minx, final int miny, final int width, final int height,
-            final int tilesWidth, final int tilesHeight, final int tileGridXOffset, final int tileGridYOffset,
-            final SampleModel sampleM)
+    /**
+     * The sample model to use for creating the tiles.
+     */
+    private final SampleModel sampleModel;
+
+    /**
+     * Creates a new tiled image.
+     *
+     * @param dataType  sample data type as one of the {@link java.awt.image.DataBuffer} constants.
+     * @param numBands  number of bands in the sample model to create.
+     */
+    TiledImage(final int dataType,  final int numBands,
+               final int minX,      final int minY,
+               final int width,     final int height,
+               final int tileWidth, final int tileHeight,
+               final int minTileX,  final int minTileY)
     {
-        this.minx = minx;
-        this.miny = miny;
-        this.width = width;
-        this.height = height;
-        this.tileSize = new Dimension(tilesWidth, tilesHeight);
-        numxtile = (int) StrictMath.ceil(width / (double) tilesWidth);
-        numytile = (int) StrictMath.ceil(height / (double) tilesHeight);
-        sm = sampleM;
-        tgXo = tileGridXOffset;
-        tgYo = tileGridYOffset;
-        tiles = new WritableRaster[numxtile * numytile];
-        minTx = (int) StrictMath.floor((tgXo - minx) / (double)tileSize.width);
-        minTy = (int) StrictMath.floor((tgYo - miny) / (double)tileSize.height);
-    }
-
-
-
-    @Override
-    public ColorModel getColorModel() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public SampleModel getSampleModel() {
-        return sm;
-    }
-
-    @Override
-    public int getWidth() {
-        return width;
-    }
-
-    @Override
-    public int getHeight() {
-        return height;
-    }
-
-    @Override
-    public int getMinX() {
-        return minx;
-    }
-
-    @Override
-    public int getMinY() {
-        return miny;
-    }
-
-    @Override
-    public int getNumXTiles() {
-        return tileSize.width;
-    }
-
-    @Override
-    public int getNumYTiles() {
-        return numxtile;
-    }
-
-    @Override
-    public int getMinTileX() {
-        return minTx;
-    }
-
-    @Override
-    public int getMinTileY() {
-        return minTy;
-    }
-
-    @Override
-    public int getTileWidth() {
-        return tileSize.width;
-    }
-
-    @Override
-    public int getTileHeight() {
-        return tileSize.height;
-    }
-
-    @Override
-    public int getTileGridXOffset() {
-        return tgXo;
+        this.minX        = minX;
+        this.minY        = minY;
+        this.width       = width;
+        this.height      = height;
+        this.tileWidth   = tileWidth;
+        this.tileHeight  = tileHeight;
+        this.minTileX    = minTileX;
+        this.minTileY    = minTileY;
+        this.numXTiles   = (width  + tileWidth  - 1) / tileWidth;      // Round toward upper integer value.
+        this.numYTiles   = (height + tileHeight - 1) / tileHeight;
+        this.tiles       = new WritableRaster[numXTiles * numYTiles];
+        this.sampleModel = new PixelInterleavedSampleModel(dataType, tileWidth, tileHeight,
+                                numBands, tileWidth * numBands, bandOffsets(numBands));
+    }
+
+    /**
+     * Returns arbitrary band offsets for the given number of bands.
+     */
+    static int[] bandOffsets(final int numBands) {
+        final int[] bandOffsets = new int[numBands];
+        for (int i=1; i<numBands; i++) {
+            bandOffsets[i] = i;
+        }
+        return bandOffsets;
     }
 
-    @Override
-    public int getTileGridYOffset() {
-        return tgYo;
+    /*
+     * No source, no property, no color model since this test images is not for rendering on screen.
+     */
+    @Override public Vector<RenderedImage> getSources()             {return null;}
+    @Override public Object                getProperty(String name) {return Image.UndefinedProperty;}
+    @Override public String[]              getPropertyNames()       {return null;}
+    @Override public ColorModel            getColorModel()          {return null;}
+    @Override public SampleModel           getSampleModel()         {return sampleModel;}
+
+    /*
+     * Information specified to the constructor.
+     */
+    @Override public int getMinX()            {return minX;}
+    @Override public int getMinY()            {return minY;}
+    @Override public int getWidth()           {return width;}
+    @Override public int getHeight()          {return height;}
+    @Override public int getTileWidth()       {return tileWidth;}
+    @Override public int getTileHeight()      {return tileHeight;}
+    @Override public int getNumXTiles()       {return numXTiles;}
+    @Override public int getNumYTiles()       {return numYTiles;}
+    @Override public int getMinTileX()        {return minTileX;}
+    @Override public int getMinTileY()        {return minTileY;}
+    @Override public int getTileGridXOffset() {return minX - (minTileX * tileWidth);}
+    @Override public int getTileGridYOffset() {return minY - (minTileY * tileHeight);}
+
+    /**
+     * Sets a sample value at the given location in pixel coordinates.
+     * This is a helper method for testing purpose on small images only,
+     * since invoking this method in a loop is inefficient.
+     */
+    final void setSample(int x, int y, final int b, final double value) {
+        if ((x -= minX) < 0 || x >= width || (y -= minY) < 0 || y >= height) {
+            throw new IndexOutOfBoundsException();
+        }
+        getWritableTile(x / tileWidth  + minTileX,
+                        y / tileHeight + minTileY).setSample(x, y, b, value);
     }
 
+    /**
+     * Returns the tile at the given location in tile coordinates.
+     */
     @Override
-    public Raster getTile(int tileX, int tileY) {
+    public Raster getTile(final int tileX, final int tileY) {
         return getWritableTile(tileX, tileY);
     }
 
-    @Override
-    public Raster getData() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public Raster getData(Rectangle rect) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
+    /**
+     * Returns the tile at the given location tile coordinates.
+     */
     @Override
     public WritableRaster getWritableTile(int tileX, int tileY) {
-        final int id = (tileY - minTy) * numxtile + tileX - minTx;
-        if (id == -22) {
-            System.out.println("");
+        if ((tileX -= minTileX) < 0 || tileX >= numXTiles ||
+            (tileY -= minTileY) < 0 || tileY >= numYTiles)
+        {
+            throw new IndexOutOfBoundsException();
         }
-        if (tiles[id] == null)
-            tiles[id] = Raster.createInterleavedRaster(sm.getDataType(),
-                    tileSize.width, tileSize.height,
-                    sm.getNumBands(),
-                    new Point(tgXo + tileX * tileSize.width, tgYo + tileY * tileSize.height));
-        return tiles[id];
+        final int i = tileY * numXTiles + tileX;
+        WritableRaster raster = tiles[i];
+        if (raster == null) {
+            tiles[i] = raster = Raster.createInterleavedRaster(sampleModel.getDataType(),
+                    tileWidth, tileHeight, sampleModel.getNumBands(),
+                    new Point(tileX * tileWidth  + minX,
+                              tileY * tileHeight + minY));
+        }
+        return raster;
     }
 
+    /**
+     * Ignored since this implementation does not need to be informed
+     * about when the user is doing with the {@link WritableRaster}.
+     */
     @Override
     public void releaseWritableTile(int tileX, int tileY) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
     }
 
+    /**
+     * Returns {@code false} since we do not keep track of who called {@link #getWritableTile(int,int)}.
+     */
     @Override
     public boolean isTileWritable(int tileX, int tileY) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public Point[] getWritableTileIndices() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+        return false;
     }
 
+    /**
+     * Returns {@code false} since we do not keep track of who called {@link #getWritableTile(int,int)}.
+     */
     @Override
     public boolean hasTileWriters() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public void setData(Raster r) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public Vector<RenderedImage> getSources() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    @Override
-    public Object getProperty(String name) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+        return false;
     }
 
+    /**
+     * Returns {@code null} since we do not keep track of who called {@link #getWritableTile(int,int)}.
+     */
     @Override
-    public String[] getPropertyNames() {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+    public Point[] getWritableTileIndices() {
+        return null;
     }
 
-    @Override
-    public WritableRaster copyData(WritableRaster raster) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-
+    /**
+     * Unsupported since we do not need tile observers for the tests.
+     */
     @Override
     public void addTileObserver(TileObserver to) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+        throw new UnsupportedOperationException();
     }
 
+    /**
+     * Ignored since no listener can have been registered.
+     */
     @Override
     public void removeTileObserver(TileObserver to) {
-        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-    }
-
-    public void setSample(final int x, final int y, final int b, final double value) {
-        final WritableRaster wr = getTileFromPixCoords(x, y);
-        wr.setSample(x, y, b, value);
     }
 
-    private WritableRaster getTileFromPixCoords(final int x, final int y) {
-        final int tx = StrictMath.floorDiv((x - tgXo), tileSize.width);
-        final int ty = StrictMath.floorDiv((y - tgYo), tileSize.height);
-        return getWritableTile(tx, ty);
-    }
+    /*
+     * Not needed for the tests.
+     */
+    @Override public Raster         getData()                       {throw new UnsupportedOperationException();}
+    @Override public Raster         getData(Rectangle rect)         {throw new UnsupportedOperationException();}
+    @Override public void           setData(Raster r)               {throw new UnsupportedOperationException();}
+    @Override public WritableRaster copyData(WritableRaster raster) {throw new UnsupportedOperationException();}
 }