You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2016/06/24 19:11:20 UTC

svn commit: r1750158 - /commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/

Author: britter
Date: Fri Jun 24 19:11:18 2016
New Revision: 1750158

URL: http://svn.apache.org/viewvc?rev=1750158&view=rev
Log:
Split up roundtrip test into separat test cases using the Theories runner to build up test input combinations. This also closes #22 from GitHub.

Added:
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/BitmapRoundtripTest.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FormatInfo.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FullColorRoundtrip.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/GrayscaleRountripTest.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/LimitedColorRoundtripTest.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/NullParametersRoundtripTest.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/PixelDensityRoundtrip.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/RoundtripBase.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/TestImages.java
Removed:
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/RoundtripTest.java

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/BitmapRoundtripTest.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/BitmapRoundtripTest.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/BitmapRoundtripTest.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/BitmapRoundtripTest.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,50 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+@RunWith(Theories.class)
+public class BitmapRoundtripTest extends RoundtripBase {
+
+    @DataPoints
+    public static BufferedImage[] images = new BufferedImage[] {
+            TestImages.createArgbBitmapImage(1, 1), // minimal
+            TestImages.createArgbBitmapImage(2, 2), //
+            TestImages.createArgbBitmapImage(10, 10), // larger than 8
+            TestImages.createArgbBitmapImage(300, 300), // larger than 256
+
+            TestImages.createBitmapBitmapImage(1, 1), // minimal
+            TestImages.createBitmapBitmapImage(2, 2), //
+            TestImages.createBitmapBitmapImage(10, 10), // larger than 8
+            TestImages.createBitmapBitmapImage(300, 300), // larger than 256
+    };
+
+    @DataPoints
+    public static FormatInfo[] formatInfos = FormatInfo.READ_WRITE_FORMATS;
+
+    @Theory
+    public void testBitmapRoundtrip(BufferedImage testImage, FormatInfo formatInfo) throws Exception {
+        roundtrip(formatInfo, testImage, "bitmap", true);
+    }
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FormatInfo.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FormatInfo.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FormatInfo.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FormatInfo.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,133 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import org.apache.commons.imaging.ImageFormat;
+import org.apache.commons.imaging.ImageFormats;
+
+class FormatInfo {
+
+    static final int COLOR_FULL_RGB = 0;
+    static final int COLOR_LIMITED_INDEX = 1;
+    static final int COLOR_GRAYSCALE = 2;
+    static final int COLOR_BITMAP = 3;
+
+    static final FormatInfo[] PRESERVING_RESOLUTION_FORMATS = new FormatInfo[] {
+            new FormatInfo(ImageFormats.PNG, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.ICO, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.TIFF, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.BMP, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.PCX, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.DCX, true, true,
+                    COLOR_FULL_RGB, true, true), //
+    };
+
+    static FormatInfo[] READ_WRITE_FORMATS = new FormatInfo[] {
+            new FormatInfo(ImageFormats.PNG, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.GIF, true, true,
+                    COLOR_LIMITED_INDEX, true, false), //
+            new FormatInfo(ImageFormats.ICO, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.TIFF, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.BMP, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.PBM, true, true,
+                    COLOR_BITMAP, true, false), //
+            new FormatInfo(ImageFormats.PGM, true, true,
+                    COLOR_GRAYSCALE, true, false), //
+            new FormatInfo(ImageFormats.PPM, true, true,
+                    COLOR_FULL_RGB, true, false), //
+            new FormatInfo(ImageFormats.PAM, true, true,
+                    COLOR_FULL_RGB, true, false),//
+            new FormatInfo(ImageFormats.WBMP, true, true,
+                    COLOR_BITMAP, true, false), //
+            new FormatInfo(ImageFormats.PCX, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.DCX, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.XBM, true, true,
+                    COLOR_BITMAP, false, false), //
+            new FormatInfo(ImageFormats.XPM, true, true,
+                    COLOR_FULL_RGB, false, false), //
+    };
+
+    static final FormatInfo[] ALL_FORMATS = { //
+            new FormatInfo(ImageFormats.PNG, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.GIF, true, true,
+                    COLOR_LIMITED_INDEX, true, false), //
+            new FormatInfo(ImageFormats.ICO, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.TIFF, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.JPEG, true, false,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.BMP, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.PSD, true, false,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.PBM, true, true,
+                    COLOR_BITMAP, true, false), //
+            new FormatInfo(ImageFormats.PGM, true, true,
+                    COLOR_GRAYSCALE, true, false), //
+            new FormatInfo(ImageFormats.PPM, true, true,
+                    COLOR_FULL_RGB, true, false), //
+            new FormatInfo(ImageFormats.PAM, true, true,
+                    COLOR_FULL_RGB, true, false),//
+            new FormatInfo(ImageFormats.PNM, true, true,
+                    COLOR_FULL_RGB, true, false), //
+            new FormatInfo(ImageFormats.TGA, false, false,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.WBMP, true, true,
+                    COLOR_BITMAP, true, false), //
+            new FormatInfo(ImageFormats.PCX, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.DCX, true, true,
+                    COLOR_FULL_RGB, true, true), //
+            new FormatInfo(ImageFormats.XBM, true, true,
+                    COLOR_BITMAP, false, false), //
+            new FormatInfo(ImageFormats.XPM, true, true,
+                    COLOR_FULL_RGB, false, false), //
+    };
+
+    final ImageFormat format;
+    final boolean canRead;
+    final boolean canWrite;
+    final int colorSupport;
+    final boolean identicalSecondWrite;
+    final boolean preservesResolution;
+
+    FormatInfo(final ImageFormat format, final boolean canRead,
+                      final boolean canWrite, final int colorSupport,
+                      final boolean identicalSecondWrite,
+                      final boolean preservesResolution) {
+        this.canRead = canRead;
+        this.canWrite = canWrite;
+        this.colorSupport = colorSupport;
+        this.format = format;
+        this.identicalSecondWrite = identicalSecondWrite;
+        this.preservesResolution = preservesResolution;
+    }
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FullColorRoundtrip.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FullColorRoundtrip.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FullColorRoundtrip.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/FullColorRoundtrip.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,56 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+@RunWith(Theories.class)
+public class FullColorRoundtrip extends RoundtripBase {
+
+    @DataPoints
+    public static BufferedImage[] images = new BufferedImage[]{
+            TestImages.createFullColorImage(1, 1), // minimal
+            TestImages.createFullColorImage(2, 2), //
+            TestImages.createFullColorImage(10, 10), // larger than 8
+            TestImages.createFullColorImage(300, 300), // larger than 256
+    };
+
+    @DataPoints
+    public static FormatInfo[] formatInfos = FormatInfo.READ_WRITE_FORMATS;
+
+    @Theory
+    public void testFullColorRoundtrip(final BufferedImage testImage, final FormatInfo formatInfo) throws Exception {
+        boolean imageExact = true;
+        if (formatInfo.colorSupport == FormatInfo.COLOR_BITMAP) {
+            imageExact = false;
+        }
+        if (formatInfo.colorSupport == FormatInfo.COLOR_GRAYSCALE) {
+            imageExact = false;
+        }
+        if (formatInfo.colorSupport == FormatInfo.COLOR_LIMITED_INDEX) {
+            imageExact = false;
+        }
+
+        roundtrip(formatInfo, testImage, "fullColor", imageExact);
+    }
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/GrayscaleRountripTest.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/GrayscaleRountripTest.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/GrayscaleRountripTest.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/GrayscaleRountripTest.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,52 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+@RunWith(Theories.class)
+public class GrayscaleRountripTest extends RoundtripBase {
+
+    @DataPoints
+    public static BufferedImage[] images = new BufferedImage[]{
+            TestImages.createArgbBitmapImage(1, 1), // minimal
+            TestImages.createArgbGrayscaleImage(2, 2), //
+            TestImages.createArgbGrayscaleImage(10, 10), // larger than 8
+            TestImages.createArgbGrayscaleImage(300, 300), // larger than 256
+
+            TestImages.createGrayscaleGrayscaleImage(1, 1), // minimal
+            TestImages.createGrayscaleGrayscaleImage(2, 2), //
+            TestImages.createGrayscaleGrayscaleImage(10, 10), // larger than 8
+            TestImages.createGrayscaleGrayscaleImage(300, 300), // larger than 256
+    };
+
+    @DataPoints
+    public static FormatInfo[] formatInfos = FormatInfo.READ_WRITE_FORMATS;
+
+    @Theory
+    public void testGrayscaleRoundtrip(final BufferedImage testImage, final FormatInfo formatInfo) throws Exception {
+            boolean imageExact = formatInfo.colorSupport != FormatInfo.COLOR_BITMAP;
+
+            roundtrip(formatInfo, testImage, "gray", imageExact);
+    }
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,104 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.imaging.util.Debug;
+import org.apache.commons.io.FileUtils;
+import org.junit.Assert;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+final class ImageAsserts {
+
+    private ImageAsserts() {
+    }
+    
+    static void assertEquals(final BufferedImage a, final BufferedImage b) {
+        assertEquals(a, b, 0);
+    }
+
+    static void assertEquals(final BufferedImage a, final BufferedImage b, final int tolerance) {
+        Assert.assertEquals(a.getWidth(), b.getWidth());
+        Assert.assertEquals(a.getHeight(), b.getHeight());
+
+        for (int x = 0; x < a.getWidth(); x++) {
+            for (int y = 0; y < a.getHeight(); y++) {
+                final int a_argb = a.getRGB(x, y);
+                final int b_argb = b.getRGB(x, y);
+                if (a_argb != b_argb) {
+                    if (calculateARGBDistance(a_argb, b_argb) <= tolerance) {
+                        continue; // ignore.
+                    }
+                }
+                if (a_argb != b_argb) {
+                    Debug.debug("width: " + a.getWidth());
+                    Debug.debug("height: " + a.getHeight());
+                    Debug.debug("distance: " + calculateARGBDistance(a_argb, b_argb));
+                    Debug.debug("x: " + x);
+                    Debug.debug("y: " + y);
+                    Debug.debug("a_argb: " + a_argb + " (0x" + Integer.toHexString(a_argb) + ")");
+                    Debug.debug("b_argb: " + b_argb + " (0x" + Integer.toHexString(b_argb) + ")");
+                }
+                Assert.assertEquals(a_argb, b_argb);
+            }
+        }
+    }
+
+    static int calculateARGBDistance(final int a, final int b) {
+        final int aAlpha = 0xff & (a >> 24);
+        final int aRed = 0xff & (a >> 16);
+        final int aGreen = 0xff & (a >> 8);
+        final int aBlue = 0xff & (a >> 0);
+        final int bAlpha = 0xff & (b >> 24);
+        final int bRed = 0xff & (b >> 16);
+        final int bGreen = 0xff & (b >> 8);
+        final int bBlue = 0xff & (b >> 0);
+        final int diff = Math.abs(aAlpha - bAlpha) + Math.abs(aRed - bRed)
+                + Math.abs(aGreen - bGreen) + Math.abs(aBlue - bBlue);
+        return diff;
+
+    }
+
+    static void assertEquals(final File a, final File b) throws IOException {
+        assertTrue(a.exists() && a.isFile());
+        assertTrue(b.exists() && b.isFile());
+        Assert.assertEquals(a.length(), b.length());
+
+        final byte aData[] = FileUtils.readFileToByteArray(a);
+        final byte bData[] = FileUtils.readFileToByteArray(b);
+
+        for (int i = 0; i < a.length(); i++) {
+            final int aByte = 0xff & aData[i];
+            final int bByte = 0xff & bData[i];
+
+            if (aByte != bByte) {
+                Debug.debug("a: " + a);
+                Debug.debug("b: " + b);
+                Debug.debug("i: " + i);
+                Debug.debug("aByte: " + aByte + " (0x" + Integer.toHexString(aByte) + ")");
+                Debug.debug("bByte: " + bByte + " (0x" + Integer.toHexString(bByte) + ")");
+            }
+            Assert.assertEquals(aByte, bByte);
+        }
+    }
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/LimitedColorRoundtripTest.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/LimitedColorRoundtripTest.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/LimitedColorRoundtripTest.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/LimitedColorRoundtripTest.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,54 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+@RunWith(Theories.class)
+public class LimitedColorRoundtripTest extends RoundtripBase {
+
+    @DataPoints
+    public static BufferedImage[] images = new BufferedImage[] {
+            TestImages.createLimitedColorImage(1, 1), // minimal
+            TestImages.createLimitedColorImage(2, 2), //
+            TestImages.createLimitedColorImage(10, 10), // larger than 8
+            TestImages.createLimitedColorImage(300, 300), // larger than 256
+    };
+
+    @DataPoints
+    public static FormatInfo[] formatInfos = FormatInfo.READ_WRITE_FORMATS;
+
+    @Theory
+    public void testLimitedColorRoundtrip(final BufferedImage testImage, final FormatInfo formatInfo) throws Exception {
+            boolean imageExact = true;
+            if (formatInfo.colorSupport == FormatInfo.COLOR_BITMAP) {
+                imageExact = false;
+            }
+            if (formatInfo.colorSupport == FormatInfo.COLOR_GRAYSCALE) {
+                imageExact = false;
+            }
+
+            roundtrip(formatInfo, testImage, "indexable", imageExact);
+    }
+
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/NullParametersRoundtripTest.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/NullParametersRoundtripTest.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/NullParametersRoundtripTest.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/NullParametersRoundtripTest.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,51 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+import org.apache.commons.imaging.Imaging;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(Theories.class)
+public class NullParametersRoundtripTest extends RoundtripBase {
+
+    @DataPoints
+    public static FormatInfo[] formatInfos = FormatInfo.READ_WRITE_FORMATS;
+
+    @Theory
+    public void testNullParametersRoundtrip(final FormatInfo formatInfo) throws Exception {
+        final BufferedImage testImage = TestImages.createFullColorImage(1, 1);
+        final File temp1 = createTempFile("nullParameters.", "." + formatInfo.format.getExtension());
+        Imaging.writeImage(testImage, temp1, formatInfo.format, null);
+        Imaging.getImageInfo(temp1, null);
+        Imaging.getImageSize(temp1, null);
+        Imaging.getMetadata(temp1, null);
+        Imaging.getICCProfile(temp1, null);
+        BufferedImage imageRead = Imaging.getBufferedImage(temp1, null);
+
+        assertNotNull(imageRead);
+    }
+
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/PixelDensityRoundtrip.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/PixelDensityRoundtrip.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/PixelDensityRoundtrip.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/PixelDensityRoundtrip.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,70 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.imaging.ImageInfo;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.ImagingConstants;
+import org.apache.commons.imaging.PixelDensity;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Theories.class)
+public class PixelDensityRoundtrip extends RoundtripBase {
+
+    @DataPoints
+    public static FormatInfo[] formatInfos = FormatInfo.PRESERVING_RESOLUTION_FORMATS;
+
+    @Theory
+    public void testPixelDensityRoundtrip(final FormatInfo formatInfo) throws Exception {
+        final BufferedImage testImage = TestImages.createFullColorImage(2, 2);
+
+        final File temp1 = createTempFile("pixeldensity.", "."
+                + formatInfo.format.getExtension());
+
+        final Map<String, Object> params = new HashMap<>();
+        final PixelDensity pixelDensity = PixelDensity.createFromPixelsPerInch(75, 150);
+        params.put(ImagingConstants.PARAM_KEY_PIXEL_DENSITY, pixelDensity);
+        Imaging.writeImage(testImage, temp1, formatInfo.format, params);
+
+        final ImageInfo imageInfo = Imaging.getImageInfo(temp1);
+        if (imageInfo != null) {
+            final int xReadDPI = imageInfo.getPhysicalWidthDpi();
+            final int yReadDPI = imageInfo.getPhysicalHeightDpi();
+            // allow a 5% margin of error in storage and conversion
+            assertTrue("horizontal pixel density stored wrongly for " + formatInfo.format +
+                            " in=" + pixelDensity.horizontalDensityInches() + ", out=" + xReadDPI,
+                    Math.abs((xReadDPI - pixelDensity.horizontalDensityInches()) /
+                            pixelDensity.horizontalDensityInches()) <= 0.05);
+            assertTrue("vertical pixel density stored wrongly for " + formatInfo.format +
+                            " in=" + pixelDensity.verticalDensityInches() + ", out=" + yReadDPI,
+                    Math.abs((yReadDPI - pixelDensity.verticalDensityInches()) /
+                            pixelDensity.verticalDensityInches()) <= 0.05);
+        }
+    }
+
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/RoundtripBase.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/RoundtripBase.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/RoundtripBase.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/RoundtripBase.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,79 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.ImagingConstants;
+import org.apache.commons.imaging.common.RgbBufferedImageFactory;
+import org.apache.commons.imaging.util.Debug;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+import static org.junit.Assert.assertNotNull;
+
+public class RoundtripBase {
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    protected void roundtrip(final FormatInfo formatInfo, final BufferedImage testImage,
+                             final String tempPrefix, final boolean imageExact) throws IOException,
+            ImageReadException, ImageWriteException {
+        final File temp1 = createTempFile(tempPrefix + ".", "."
+                + formatInfo.format.getExtension());
+        Debug.debug("tempFile: " + temp1.getName());
+
+        final Map<String, Object> params = new HashMap<>();
+        Imaging.writeImage(testImage, temp1, formatInfo.format, params);
+
+        final Map<String, Object> readParams = new HashMap<>();
+        readParams.put(ImagingConstants.BUFFERED_IMAGE_FACTORY,
+                new RgbBufferedImageFactory());
+        final BufferedImage image2 = Imaging.getBufferedImage(temp1, readParams);
+        assertNotNull(image2);
+
+        if (imageExact) {
+            // note tolerance when comparing grayscale images
+            // BufferedImages of
+            ImageAsserts.assertEquals(testImage, image2);
+        }
+
+        if (formatInfo.identicalSecondWrite) {
+            final File temp2 = createTempFile(tempPrefix + ".", "."
+                    + formatInfo.format.getExtension());
+            // Debug.debug("tempFile: " + tempFile.getName());
+            Imaging.writeImage(image2, temp2, formatInfo.format, params);
+
+            ImageAsserts.assertEquals(temp1, temp2);
+        }
+    }
+
+    protected File createTempFile(final String prefix, final String suffix)
+            throws IOException {
+        return File.createTempFile(prefix, suffix, folder.newFolder());
+    }
+
+}

Added: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/TestImages.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/TestImages.java?rev=1750158&view=auto
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/TestImages.java (added)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/roundtrip/TestImages.java Fri Jun 24 19:11:18 2016
@@ -0,0 +1,115 @@
+/*
+ * 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.commons.imaging.roundtrip;
+
+import java.awt.image.BufferedImage;
+
+final class TestImages {
+
+    private TestImages() {
+    }
+
+    static BufferedImage createArgbBitmapImage(final int width, final int height) {
+        final BufferedImage result = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_ARGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                // alternating black and white.
+                final int modulator = y + 2; // make sure lines vary.
+                final int argb = (x + y) % modulator == 0 ? 0xff000000 : 0xffffffff;
+                result.setRGB(x, y, argb);
+            }
+        }
+        return result;
+    }
+
+    static BufferedImage createBitmapBitmapImage(final int width, final int height) {
+        final BufferedImage result = new BufferedImage(width, height,
+                BufferedImage.TYPE_BYTE_BINARY);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                // alternating black and white.
+                final int modulator = y + 2; // make sure lines vary.
+                final int argb = (x + y) % modulator == 0 ? 0xff000000 : 0xffffffff;
+                result.setRGB(x, y, argb);
+            }
+        }
+        return result;
+    }
+
+    static BufferedImage createArgbGrayscaleImage(final int width, final int height) {
+        final BufferedImage result = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_ARGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                final int value = (256 * (x + y)) / (width + height);
+                final int argb = (0xff << 24) | (value << 16) | (value << 8)
+                        | (value << 0);
+
+                result.setRGB(x, y, argb);
+            }
+        }
+        return result;
+    }
+
+    static BufferedImage createGrayscaleGrayscaleImage(final int width, final int height) {
+        final BufferedImage result = new BufferedImage(width, height,
+                BufferedImage.TYPE_BYTE_GRAY);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                final int value = (256 * (x + y)) / (width + height);
+                final int argb = (0xff << 24) | (value << 16) | (value << 8)
+                        | (value << 0);
+
+                result.setRGB(x, y, argb);
+            }
+        }
+        return result;
+    }
+
+    static BufferedImage createLimitedColorImage(final int width, final int height) {
+        final int colors[] = {0xffffffff, 0xff000000, 0xfff00000, 0xff0000ff,
+                0xff123456, 0xfffefeff, 0xff7f817f,};
+
+        final BufferedImage result = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_ARGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                final int argb = colors[(x + y) % colors.length];
+                result.setRGB(x, y, argb);
+            }
+        }
+        return result;
+    }
+
+    static BufferedImage createFullColorImage(final int width, final int height) {
+        final BufferedImage result = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_ARGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                final int red = (x * 255) / width;
+                final int green = (y * 255) / height;
+                final int blue = ((x + y) * 255) / (width + height);
+                final int argb = (0xff << 24) | (red << 16) | (green << 8)
+                        | (blue << 0);
+                result.setRGB(x, y, argb);
+            }
+        }
+        return result;
+    }
+}