[cairo-commit] 2 commits - src/cairo-png.c test/create-from-png-alpha-ref.png test/create-from-png.c test/create-from-png-gray-alpha-ref.png test/create-from-png-gray-ref.png test/create-from-png-indexed-alpha-ref.png test/create-from-png-indexed-ref.png test/create-from-png-ref.png

Chris Wilson ickle at kemper.freedesktop.org
Mon Apr 21 11:56:24 PDT 2008


 src/cairo-png.c                            |   38 ++++-----
 test/create-from-png-alpha-ref.png         |binary
 test/create-from-png-gray-alpha-ref.png    |binary
 test/create-from-png-gray-ref.png          |binary
 test/create-from-png-indexed-alpha-ref.png |binary
 test/create-from-png-indexed-ref.png       |binary
 test/create-from-png-ref.png               |binary
 test/create-from-png.c                     |  121 +++++++++++++++++++++++++++++
 8 files changed, 141 insertions(+), 18 deletions(-)

New commits:
commit 20b1b33c0fc76d2ec2b4f83d9ce058429c4f49db
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Apr 21 19:54:48 2008 +0100

    [cairo-png] Recheck png_info after setting transformation options.
    
    After specifying how to transform the various colour modes into ones we
    can handle, re-read the image header to confirm that the output on
    reading the PNG will be RGB24 or ARGB32. This simplifies our logic
    considerably as we no longer have to second guess the colour space
    transformation that will be performed by libpng. (And allows for some
    paranoid checks.)

diff --git a/src/cairo-png.c b/src/cairo-png.c
index 3ec85c0..c1cda34 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -434,7 +434,6 @@ read_png (png_rw_ptr	read_func,
     unsigned int i;
     cairo_format_t format;
     cairo_status_t status;
-    cairo_bool_t need_alpha;
 
     /* XXX: Perhaps we'll want some other error handlers? */
     png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
@@ -486,11 +485,8 @@ read_png (png_rw_ptr	read_func,
     }
 
     /* transform transparency to alpha */
-    need_alpha = FALSE;
-    if (png_get_valid (png, info, PNG_INFO_tRNS)) {
+    if (png_get_valid (png, info, PNG_INFO_tRNS))
         png_set_tRNS_to_alpha (png);
-	need_alpha = TRUE;
-    }
 
     if (depth == 16)
         png_set_strip_16 (png);
@@ -508,30 +504,36 @@ read_png (png_rw_ptr	read_func,
     if (interlace != PNG_INTERLACE_NONE)
         png_set_interlace_handling (png);
 
+    /* recheck header after setting EXPAND options */
+    png_read_update_info (png, info);
+    png_get_IHDR (png, info,
+                  &png_width, &png_height, &depth,
+                  &color_type, &interlace, NULL, NULL);
+    if (depth != 8 || interlace != PNG_INTERLACE_NONE ||
+	! (color_type == PNG_COLOR_TYPE_RGB ||
+	   color_type == PNG_COLOR_TYPE_RGB_ALPHA))
+    {
+	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR));
+	goto BAIL;
+    }
+
     switch (color_type) {
 	default:
-	case PNG_COLOR_TYPE_GRAY_ALPHA:
+	    ASSERT_NOT_REACHED;
+	    /* fall-through just in case ;-) */
+
 	case PNG_COLOR_TYPE_RGB_ALPHA:
 	    format = CAIRO_FORMAT_ARGB32;
 	    png_set_read_user_transform_fn (png, premultiply_data);
 	    break;
 
-	case PNG_COLOR_TYPE_GRAY:
 	case PNG_COLOR_TYPE_RGB:
-	case PNG_COLOR_TYPE_PALETTE:
-	    if (need_alpha) {
-		format = CAIRO_FORMAT_ARGB32;
-		png_set_read_user_transform_fn (png, premultiply_data);
-	    } else {
-		format = CAIRO_FORMAT_RGB24;
-		png_set_read_user_transform_fn (png, convert_bytes_to_data);
-		png_set_filler (png, 0xff, PNG_FILLER_AFTER);
-	    }
+	    format = CAIRO_FORMAT_RGB24;
+	    png_set_read_user_transform_fn (png, convert_bytes_to_data);
+	    png_set_filler (png, 0xff, PNG_FILLER_AFTER);
 	    break;
     }
 
-    png_read_update_info (png, info);
-
     stride = cairo_format_stride_for_width (format, png_width);
     if (stride < 0) {
 	surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
commit a313547f6d0ed060de7fc27dc2886ef09b8598d4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Apr 21 19:44:11 2008 +0100

    [test/create-from-png] Check loading of various colour types.
    
    Check that when loading from index/gray/rgb PNGs, with and without
    alpha/transparency, that the correct surface is generated by read_png(),
    i.e. if the PNG contains an alpha channel then the image must be an
    ARGB32 surface.

diff --git a/test/create-from-png-alpha-ref.png b/test/create-from-png-alpha-ref.png
new file mode 100644
index 0000000..a5175a1
Binary files /dev/null and b/test/create-from-png-alpha-ref.png differ
diff --git a/test/create-from-png-gray-alpha-ref.png b/test/create-from-png-gray-alpha-ref.png
new file mode 100644
index 0000000..f5d47dc
Binary files /dev/null and b/test/create-from-png-gray-alpha-ref.png differ
diff --git a/test/create-from-png-gray-ref.png b/test/create-from-png-gray-ref.png
new file mode 100644
index 0000000..12dc90b
Binary files /dev/null and b/test/create-from-png-gray-ref.png differ
diff --git a/test/create-from-png-indexed-alpha-ref.png b/test/create-from-png-indexed-alpha-ref.png
new file mode 100644
index 0000000..9f32c69
Binary files /dev/null and b/test/create-from-png-indexed-alpha-ref.png differ
diff --git a/test/create-from-png-indexed-ref.png b/test/create-from-png-indexed-ref.png
new file mode 100644
index 0000000..6b1d713
Binary files /dev/null and b/test/create-from-png-indexed-ref.png differ
diff --git a/test/create-from-png-ref.png b/test/create-from-png-ref.png
index 765adc4..5753560 100644
Binary files a/test/create-from-png-ref.png and b/test/create-from-png-ref.png differ
diff --git a/test/create-from-png.c b/test/create-from-png.c
index fe08b30..0707680 100644
--- a/test/create-from-png.c
+++ b/test/create-from-png.c
@@ -145,5 +145,126 @@ main (void)
     }
     cairo_surface_destroy (surface);
 
