Created
January 23, 2013 19:45
-
-
Save akosmaroy/4612129 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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