Skip to content

Instantly share code, notes, and snippets.

@akosmaroy
Created January 23, 2013 19:45
Show Gist options
  • Save akosmaroy/4612129 to your computer and use it in GitHub Desktop.
Save akosmaroy/4612129 to your computer and use it in GitHub Desktop.
diff --git a/utils/src/main/java/org/jaitools/tiledimage/DiskMemImageGraphics.java b/utils/src/main/java/org/jaitools/tiledimage/DiskMemImageGraphics.java
index fdb45e1..eb94cf6 100644
--- a/utils/src/main/java/org/jaitools/tiledimage/DiskMemImageGraphics.java
+++ b/utils/src/main/java/org/jaitools/tiledimage/DiskMemImageGraphics.java
@@ -99,7 +99,9 @@ public class DiskMemImageGraphics extends Graphics2D {
* java.awt.Graphics parameters
*/
private Point origin;
- private Shape clip;
+ private Shape compClip;
+ private Shape devClip;
+ private Shape usrClip;
private Color color;
private Font font;
private PaintMode paintMode;
@@ -497,13 +499,16 @@ public class DiskMemImageGraphics extends Graphics2D {
@Override
public void clip(Shape s) {
- if(clip == null) {
- clip = s;
- } else {
- Area clipArea = (clip instanceof Area ? (Area)clip : new Area(clip));
- clipArea.intersect(s instanceof Area ? (Area)s : new Area(s));
- clip = clipArea;
+ s = transformShape(s);
+ if (usrClip != null) {
+ Area a1 = (usrClip instanceof Area) ? (Area) usrClip
+ : new Area(usrClip);
+ Area a2 = (s instanceof Area) ? (Area) s : new Area(s);
+ a2.intersect(a1);
+ s = a2;
}
+ usrClip = s;
+ validateCompClip();
}
@Override
@@ -570,7 +575,7 @@ public class DiskMemImageGraphics extends Graphics2D {
@Override
public Rectangle getClipBounds() {
- return clip.getBounds();
+ return getClip().getBounds();
}
@Override
@@ -585,12 +590,13 @@ public class DiskMemImageGraphics extends Graphics2D {
@Override
public Shape getClip() {
- return clip;
+ return untransformShape(usrClip);
}
@Override
public void setClip(Shape clip) {
- this.clip = clip;
+ usrClip = clip;
+ validateCompClip();
}
@Override
@@ -738,6 +744,64 @@ public class DiskMemImageGraphics extends Graphics2D {
}
/**
+ * Transform a shape with the current transform.
+ *
+ * @param s the shape to transform
+ * @return the transformed shape.
+ */
+ private Shape transformShape(Shape s) {
+ if (s == null) {
+ return null;
+ }
+ if (transform == null) {
+ return s;
+ }
+
+ return transform.createTransformedShape(s);
+ }
+
+ /**
+ * Transform a shape with the inverse of the current transform.
+ *
+ * @param s the shape to transform
+ * @return the transformed shape.
+ */
+ private Shape untransformShape(Shape s) {
+ if (s == null) {
+ return null;
+ }
+ if (transform == null) {
+ return s;
+ }
+
+ try {
+ return transform.createInverse().createTransformedShape(s);
+ } catch (NoninvertibleTransformException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Re-calculate the composite clip, based on both the device clip and
+ * the user clip, and the current transform. Call this every time
+ * any of these three (devClip, usrClip, transform) change.
+ */
+ private void validateCompClip() {
+ if (usrClip == null) {
+ compClip = devClip;
+ return;
+ }
+
+ Area a1 = new Area(devClip);
+ Area a2 = (usrClip instanceof Area) ? (Area) usrClip
+ : new Area(usrClip);
+ a1.intersect(a2);
+
+ compClip = a1;
+ }
+
+
+ /**
* Performs the graphics operation by partitioning the work across the image's
* tiles and using Graphics2D routines to draw into each tile.
*
@@ -945,7 +1009,10 @@ public class DiskMemImageGraphics extends Graphics2D {
Graphics2D gr = getProxy();
origin = new Point(0, 0);
- clip = targetImage.getBounds();
+ devClip = targetImage.getBounds();
+ usrClip = null;
+ compClip = null;
+ validateCompClip();
color = gr.getColor();
font = gr.getFont();
@@ -983,11 +1050,11 @@ public class DiskMemImageGraphics extends Graphics2D {
gr.setColor(getColor());
if (workingOrigin == null) {
- gr.setClip(clip);
+ gr.setClip(compClip);
} else {
AffineTransform tr = AffineTransform.getTranslateInstance(
-workingOrigin.x, -workingOrigin.y);
- Shape trclip = tr.createTransformedShape(clip);
+ Shape trclip = tr.createTransformedShape(compClip);
gr.setClip(trclip);
}
diff --git a/utils/src/test/java/org/jaitools/tiledimage/ClipTest.java b/utils/src/test/java/org/jaitools/tiledimage/ClipTest.java
new file mode 100644
index 0000000..b6c39a3
--- /dev/null
+++ b/utils/src/test/java/org/jaitools/tiledimage/ClipTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013, Michael Bedward. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jaitools.tiledimage;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+
+import javax.media.jai.JAI;
+
+import org.jaitools.tiledimage.DiskMemImage;
+import org.jaitools.testutils.WaitingImageFrame;
+import org.jaitools.tilecache.DiskMemTileCache;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * A test to verify that clipping works correctly.
+ *
+ * @author Akos Maroy, akos@maroy.hu
+ */
+public class ClipTest extends TiledImageTestBase {
+
+ private final int tileWidth = 600;
+ private final int tileHeight = 600;
+ private final int xTiles = 1;
+ private final int yTiles = 1;
+
+ // Set this to true to display the test image on screen
+ private final boolean SHOW_IMAGE = true;
+
+ /**
+ * Draw some graphics into an Graphics2D object.
+ *
+ * @param image the image to draw into
+ * @throws NoninvertibleTransformException in transform errors.
+ */
+ private void draw(Graphics2D gr) throws NoninvertibleTransformException {
+ gr.setPaint(Color.WHITE);
+ gr.fill(new Rectangle(0, 0, tileWidth, tileHeight));
+
+ // AffineTransform[[0.318755336305853, 0.0, 420.03106689453125],
+ // [0.0, 0.318755336305853, 245.5029296875]]
+ AffineTransform transform = new AffineTransform(
+ 0.318755336305853, 0.0, 0.0,
+ 0.318755336305853, 420.03106689453125, 245.5029296875);
+ gr.setTransform(transform);
+
+ Shape s = new Rectangle(0, 0, 96, 83);
+
+ // create an enbedded graphics
+ Graphics2D grr = (Graphics2D) gr.create();
+ // AffineTransform[[1.0, 0.0, -343.9285583496093],
+ // [0.0, 1.0, -502.5158386230469]]
+ grr.clip(s.getBounds());
+ transform = new AffineTransform(
+ 1.0, 0.0, 0.0,
+ 1.0, -343.9285583496093, -502.5158386230469);
+ grr.transform(transform);
+
+ AffineTransform t = new AffineTransform(transform);
+ t.invert();
+ s = t.createTransformedShape(s);
+
+ assertTrue(s.getBounds().intersects(grr.getClip().getBounds2D()));
+
+ grr.setPaint(Color.BLUE);
+ grr.draw(s);
+
+ grr.dispose();
+ gr.dispose();
+ }
+
+ @Test
+ public void test() throws Exception {
+ DiskMemImage dmi = makeImage(tileWidth, xTiles, yTiles);
+ BufferedImage bi = new BufferedImage(tileWidth, tileHeight,
+ BufferedImage.TYPE_INT_ARGB);
+
+ draw(dmi.createGraphics());
+ draw(bi.createGraphics());
+
+ JAI.create("filestore", dmi, "/tmp/dmi.tif", "TIFF", null);
+ JAI.create("filestore", bi, "/tmp/bi.tif", "TIFF", null);
+
+ if (SHOW_IMAGE) {
+ CountDownLatch latch = new CountDownLatch(1);
+ WaitingImageFrame.showImage(dmi, "Test image", latch);
+ latch.await();
+ }
+
+ // Test for matching pixels between image tiles and reference tile
+ Raster refTile = bi.getData();
+ Raster tile = dmi.getTile(0, 0);
+ assertEquals(tile.getWidth(), refTile.getWidth());
+ assertEquals(tile.getHeight(), refTile.getHeight());
+ assertEquals(tile.getNumBands(), refTile.getNumBands());
+ for (int y = 0; y < tileHeight; y++) {
+ for (int x = 0; x < tileWidth; x++) {
+ for (int band = 0; band < dmi.getNumBands(); band++) {
+ assertEquals(refTile.getSample(x, y, band),
+ tile.getSample(x + tile.getMinX(), y + tile.getMinY(), band));
+ }
+ }
+ }
+
+ }
+
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment