forked from AuroraMiddleware/gtk
Added some tests of composite to highlight problems in the old
* gdk-pixbuf/.cvsignore: * gdk-pixbuf/Makefile.am: * gdk-pixbuf/test-gdk-pixbuf.c (store_pixel), (fill_with_pixel), (load_pixel), (simple_composite_test_one), (simple_composite_test_one_type), (simple_composite_test), (main): Added some tests of composite to highlight problems in the old implementation. These tests run without any user interaction. Just do "make check". * gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest), (composite_pixel), (composite_line): Fix composite to do a textbook "A over B" composite. This was clearly the intent, and it was easy to fix the code to do it. (Note to those that read my earlier tries at a patch; this version fixes typos that were present in all my patch attempts. I checked the final version by adding more tests.)
This commit is contained in:
parent
fec650eb38
commit
24fa8a64bc
@ -5,6 +5,7 @@ Makefile
|
||||
.libs
|
||||
*.la
|
||||
*.lo
|
||||
test-gdk-pixbuf
|
||||
testpixbuf
|
||||
testpixbuf-drawable
|
||||
testpixbuf-scale
|
||||
|
@ -1,3 +1,21 @@
|
||||
2000-05-04 Darin Adler <darin@eazel.com>
|
||||
|
||||
* gdk-pixbuf/.cvsignore:
|
||||
* gdk-pixbuf/Makefile.am:
|
||||
* gdk-pixbuf/test-gdk-pixbuf.c (store_pixel), (fill_with_pixel),
|
||||
(load_pixel), (simple_composite_test_one),
|
||||
(simple_composite_test_one_type), (simple_composite_test), (main):
|
||||
Added some tests of composite to highlight problems in the old
|
||||
implementation. These tests run without any user interaction.
|
||||
Just do "make check".
|
||||
|
||||
* gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest),
|
||||
(composite_pixel), (composite_line): Fix composite to do a textbook
|
||||
"A over B" composite. This was clearly the intent, and it was easy
|
||||
to fix the code to do it. (Note to those that read my earlier tries
|
||||
at a patch; this version fixes typos that were present in all
|
||||
my patch attempts. I checked the final version by adding more tests.)
|
||||
|
||||
2000-04-22 05:27:43 2000 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gdk-pixbuf/pixops/pixops.c (pixops_scale_nearest): Properly
|
||||
|
@ -138,7 +138,8 @@ extra_sources = $(libpixbufloader_png_la_SOURCES) \
|
||||
builtin_libraries =
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = testpixbuf testpixbuf-drawable testanimation testpixbuf-scale
|
||||
noinst_PROGRAMS = test-gdk-pixbuf testpixbuf testpixbuf-drawable testanimation testpixbuf-scale
|
||||
TESTS = test-gdk-pixbuf
|
||||
|
||||
DEPS = libgdk_pixbuf.la
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_builddir) \
|
||||
@ -150,11 +151,13 @@ AM_CPPFLAGS = "-DPIXBUF_LIBDIR=\"$(libexecdir)\""
|
||||
LDADDS = libgdk_pixbuf.la $(GLIB_LIBS) $(GTK_LIBS) $(STATIC_LIB_DEPS)
|
||||
|
||||
if INSIDE_GNOME_LIBS
|
||||
test_gdk_pixbuf_LDADD = $(LDADDS) -lgmodule
|
||||
testpixbuf_LDADD = $(LDADDS) -lgmodule
|
||||
testpixbuf_drawable_LDADD = $(LDADDS)
|
||||
testpixbuf_scale_LDADD = $(LDADDS)
|
||||
testanimation_LDADD = $(LDADDS) -lgmodule
|
||||
else
|
||||
test_gdk_pixbuf_LDADD = $(LDADDS) $(GNOME_LIBS) -lgmodule
|
||||
testpixbuf_LDADD = $(LDADDS) $(GNOME_LIBS) -lgmodule
|
||||
testpixbuf_drawable_LDADD = $(LDADDS) $(GNOME_LIBS)
|
||||
testpixbuf_scale_LDADD = $(LDADDS) $(GNOME_LIBS)
|
||||
|
@ -171,36 +171,23 @@ pixops_composite_nearest (guchar *dest_buf,
|
||||
unsigned int a0;
|
||||
|
||||
if (src_has_alpha)
|
||||
a0 = (p[3] * overall_alpha + 0xff) >> 8;
|
||||
a0 = (p[3] * overall_alpha) / 0xff;
|
||||
else
|
||||
a0 = overall_alpha;
|
||||
|
||||
if (dest_has_alpha)
|
||||
{
|
||||
unsigned int a1 = dest[3];
|
||||
unsigned int total = a0 + a1;
|
||||
|
||||
if (total)
|
||||
{
|
||||
dest[0] = (a0 * src[0] + a1 * dest[0]) / (total);
|
||||
dest[1] = (a0 * src[1] + a1 * dest[1]) / (total);
|
||||
dest[2] = (a0 * src[2] + a1 * dest[2]) / (total);
|
||||
dest[3] = total - ((a0 * a1 + 0xff) >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
dest[2] = 0;
|
||||
dest[3] = 0;
|
||||
}
|
||||
dest[0] = (a0 * src[0] + (0xff - a0) * dest[0]) / 0xff;
|
||||
dest[1] = (a0 * src[1] + (0xff - a0) * dest[1]) / 0xff;
|
||||
dest[2] = (a0 * src[2] + (0xff - a0) * dest[2]) / 0xff;
|
||||
dest[3] = (0xff * a0 + (0xff - a0) * dest[3]) / 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = dest[0] + ((a0 * (p[0] - dest[0]) + 0xff) >> 8);
|
||||
dest[1] = dest[1] + ((a0 * (p[1] - dest[1]) + 0xff) >> 8);
|
||||
dest[2] = dest[2] + ((a0 * (p[2] - dest[2]) + 0xff) >> 8);
|
||||
|
||||
dest[0] = (a0 * p[0] + (0xff - a0) * dest[0]) / 0xff;
|
||||
dest[1] = (a0 * p[1] + (0xff - a0) * dest[1]) / 0xff;
|
||||
dest[2] = (a0 * p[2] + (0xff - a0) * dest[2]) / 0xff;
|
||||
|
||||
if (dest_channels == 4)
|
||||
dest[3] = 0xff;
|
||||
}
|
||||
@ -309,29 +296,18 @@ composite_pixel (guchar *dest, int dest_x, int dest_channels, int dest_has_alpha
|
||||
{
|
||||
if (dest_has_alpha)
|
||||
{
|
||||
unsigned int w = (((1 << 16) - a) * dest[3]) >> 8;
|
||||
unsigned int total = a + w;
|
||||
|
||||
if (total)
|
||||
{
|
||||
dest[0] = (r + w * dest[0]) / total;
|
||||
dest[1] = (g + w * dest[1]) / total;
|
||||
dest[2] = (b + w * dest[2]) / total;
|
||||
dest[3] = (r * w) >> 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
dest[2] = 0;
|
||||
dest[3] = 0;
|
||||
}
|
||||
unsigned int w = (0xff0000 - a) * dest[3];
|
||||
|
||||
dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
|
||||
dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
|
||||
dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
|
||||
dest[3] = (0xff * a + (0xff0000 - a) * dest[3]) / 0xff0000;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = ((0xff0000 - a) * dest[0] + r) >> 24;
|
||||
dest[1] = ((0xff0000 - a) * dest[1] + g) >> 24;
|
||||
dest[2] = ((0xff0000 - a) * dest[2] + b) >> 24;
|
||||
dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
|
||||
dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
|
||||
dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,7 +342,7 @@ composite_line (int *weights, int n_x, int n_y,
|
||||
ta = q[3] * line_weights[j];
|
||||
else
|
||||
ta = 0xff * line_weights[j];
|
||||
|
||||
|
||||
r += ta * q[0];
|
||||
g += ta * q[1];
|
||||
b += ta * q[2];
|
||||
@ -378,29 +354,18 @@ composite_line (int *weights, int n_x, int n_y,
|
||||
|
||||
if (dest_has_alpha)
|
||||
{
|
||||
unsigned int w = (((1 << 16) - a) * dest[3]) >> 8;
|
||||
unsigned int total = a + w;
|
||||
unsigned int w = (0xff0000 - a) * dest[3];
|
||||
|
||||
if (total)
|
||||
{
|
||||
dest[0] = (r + w * dest[0]) / total;
|
||||
dest[1] = (r + w * dest[1]) / total;
|
||||
dest[2] = (r + w * dest[2]) / total;
|
||||
dest[3] = (r * w) >> 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
dest[2] = 0;
|
||||
dest[3] = 0;
|
||||
}
|
||||
dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
|
||||
dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
|
||||
dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
|
||||
dest[3] = (0xff * a + (0xff0000 - a) * dest[3]) / 0xff0000;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = ((0xff0000 - a) * dest[0] + r) >> 24;
|
||||
dest[1] = ((0xff0000 - a) * dest[1] + g) >> 24;
|
||||
dest[2] = ((0xff0000 - a) * dest[2] + b) >> 24;
|
||||
dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;
|
||||
dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;
|
||||
dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;
|
||||
}
|
||||
|
||||
dest += dest_channels;
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
||||
|
||||
/* GdkPixbuf library - test program
|
||||
*
|
||||
* Copyright (C) 1999 The Free Software Foundation
|
||||
@ -27,7 +29,210 @@
|
||||
|
||||
|
||||
|
||||
static void
|
||||
store_pixel (guchar *pixels,
|
||||
int pixel,
|
||||
gboolean alpha)
|
||||
{
|
||||
if (alpha) {
|
||||
pixels[0] = pixel >> 24;
|
||||
pixels[1] = pixel >> 16;
|
||||
pixels[2] = pixel >> 8;
|
||||
pixels[3] = pixel;
|
||||
} else {
|
||||
pixels[0] = pixel >> 16;
|
||||
pixels[1] = pixel >> 8;
|
||||
pixels[2] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fill_with_pixel (GdkPixbuf *pixbuf,
|
||||
int pixel)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (x = 0; x < gdk_pixbuf_get_width (pixbuf); x++) {
|
||||
for (y = 0; y < gdk_pixbuf_get_height (pixbuf); y++) {
|
||||
store_pixel (gdk_pixbuf_get_pixels (pixbuf)
|
||||
+ y * gdk_pixbuf_get_rowstride (pixbuf)
|
||||
+ x * gdk_pixbuf_get_n_channels (pixbuf),
|
||||
pixel,
|
||||
gdk_pixbuf_get_has_alpha (pixbuf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
load_pixel (const guchar *pixels,
|
||||
gboolean alpha)
|
||||
{
|
||||
if (alpha)
|
||||
return (((((pixels[0] << 8) | pixels[1]) << 8) | pixels[2]) << 8) | pixels[3];
|
||||
else
|
||||
return (((pixels[0] << 8) | pixels[1]) << 8) | pixels[2];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
simple_composite_test_one (GdkInterpType type,
|
||||
int source_pixel,
|
||||
gboolean source_alpha,
|
||||
int destination_pixel,
|
||||
gboolean destination_alpha,
|
||||
int expected_result)
|
||||
{
|
||||
GdkPixbuf *source_pixbuf;
|
||||
GdkPixbuf *destination_pixbuf;
|
||||
int result_pixel;
|
||||
|
||||
source_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, source_alpha, 8, 32, 32);
|
||||
destination_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, destination_alpha, 8, 32, 32);
|
||||
|
||||
fill_with_pixel (source_pixbuf, source_pixel);
|
||||
fill_with_pixel (destination_pixbuf, destination_pixel);
|
||||
|
||||
gdk_pixbuf_composite (source_pixbuf, destination_pixbuf,
|
||||
0, 0, 32, 32, 0, 0, 1, 1, type, 0xFF);
|
||||
|
||||
result_pixel = load_pixel (gdk_pixbuf_get_pixels (destination_pixbuf)
|
||||
+ 16 * gdk_pixbuf_get_rowstride (destination_pixbuf)
|
||||
+ 16 * gdk_pixbuf_get_n_channels (destination_pixbuf),
|
||||
destination_alpha);
|
||||
|
||||
gdk_pixbuf_unref (source_pixbuf);
|
||||
gdk_pixbuf_unref (destination_pixbuf);
|
||||
|
||||
if (result_pixel != expected_result) {
|
||||
char *interpolation_type, *source_string, *destination_string, *result_string, *expected_string;
|
||||
|
||||
switch (type) {
|
||||
case GDK_INTERP_NEAREST: interpolation_type = "GDK_INTERP_NEAREST"; break;
|
||||
case GDK_INTERP_TILES: interpolation_type = "GDK_INTERP_TILES"; break;
|
||||
case GDK_INTERP_BILINEAR: interpolation_type = "GDK_INTERP_BILINEAR"; break;
|
||||
case GDK_INTERP_HYPER: interpolation_type = "GDK_INTERP_HYPER"; break;
|
||||
default: interpolation_type = "???";
|
||||
}
|
||||
|
||||
if (source_alpha) {
|
||||
source_string = g_strdup_printf ("0x%08X", source_pixel);
|
||||
} else {
|
||||
source_string = g_strdup_printf ("0x%06X", source_pixel);
|
||||
}
|
||||
|
||||
if (destination_alpha) {
|
||||
destination_string = g_strdup_printf ("0x%08X", destination_pixel);
|
||||
result_string = g_strdup_printf ("0x%08X", result_pixel);
|
||||
expected_string = g_strdup_printf ("0x%08X", expected_result);
|
||||
} else {
|
||||
destination_string = g_strdup_printf ("0x%06X", destination_pixel);
|
||||
result_string = g_strdup_printf ("0x%06X", result_pixel);
|
||||
expected_string = g_strdup_printf ("0x%06X", expected_result);
|
||||
}
|
||||
|
||||
g_message ("simple_composite_test (%s): composite %s on top of %s, expected %s, got %s",
|
||||
interpolation_type,
|
||||
source_string, destination_string, expected_string, result_string);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
simple_composite_test_one_type (GdkInterpType type)
|
||||
{
|
||||
gboolean success;
|
||||
|
||||
success = TRUE;
|
||||
|
||||
/* There are only a few trivial cases in here.
|
||||
* But these were enough to expose the problems in the old composite code.
|
||||
*/
|
||||
|
||||
/* Non-alpha into non-alpha. */
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0x000000, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0xFFFFFF, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0xFF0000, FALSE, 0x000000, FALSE, 0xFF0000);
|
||||
success &= simple_composite_test_one (type, 0x00FF00, FALSE, 0x000000, FALSE, 0x00FF00);
|
||||
success &= simple_composite_test_one (type, 0x0000FF, FALSE, 0x000000, FALSE, 0x0000FF);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0xFF0000, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0x00FF00, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0x0000FF, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0x00FF00, FALSE, 0xFFFFFF, FALSE, 0x00FF00);
|
||||
success &= simple_composite_test_one (type, 0xFFFFFF, FALSE, 0xFFFFFF, FALSE, 0xFFFFFF);
|
||||
|
||||
/* Alpha into non-alpha. */
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x000000, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0xFFFFFF, FALSE, 0xFFFFFF);
|
||||
success &= simple_composite_test_one (type, 0x0000007F, TRUE, 0xFFFFFF, FALSE, 0x808080);
|
||||
success &= simple_composite_test_one (type, 0x00000080, TRUE, 0xFFFFFF, FALSE, 0x7F7F7F);
|
||||
success &= simple_composite_test_one (type, 0x000000FF, TRUE, 0xFFFFFF, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0x000000FF, TRUE, 0xFFFFFF, FALSE, 0x000000);
|
||||
success &= simple_composite_test_one (type, 0xFF0000FF, TRUE, 0x000000, FALSE, 0xFF0000);
|
||||
success &= simple_composite_test_one (type, 0x00FF00FF, TRUE, 0x000000, FALSE, 0x00FF00);
|
||||
success &= simple_composite_test_one (type, 0x0000FFFF, TRUE, 0x000000, FALSE, 0x0000FF);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0xFF0000, FALSE, 0xFF0000);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x00FF00, FALSE, 0x00FF00);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x0000FF, FALSE, 0x0000FF);
|
||||
success &= simple_composite_test_one (type, 0x00FF0080, TRUE, 0xFFFFFF, FALSE, 0x7FFF7F);
|
||||
success &= simple_composite_test_one (type, 0xFFFFFFFF, TRUE, 0xFFFFFF, FALSE, 0xFFFFFF);
|
||||
|
||||
/* Non-alpha into alpha. */
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0x00000000, TRUE, 0x000000FF);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0xFFFFFFFF, TRUE, 0x000000FF);
|
||||
success &= simple_composite_test_one (type, 0xFF0000, FALSE, 0x00000000, TRUE, 0xFF0000FF);
|
||||
success &= simple_composite_test_one (type, 0x00FF00, FALSE, 0x00000000, TRUE, 0x00FF00FF);
|
||||
success &= simple_composite_test_one (type, 0x0000FF, FALSE, 0x00000000, TRUE, 0x0000FFFF);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0xFF0000FF, TRUE, 0x000000FF);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0x00FF00FF, TRUE, 0x000000FF);
|
||||
success &= simple_composite_test_one (type, 0x000000, FALSE, 0x0000FFFF, TRUE, 0x000000FF);
|
||||
success &= simple_composite_test_one (type, 0x00FF00, FALSE, 0xFFFFFF00, TRUE, 0x00FF00FF);
|
||||
success &= simple_composite_test_one (type, 0xFFFFFF, FALSE, 0xFFFFFFFF, TRUE, 0xFFFFFFFF);
|
||||
|
||||
/* Alpha into alpha. */
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x00000000, TRUE, 0x00000000);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0xFFFFFFFF, TRUE, 0xFFFFFFFF);
|
||||
success &= simple_composite_test_one (type, 0x0000007F, TRUE, 0xFFFFFFFF, TRUE, 0x808080FF);
|
||||
success &= simple_composite_test_one (type, 0x00000080, TRUE, 0xFFFFFFFF, TRUE, 0x7F7F7FFF);
|
||||
success &= simple_composite_test_one (type, 0x000000FF, TRUE, 0xFFFFFFFF, TRUE, 0x000000FF);
|
||||
success &= simple_composite_test_one (type, 0xFF0000FF, TRUE, 0x00000000, TRUE, 0xFF0000FF);
|
||||
success &= simple_composite_test_one (type, 0x00FF00FF, TRUE, 0x00000000, TRUE, 0x00FF00FF);
|
||||
success &= simple_composite_test_one (type, 0x0000FFFF, TRUE, 0x00000000, TRUE, 0x0000FFFF);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0xFF0000FF, TRUE, 0xFF0000FF);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x00FF00FF, TRUE, 0x00FF00FF);
|
||||
success &= simple_composite_test_one (type, 0x00000000, TRUE, 0x0000FFFF, TRUE, 0x0000FFFF);
|
||||
success &= simple_composite_test_one (type, 0x00FF0080, TRUE, 0xFFFFFF00, TRUE, 0x7FFF7F80);
|
||||
success &= simple_composite_test_one (type, 0xFFFFFFFF, TRUE, 0xFFFFFFFF, TRUE, 0xFFFFFFFF);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
simple_composite_test (void)
|
||||
{
|
||||
gboolean success;
|
||||
|
||||
success = TRUE;
|
||||
|
||||
success &= simple_composite_test_one_type (GDK_INTERP_NEAREST);
|
||||
success &= simple_composite_test_one_type (GDK_INTERP_TILES);
|
||||
success &= simple_composite_test_one_type (GDK_INTERP_BILINEAR);
|
||||
success &= simple_composite_test_one_type (GDK_INTERP_HYPER);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = EXIT_SUCCESS;
|
||||
|
||||
/* Run some tests. */
|
||||
if (!simple_composite_test ()) {
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user