+    /* check that loading alpha/opaque PNGs generate the correct surfaces */
+    xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+	       "create-from-png-alpha-ref.png");
+    surface = cairo_image_surface_create_from_png (filename);
+    if (cairo_surface_status (surface)) {
+	cairo_test_log ("Error reading PNG image %s: %s\n",
+			filename,
+			cairo_status_to_string (cairo_surface_status (surface)));
+	free (filename);
+	return CAIRO_TEST_FAILURE;
+    }
+    if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
+	cairo_test_log ("Error reading PNG image %s: did not create an ARGB32 image\n",
+		filename);
+	cairo_surface_destroy (surface);
+	return CAIRO_TEST_FAILURE;
+    }
+    free (filename);
+    cairo_surface_destroy (surface);
+
+    xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+	       "create-from-png-ref.png");
+    surface = cairo_image_surface_create_from_png (filename);
+    if (cairo_surface_status (surface)) {
+	cairo_test_log ("Error reading PNG image %s: %s\n",
+			filename,
+			cairo_status_to_string (cairo_surface_status (surface)));
+	free (filename);
+	return CAIRO_TEST_FAILURE;
+    }
+    if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
+	cairo_test_log ("Error reading PNG image %s: did not create an RGB24 image\n",
+		filename);
+	cairo_surface_destroy (surface);
+	return CAIRO_TEST_FAILURE;
+    }
+    free (filename);
+    cairo_surface_destroy (surface);
+
+    /* check paletted PNGs */
+    xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+	       "create-from-png-indexed-alpha-ref.png");
+    surface = cairo_image_surface_create_from_png (filename);
+    if (cairo_surface_status (surface)) {
+	cairo_test_log ("Error reading PNG image %s: %s\n",
+			filename,
+			cairo_status_to_string (cairo_surface_status (surface)));
+	free (filename);
+	return CAIRO_TEST_FAILURE;
+    }
+    if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
+	cairo_test_log ("Error reading PNG image %s: did not create an ARGB32 image\n",
+		filename);
+	free (filename);
+	cairo_surface_destroy (surface);
+	return CAIRO_TEST_FAILURE;
+    }
+    free (filename);
+    cairo_surface_destroy (surface);
+
+    xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+	       "create-from-png-indexed-ref.png");
+    surface = cairo_image_surface_create_from_png (filename);
+    if (cairo_surface_status (surface)) {
+	cairo_test_log ("Error reading PNG image %s: %s\n",
+			filename,
+			cairo_status_to_string (cairo_surface_status (surface)));
+	free (filename);
+	return CAIRO_TEST_FAILURE;
+    }
+    if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
+	cairo_test_log ("Error reading PNG image %s: did not create an RGB24 image\n",
+		filename);
+	free (filename);
+	cairo_surface_destroy (surface);
+	return CAIRO_TEST_FAILURE;
+    }
+    free (filename);
+    cairo_surface_destroy (surface);
+
+    /* check grayscale PNGs */
+    xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+	       "create-from-png-gray-alpha-ref.png");
+    surface = cairo_image_surface_create_from_png (filename);
+    if (cairo_surface_status (surface)) {
+	cairo_test_log ("Error reading PNG image %s: %s\n",
+			filename,
+			cairo_status_to_string (cairo_surface_status (surface)));
+	free (filename);
+	return CAIRO_TEST_FAILURE;
+    }
+    if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
+	cairo_test_log ("Error reading PNG image %s: did not create an ARGB32 image\n",
+		filename);
+	free (filename);
+	cairo_surface_destroy (surface);
+	return CAIRO_TEST_FAILURE;
+    }
+    free (filename);
+    cairo_surface_destroy (surface);
+
+    xasprintf (&filename, "%s/%s", srcdir ? srcdir : ".",
+	       "create-from-png-gray-ref.png");
+    surface = cairo_image_surface_create_from_png (filename);
+    if (cairo_surface_status (surface)) {
+	cairo_test_log ("Error reading PNG image %s: %s\n",
+			filename,
+			cairo_status_to_string (cairo_surface_status (surface)));
+	free (filename);
+	return CAIRO_TEST_FAILURE;
+    }
+    if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
+	cairo_test_log ("Error reading PNG image %s: did not create an RGB24 image\n",
+		filename);
+	free (filename);
+	cairo_surface_destroy (surface);
+	return CAIRO_TEST_FAILURE;
+    }
+    free (filename);
+    cairo_surface_destroy (surface);
+
     return cairo_test (&test);
 }


More information about the cairo-commit mailing list