Merge branch '0.8'
[swfdec.git] / test / swfdec_test_image.c
blob9c5e12503024bf3d37d61f23bbf155af0e81db26
1 /* Swfdec
2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_test_image.h"
25 #include "swfdec_test_function.h"
26 #include "swfdec_test_utils.h"
28 #define SWFDEC_TEST_IMAGE_IS_VALID(image) ((image)->surface && \
29 cairo_surface_status ((image)->surface) == CAIRO_STATUS_SUCCESS)
31 SwfdecTestImage *
32 swfdec_test_image_new (SwfdecAsContext *context, guint width, guint height)
34 SwfdecTestImage *ret;
35 SwfdecAsObject *object;
37 ret = g_object_new (SWFDEC_TYPE_TEST_IMAGE, "context", context, NULL);
38 ret->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
40 object = swfdec_as_object_new (context, NULL);
41 swfdec_as_object_set_constructor_by_name (object,
42 swfdec_as_context_get_string (context, "Image"), NULL);
43 swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (ret));
45 return ret;
48 /*** SWFDEC_TEST_IMAGE ***/
50 G_DEFINE_TYPE (SwfdecTestImage, swfdec_test_image, SWFDEC_TYPE_AS_RELAY)
52 static void
53 swfdec_test_image_dispose (GObject *object)
55 SwfdecTestImage *image = SWFDEC_TEST_IMAGE (object);
57 if (image->surface) {
58 cairo_surface_destroy (image->surface);
59 image->surface = NULL;
62 G_OBJECT_CLASS (swfdec_test_image_parent_class)->dispose (object);
65 static void
66 swfdec_test_image_class_init (SwfdecTestImageClass *klass)
68 GObjectClass *object_class = G_OBJECT_CLASS (klass);
70 object_class->dispose = swfdec_test_image_dispose;
73 static void
74 swfdec_test_image_init (SwfdecTestImage *this)
78 /*** AS CODE ***/
80 /* Compare two buffers, returning the number of pixels that are
81 * different and the maximum difference of any single color channel in
82 * result_ret.
84 * This function should be rewritten to compare all formats supported by
85 * cairo_format_t instead of taking a mask as a parameter.
87 static gboolean
88 buffer_diff_core (unsigned char *buf_a,
89 unsigned char *buf_b,
90 unsigned char *buf_diff,
91 int width,
92 int height,
93 int stride_a,
94 int stride_b,
95 int stride_diff)
97 int x, y;
98 gboolean result = TRUE;
99 guint32 *row_a, *row_b, *row;
101 for (y = 0; y < height; y++) {
102 row_a = (guint32 *) (gpointer) (buf_a + y * stride_a);
103 row_b = (guint32 *) (gpointer) (buf_b + y * stride_b);
104 row = (guint32 *) (gpointer) (buf_diff + y * stride_diff);
105 for (x = 0; x < width; x++) {
106 /* check if the pixels are the same */
107 if (row_a[x] != row_b[x]) {
108 int channel;
109 static const unsigned int threshold = 3;
110 guint32 diff_pixel = 0;
112 /* calculate a difference value for all 4 channels */
113 for (channel = 0; channel < 4; channel++) {
114 int value_a = (row_a[x] >> (channel*8)) & 0xff;
115 int value_b = (row_b[x] >> (channel*8)) & 0xff;
116 unsigned int diff;
117 diff = ABS (value_a - value_b);
118 if (diff <= threshold)
119 continue;
120 diff *= 4; /* emphasize */
121 diff += 128; /* make sure it's visible */
122 if (diff > 255)
123 diff = 255;
124 diff_pixel |= diff << (channel*8);
127 row[x] = diff_pixel;
128 if (diff_pixel)
129 result = FALSE;
130 } else {
131 row[x] = 0;
133 row[x] |= 0xff000000; /* Set ALPHA to 100% (opaque) */
136 return result;
139 SWFDEC_TEST_FUNCTION ("Image_compare", swfdec_test_image_compare)
140 void
141 swfdec_test_image_compare (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
142 SwfdecAsValue *argv, SwfdecAsValue *retval)
144 SwfdecTestImage *image, *compare, *diff;
145 SwfdecAsObject *o;
146 int w, h;
148 SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_IMAGE, &image, "o", &o);
150 if (!SWFDEC_IS_TEST_IMAGE (o->relay))
151 return;
152 compare = SWFDEC_TEST_IMAGE (o->relay);
154 SWFDEC_AS_VALUE_SET_OBJECT (retval, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (image)));
155 if (!SWFDEC_TEST_IMAGE_IS_VALID (image) ||
156 !SWFDEC_TEST_IMAGE_IS_VALID (compare))
157 return;
159 g_assert (cairo_surface_get_type (image->surface) == CAIRO_SURFACE_TYPE_IMAGE);
160 g_assert (cairo_surface_get_type (compare->surface) == CAIRO_SURFACE_TYPE_IMAGE);
162 w = cairo_image_surface_get_width (image->surface);
163 if (w != cairo_image_surface_get_width (compare->surface))
164 return;
165 h = cairo_image_surface_get_height (image->surface);
166 if (h != cairo_image_surface_get_height (compare->surface))
167 return;
168 diff = SWFDEC_TEST_IMAGE (swfdec_test_image_new (cx, w, h));
170 if (!buffer_diff_core (cairo_image_surface_get_data (image->surface),
171 cairo_image_surface_get_data (compare->surface),
172 cairo_image_surface_get_data (diff->surface),
173 w, h,
174 cairo_image_surface_get_stride (image->surface),
175 cairo_image_surface_get_stride (compare->surface),
176 cairo_image_surface_get_stride (diff->surface)) != 0) {
177 SWFDEC_AS_VALUE_SET_OBJECT (retval,
178 swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (diff)));
179 } else {
180 SWFDEC_AS_VALUE_SET_NULL (retval);
184 SWFDEC_TEST_FUNCTION ("Image_save", swfdec_test_image_save)
185 void
186 swfdec_test_image_save (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
187 SwfdecAsValue *argv, SwfdecAsValue *retval)
189 SwfdecTestImage *image;
190 const char *filename;
191 cairo_status_t status;
193 SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_IMAGE, &image, "s", &filename);
195 SWFDEC_AS_VALUE_SET_BOOLEAN (retval, FALSE);
196 if (!SWFDEC_TEST_IMAGE_IS_VALID (image))
197 return;
199 status = cairo_surface_write_to_png (image->surface, filename);
200 if (status != CAIRO_STATUS_SUCCESS) {
201 swfdec_test_throw (cx, "Couldn't save to %s: %s", filename, cairo_status_to_string (status));
204 SWFDEC_AS_VALUE_SET_BOOLEAN (retval, TRUE);
207 SWFDEC_TEST_FUNCTION ("Image", swfdec_test_image_create)
208 void
209 swfdec_test_image_create (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
210 SwfdecAsValue *argv, SwfdecAsValue *retval)
212 SwfdecTestImage *image;
213 const char *filename;
215 if (!swfdec_as_context_is_constructing (cx))
216 return;
218 SWFDEC_AS_CHECK (0, NULL, "s", &filename);
220 image = g_object_new (SWFDEC_TYPE_TEST_IMAGE, "context", cx, NULL);
221 image->surface = cairo_image_surface_create_from_png (filename);
223 swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (image));
224 SWFDEC_AS_VALUE_SET_OBJECT (retval, object);