sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jso...@apache.org
Subject [sis] 02/02: Image : add TranslatedRenderedImage
Date Fri, 15 Nov 2019 08:25:41 GMT
This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 84fd34f2b31e53821b45339b1dd2b7bb7f58efc3
Author: jsorel <johann.sorel@geomatys.com>
AuthorDate: Thu Nov 14 17:26:57 2019 +0100

    Image : add TranslatedRenderedImage
---
 .../sis/internal/coverage/GridCoverage2D.java      |  16 +--
 .../sis/internal/image/AbstractRenderedImage.java  | 153 +++++++++++++++++++++
 .../internal/image/TranslatedRenderedImage.java    | 138 +++++++++++++++++++
 .../image/TranslatedRenderedImageTest.java         |  64 +++++++++
 .../apache/sis/test/suite/FeatureTestSuite.java    |   3 +-
 5 files changed, 362 insertions(+), 12 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
index 5f8d76f..b2b9bf8 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/GridCoverage2D.java
@@ -18,14 +18,13 @@ package org.apache.sis.internal.coverage;
 
 import java.awt.Rectangle;
 import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
 import java.awt.image.RenderedImage;
-import java.awt.image.WritableRaster;
 import java.util.Collection;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.internal.image.TranslatedRenderedImage;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.util.ArgumentChecks;
@@ -132,17 +131,12 @@ public final class GridCoverage2D extends GridCoverage {
                 final BufferedImage bi = (BufferedImage) image;
                 return bi.getSubimage(subX, subY, subWidth, subHeight);
             } else {
-                //todo : current approach makes a copy of the datas, a better solution should
be found
-                final WritableRaster raster = image.getTile(image.getMinTileX(), image.getMinTileY()).createCompatibleWritableRaster(subWidth,
subHeight);
-                final WritableRaster derivate = raster.createWritableTranslatedChild(subX,
subY);
-                image.copyData(derivate);
-                ColorModel cm = image.getColorModel();
-                return new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
+                return new TranslatedRenderedImage(image, subX, subY);
             }
         }
     }
 
-    public double[] evaluate(DirectPosition position, double[] pixel) throws CannotEvaluateException
{
+    public double[] evaluate(DirectPosition position, double[] buffer) throws CannotEvaluateException
{
 
         try {
             position = toGridCoord(position);
@@ -167,7 +161,7 @@ public final class GridCoverage2D extends GridCoverage {
             }
 
             if (getBounds().contains(x,y)) {
-                return image.getTile(XToTileX(x), YToTileY(y)).getPixel(x, y, pixel);
+                return image.getTile(XToTileX(x), YToTileY(y)).getPixel(x, y, buffer);
             }
             throw new PointOutsideCoverageException("");
         } catch (FactoryException | TransformException ex) {
@@ -177,6 +171,7 @@ public final class GridCoverage2D extends GridCoverage {
 
     /**
      * Converts the specified point to grid coordinate.
+     *
      * @param point point to transform to grid coordinate
      * @return point in grid coordinate
      * @throws org.opengis.util.FactoryException if creating transformation fails
@@ -193,7 +188,6 @@ public final class GridCoverage2D extends GridCoverage {
         } else {
             trs = getGridGeometry().getGridToCRS(PixelInCell.CELL_CENTER);
         }
-
         return trs.transform(point, null);
     }
 
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/image/AbstractRenderedImage.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/image/AbstractRenderedImage.java
new file mode 100644
index 0000000..06786bd
--- /dev/null
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/image/AbstractRenderedImage.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.image;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.util.Vector;
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 2.0
+ * @since   2.0
+ * @module
+ */
+public abstract class AbstractRenderedImage implements RenderedImage {
+
+    @Override
+    public Vector<RenderedImage> getSources() {
+        return new Vector<>();
+    }
+
+    @Override
+    public Object getProperty(String name) {
+        return null;
+    }
+
+    @Override
+    public String[] getPropertyNames() {
+        return new String[0];
+    }
+
+    @Override
+    public Raster getData() {
+        final SampleModel sm = getSampleModel().createCompatibleSampleModel(getWidth(), getHeight());
+        final Raster rasterOut = Raster.createWritableRaster(sm, new Point(getMinX(), getMinY()));
+
+        // Clear dataBuffer to 0 value for all bank
+        for (int s = 0; s < rasterOut.getDataBuffer().getSize(); s++) {
+            for (int b = 0; b < rasterOut.getDataBuffer().getNumBanks(); b++) {
+                rasterOut.getDataBuffer().setElem(b, s, 0);
+            }
+        }
+
+        for (int y = 0; y < this.getNumYTiles(); y++) {
+            for (int x = 0; x < this.getNumYTiles(); x++) {
+                final Raster rasterIn = getTile(x, y);
+                rasterOut.getSampleModel()
+                        .setDataElements(
+                                x * this.getTileWidth(),
+                                y * this.getTileHeight(),
+                                this.getTileWidth(),
+                                this.getTileHeight(),
+                                rasterIn.getSampleModel().getDataElements(0, 0, this.getTileWidth(),
this.getTileHeight(), null, rasterIn.getDataBuffer()),
+                                rasterOut.getDataBuffer());
+            }
+        }
+
+        return rasterOut;
+    }
+
+    @Override
+    public Raster getData(Rectangle rect) {
+        final SampleModel sm = getSampleModel().createCompatibleSampleModel(rect.width, rect.height);
+        final Raster rasterOut = Raster.createWritableRaster(sm, null);
+
+        // Clear dataBuffer to 0 value for all bank
+        for (int s = 0; s < rasterOut.getDataBuffer().getSize(); s++) {
+            for (int b = 0; b < rasterOut.getDataBuffer().getNumBanks(); b++) {
+                rasterOut.getDataBuffer().setElem(b, s, 0);
+            }
+        }
+
+        final Point upperLeftPosition = this.getPositionOf(rect.x, rect.y);
+        final Point lowerRightPosition = this.getPositionOf(rect.x+rect.width-1, rect.y+rect.height-1);
+
+        for (int y = Math.max(upperLeftPosition.y,0); y < Math.min(lowerRightPosition.y
+ 1,this.getNumYTiles()); y++) {
+            for (int x = Math.max(upperLeftPosition.x,0); x < Math.min(lowerRightPosition.x
+ 1, this.getNumXTiles()); x++) {
+                final Rectangle tileRect = new Rectangle(x * this.getTileWidth(), y * this.getTileHeight(),
this.getTileWidth(), this.getTileHeight());
+
+                final int minX, maxX, minY, maxY;
+                minX = clamp(rect.x,               tileRect.x, tileRect.x + tileRect.width);
+                maxX = clamp(rect.x + rect.width,  tileRect.x, tileRect.x + tileRect.width);
+                minY = clamp(rect.y,               tileRect.y, tileRect.y + tileRect.height);
+                maxY = clamp(rect.y + rect.height, tileRect.y, tileRect.y + tileRect.height);
+
+                final Rectangle rectIn = new Rectangle(minX, minY, maxX-minX, maxY-minY);
+                rectIn.translate(-tileRect.x, -tileRect.y);
+                final Rectangle rectOut = new Rectangle(minX, minY, maxX-minX, maxY-minY);
+                rectOut.translate(-rect.x, -rect.y);
+
+                if (rectIn.width <= 0 || rectIn.height <= 0 || rectOut.width <=
0 || rectOut.height <= 0){
+                    continue;
+                }
+
+                final Raster rasterIn = getTile(x, y);
+
+                rasterOut.getSampleModel().setDataElements(rectOut.x, rectOut.y, rectOut.width,
rectOut.height,
+                        rasterIn.getSampleModel().getDataElements(rectIn.x, rectIn.y, rectIn.width,
rectIn.height, null, rasterIn.getDataBuffer()),
+                        rasterOut.getDataBuffer());
+            }
+        }
+
+        return rasterOut;
+    }
+
+
+    @Override
+    public WritableRaster copyData(WritableRaster raster) {
+        //TODO
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    /**
+     * Get the tile column and row position for a pixel.
+     * Return value can be out of the gridSize
+     */
+    protected Point getPositionOf(int x, int y){
+        final int posX = (int) (Math.floor(x / this.getTileWidth()));
+        final int posY = (int) (Math.floor(y / this.getTileHeight()));
+        return new Point(posX, posY);
+    }
+
+    /**
+     * Clamps a value between min value and max value.
+     *
+     * @param val the value to clamp
+     * @param min the minimum value
+     * @param max the maximum value
+     * @return val clamped between min and max
+     */
+    private static int clamp(int val, int min, int max) {
+        return Math.min(Math.max(val, min), max);
+    }
+}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/image/TranslatedRenderedImage.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/image/TranslatedRenderedImage.java
new file mode 100644
index 0000000..2d08aec
--- /dev/null
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/image/TranslatedRenderedImage.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.image;
+
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.util.Vector;
+
+/**
+ * Translated RenderedImage implementation.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 2.0
+ * @since   2.0
+ * @module
+ */
+public final class TranslatedRenderedImage extends AbstractRenderedImage {
+
+    private final RenderedImage image;
+    private final int offsetX;
+    private final int offsetY;
+
+    public TranslatedRenderedImage(RenderedImage image, int offsetX, int offsetY) {
+        this.image = image;
+        this.offsetX = offsetX;
+        this.offsetY = offsetY;
+    }
+
+    @Override
+    public Vector<RenderedImage> getSources() {
+        final Vector<RenderedImage> sources = new Vector<>();
+        sources.add(image);
+        return sources;
+    }
+
+    @Override
+    public Object getProperty(String name) {
+        return image.getProperty(name);
+    }
+
+    @Override
+    public String[] getPropertyNames() {
+        return image.getPropertyNames();
+    }
+
+    @Override
+    public ColorModel getColorModel() {
+        return image.getColorModel();
+    }
+
+    @Override
+    public SampleModel getSampleModel() {
+        return image.getSampleModel();
+    }
+
+    @Override
+    public int getWidth() {
+        return image.getWidth();
+    }
+
+    @Override
+    public int getHeight() {
+        return image.getHeight();
+    }
+
+    @Override
+    public int getMinX() {
+        return image.getMinX() + offsetX;
+    }
+
+    @Override
+    public int getMinY() {
+        return image.getMinY() + offsetY;
+    }
+
+    @Override
+    public int getNumXTiles() {
+        return image.getNumXTiles();
+    }
+
+    @Override
+    public int getNumYTiles() {
+        return image.getNumYTiles();
+    }
+
+    @Override
+    public int getMinTileX() {
+        return image.getMinTileX();
+    }
+
+    @Override
+    public int getMinTileY() {
+        return image.getMinTileY();
+    }
+
+    @Override
+    public int getTileWidth() {
+        return image.getTileWidth();
+    }
+
+    @Override
+    public int getTileHeight() {
+        return image.getTileHeight();
+    }
+
+    @Override
+    public int getTileGridXOffset() {
+        return image.getTileGridXOffset() + offsetX;
+    }
+
+    @Override
+    public int getTileGridYOffset() {
+        return image.getTileGridYOffset() + offsetY;
+    }
+
+    @Override
+    public Raster getTile(int tileX, int tileY) {
+        final Raster tile = image.getTile(tileX, tileY);
+        return tile.createTranslatedChild(offsetX, offsetY);
+    }
+
+}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/image/TranslatedRenderedImageTest.java
b/core/sis-feature/src/test/java/org/apache/sis/internal/image/TranslatedRenderedImageTest.java
new file mode 100644
index 0000000..6c3d251
--- /dev/null
+++ b/core/sis-feature/src/test/java/org/apache/sis/internal/image/TranslatedRenderedImageTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.image;
+
+import java.awt.Point;
+import java.awt.image.BufferedImage;
+import org.apache.sis.image.PixelIterator;
+import org.apache.sis.test.TestCase;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opengis.coverage.grid.SequenceType;
+
+/**
+ * Tests the {@link TranslatedRenderedImage} implementation.
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @version 2.0
+ * @since   2.0
+ * @module
+ */
+public class TranslatedRenderedImageTest extends TestCase {
+
+    @Test
+    public void iteratorTest() {
+        final BufferedImage image = new BufferedImage(2, 2, BufferedImage.TYPE_BYTE_GRAY);
+        image.getRaster().setSample(0, 0, 0, 1);
+        image.getRaster().setSample(1, 0, 0, 2);
+        image.getRaster().setSample(0, 1, 0, 3);
+        image.getRaster().setSample(1, 1, 0, 4);
+
+        final TranslatedRenderedImage trs = new TranslatedRenderedImage(image, -10, -20);
+
+        final PixelIterator ite = new PixelIterator.Builder().setIteratorOrder(SequenceType.LINEAR).create(trs);
+        Assert.assertTrue(ite.next());
+        Assert.assertEquals(new Point(-10, -20), ite.getPosition());
+        Assert.assertEquals(1, ite.getSample(0));
+        Assert.assertTrue(ite.next());
+        Assert.assertEquals(new Point(-9, -20), ite.getPosition());
+        Assert.assertEquals(2, ite.getSample(0));
+        Assert.assertTrue(ite.next());
+        Assert.assertEquals(new Point(-10, -19), ite.getPosition());
+        Assert.assertEquals(3, ite.getSample(0));
+        Assert.assertTrue(ite.next());
+        Assert.assertEquals(new Point(-9, -19), ite.getPosition());
+        Assert.assertEquals(4, ite.getSample(0));
+        Assert.assertFalse(ite.next());
+
+    }
+
+}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
index 9bf8ffa..b735d58 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
@@ -86,7 +86,8 @@ import org.junit.runners.Suite;
     org.apache.sis.coverage.SampleRangeFormatTest.class,
     org.apache.sis.internal.coverage.ScaledColorSpaceTest.class,
     org.apache.sis.internal.coverage.BufferedGridCoverageTest.class,
-    org.apache.sis.internal.coverage.GridCoverage2DTest.class
+    org.apache.sis.internal.coverage.GridCoverage2DTest.class,
+    org.apache.sis.internal.image.TranslatedRenderedImageTest.class
 })
 public final strictfp class FeatureTestSuite extends TestSuite {
     /**


Mime
View raw message