summaryrefslogtreecommitdiffstats
path: root/test/test_images.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_images.c')
-rw-r--r--test/test_images.c533
1 files changed, 533 insertions, 0 deletions
diff --git a/test/test_images.c b/test/test_images.c
new file mode 100644
index 0000000..68a3251
--- /dev/null
+++ b/test/test_images.c
@@ -0,0 +1,533 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zbar.h>
+#include "test_images.h"
+
+typedef enum format_type_e
+{
+ GRAY,
+ YUVP,
+ YVUP,
+ YUYV,
+ YVYU,
+ UYVY,
+ RGB888,
+ BGR888,
+ RGB565B = 0x0565,
+ RGB565L = 0x1565,
+ RGB555B = 0x0555,
+ RGB555L = 0x1555,
+} format_type_t;
+
+typedef struct format_def_s {
+ uint32_t format;
+ format_type_t type;
+ uint8_t bpp;
+ uint8_t xdiv, ydiv;
+} format_def_t;
+
+typedef union packed_u {
+ uint32_t u32[3];
+ uint16_t u16[6];
+ uint8_t u8[12];
+} packed_t;
+
+/* bar colors */
+static const uint8_t Cr[] = { 0x22, 0x92, 0x80, 0xf0, 0x10, 0x80, 0x6e, 0xde };
+static const uint8_t Cb[] = { 0x36, 0x10, 0x80, 0x5a, 0xa6, 0x80, 0xf0, 0xca };
+
+static const format_def_t formats[] = {
+ { fourcc('G', 'R', 'E', 'Y'), GRAY, 8, 0, 0 },
+ { fourcc('Y', '8', '0', '0'), GRAY, 8, 0, 0 },
+ { fourcc('Y', '8', ' ', ' '), GRAY, 8, 0, 0 },
+ { fourcc('Y', '8', 0, 0), GRAY, 8, 0, 0 },
+
+ { fourcc('Y', 'U', 'V', '9'), YUVP, 9, 4, 4 },
+ { fourcc('Y', 'V', 'U', '9'), YVUP, 9, 4, 4 },
+
+ { fourcc('I', '4', '2', '0'), YUVP, 12, 2, 2 },
+ { fourcc('Y', 'U', '1', '2'), YUVP, 12, 2, 2 },
+ { fourcc('Y', 'V', '1', '2'), YVUP, 12, 2, 2 },
+ { fourcc('4', '1', '1', 'P'), YUVP, 12, 4, 1 },
+
+ { fourcc('N', 'V', '1', '2'), YUVP, 12, 2, 2 },
+ { fourcc('N', 'V', '2', '1'), YVUP, 12, 2, 2 },
+
+ { fourcc('4', '2', '2', 'P'), YUVP, 16, 2, 1 },
+
+ { fourcc('Y', 'U', 'Y', 'V'), YUYV, 16, 2, 1 },
+ { fourcc('Y', 'U', 'Y', '2'), YUYV, 16, 2, 1 },
+ { fourcc('Y', 'V', 'Y', 'U'), YVYU, 16, 2, 1 },
+ { fourcc('U', 'Y', 'V', 'Y'), UYVY, 16, 2, 1 },
+
+ {
+ fourcc('R', 'G', 'B', '3'),
+ RGB888,
+ 24,
+ },
+ {
+ fourcc('B', 'G', 'R', '3'),
+ BGR888,
+ 24,
+ },
+ {
+ fourcc(3, 0, 0, 0),
+ RGB888,
+ 32,
+ },
+ {
+ fourcc('R', 'G', 'B', '4'),
+ RGB888,
+ 32,
+ },
+ {
+ fourcc('B', 'G', 'R', '4'),
+ BGR888,
+ 32,
+ },
+ {
+ fourcc('R', 'G', 'B', 'P'),
+ RGB565L,
+ 16,
+ },
+ {
+ fourcc('R', 'G', 'B', 'O'),
+ RGB555L,
+ 16,
+ },
+ {
+ fourcc('R', 'G', 'B', 'R'),
+ RGB565B,
+ 16,
+ },
+ {
+ fourcc('R', 'G', 'B', 'Q'),
+ RGB555B,
+ 16,
+ },
+ { 0 }
+};
+
+static const char *encoded_widths =
+ "9 111 212241113121211311141132 11111 311213121312121332111132 111 9";
+const char *test_image_ean13_data = "6268964977804";
+
+static int allocated_images = 0;
+
+int test_image_check_cleanup()
+{
+ if (allocated_images)
+ fprintf(stderr, "ERROR: %d image data buffers still allocated\n",
+ allocated_images);
+ /*else
+ fprintf(stderr, "all image data buffers freed\n");*/
+ return (allocated_images);
+}
+
+static void test_cleanup_handler(zbar_image_t *img)
+{
+ void *data = (void *)zbar_image_get_data(img);
+ /*fprintf(stderr, "cleanup image data @%p\n", data);*/
+ free(data);
+ allocated_images--;
+}
+
+static inline const format_def_t *lookup_format(zbar_image_t *img)
+{
+ uint32_t ifmt = zbar_image_get_format(img);
+ const format_def_t *fmt;
+ for (fmt = formats; fmt->format; fmt++)
+ if (fmt->format == ifmt)
+ break;
+ if (!fmt->format) {
+ fprintf(stderr, "ERROR: no %.4s (%08" PRIx32 ") format\n",
+ (char *)&ifmt, ifmt);
+ return (NULL);
+ }
+ return (fmt);
+}
+
+static inline const format_def_t *alloc_data(zbar_image_t *img)
+{
+ allocated_images++;
+ const format_def_t *fmt = lookup_format(img);
+ if (!fmt)
+ return (NULL);
+
+ unsigned w = zbar_image_get_width(img);
+ unsigned h = zbar_image_get_height(img);
+ unsigned long planelen = w * h;
+ unsigned long datalen = planelen * fmt->bpp / 8;
+ uint8_t *data = malloc(datalen);
+
+ zbar_image_set_data(img, data, datalen, test_cleanup_handler);
+
+ /*fprintf(stderr, "create %.4s(%08"PRIx32") image data %lx bytes @%p\n",
+ (char*)&fmt->format, fmt->format, datalen, data);*/
+ return (fmt);
+}
+
+/* write intensity plane */
+static inline uint8_t *fill_bars_y(uint8_t *p, unsigned w, unsigned h)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0xff;
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ unsigned v = ((((i & 1) ? y : h - y) * 256) + h - 1) / h;
+ for (; x < x0; x++)
+ *(p++) = v;
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0xff;
+
+ return (p);
+}
+
+/* write Cb (U) or Cr (V) plane */
+static inline uint8_t *fill_bars_uv(uint8_t *p, unsigned w, unsigned h,
+ const uint8_t *C)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0x80;
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ for (; x < x0; x++)
+ *(p++) = C[i];
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0x80;
+
+ return (p);
+}
+
+/* write packed CbCr plane */
+static inline uint8_t *fill_bars_nv(uint8_t *p, unsigned w, unsigned h,
+ format_type_t order)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++) {
+ *(p++) = 0x80;
+ *(p++) = 0x80;
+ }
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ uint8_t u = (order == YUVP) ? Cb[i] : Cr[i];
+ uint8_t v = (order == YUVP) ? Cr[i] : Cb[i];
+ for (; x < x0; x++) {
+ *(p++) = u;
+ *(p++) = v;
+ }
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++) {
+ *(p++) = 0x80;
+ *(p++) = 0x80;
+ }
+
+ return (p);
+}
+
+/* write packed YCbCr plane */
+static inline uint8_t *fill_bars_yuv(uint8_t *p, unsigned w, unsigned h,
+ format_type_t order)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+ packed_t yuv;
+ uint32_t *q = (uint32_t *)p;
+ w /= 2;
+
+ yuv.u8[0] = yuv.u8[2] = (order == UYVY) ? 0x80 : 0xff;
+ yuv.u8[1] = yuv.u8[3] = (order == UYVY) ? 0xff : 0x80;
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++)
+ *(q++) = yuv.u32[0];
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ unsigned v = ((((i & 1) ? y : h - y) * 256) + h - 1) / h;
+ if (order == UYVY) {
+ yuv.u8[0] = Cb[i];
+ yuv.u8[2] = Cr[i];
+ yuv.u8[1] = yuv.u8[3] = v;
+ } else {
+ yuv.u8[0] = yuv.u8[2] = v;
+ yuv.u8[1] = (order == YUYV) ? Cb[i] : Cr[i];
+ yuv.u8[3] = (order == YVYU) ? Cr[i] : Cb[i];
+ }
+ for (; x < x0; x++)
+ *(q++) = yuv.u32[0];
+ }
+
+ yuv.u8[0] = yuv.u8[2] = (order == UYVY) ? 0x80 : 0xff;
+ yuv.u8[1] = yuv.u8[3] = (order == UYVY) ? 0xff : 0x80;
+ for (; y < h; y++)
+ for (x = 0; x < w; x++)
+ *(q++) = yuv.u32[0];
+
+ return ((uint8_t *)q);
+}
+
+static inline uint8_t *fill_bars_rgb(uint8_t *p, unsigned w, unsigned h,
+ format_type_t order, int bpp)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+ packed_t rgb;
+
+ unsigned headlen = y0 * w * bpp / 8;
+ memset(p, 0xff, headlen);
+ uint32_t *q = (uint32_t *)(p + headlen);
+
+ for (y = y0; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ /* FIXME clean this up... */
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ unsigned yi = (i & 1) ? y : h - y;
+ unsigned v1, v0;
+ if (yi < h / 2 - 1) {
+ v1 = ((yi * 0x180) + h - 1) / h + 0x40;
+ v0 = 0x00;
+ } else {
+ v1 = 0xff;
+ v0 = (((yi - (h / 2)) * 0x180) + h - 1) / h + 0x40;
+ }
+
+ uint8_t r = (i & 4) ? v1 : v0;
+ uint8_t g = (i & 2) ? v1 : v0;
+ uint8_t b = (i & 1) ? v1 : v0;
+ if (bpp == 32) {
+ if (order == RGB888) {
+ rgb.u8[0] = 0xff;
+ rgb.u8[1] = r;
+ rgb.u8[2] = g;
+ rgb.u8[3] = b;
+ } else {
+ rgb.u8[0] = b;
+ rgb.u8[1] = g;
+ rgb.u8[2] = r;
+ rgb.u8[3] = 0xff;
+ }
+ for (; x < x0; x++)
+ *(q++) = rgb.u32[0];
+ } else if (bpp == 24) {
+ rgb.u8[0] = rgb.u8[3] = rgb.u8[6] = rgb.u8[9] =
+ (order == RGB888) ? r : b;
+ rgb.u8[1] = rgb.u8[4] = rgb.u8[7] = rgb.u8[10] = g;
+ rgb.u8[2] = rgb.u8[5] = rgb.u8[8] = rgb.u8[11] =
+ (order == RGB888) ? b : r;
+ for (; x < x0; x += 4) {
+ *(q++) = rgb.u32[0];
+ *(q++) = rgb.u32[1];
+ *(q++) = rgb.u32[2];
+ }
+ } else {
+ assert(bpp == 16);
+ r = ((r + 7) / 8) & 0x1f;
+ b = ((b + 7) / 8) & 0x1f;
+ if ((order & 0x0fff) == 0x0555) {
+ g = ((g + 7) / 8) & 0x1f;
+ rgb.u16[0] = b | (g << 5) | (r << 10);
+ } else {
+ g = ((g + 3) / 4) & 0x3f;
+ rgb.u16[0] = b | (g << 5) | (r << 11);
+ }
+ if (order & 0x1000)
+ rgb.u16[0] = (rgb.u16[0] >> 8) | (rgb.u16[0] << 8);
+ rgb.u16[1] = rgb.u16[0];
+ for (; x < x0; x += 2)
+ *(q++) = rgb.u32[0];
+ }
+ }
+
+ memset(q, 0xff, headlen);
+ return (((uint8_t *)q) + headlen);
+}
+
+int test_image_bars(zbar_image_t *img)
+{
+ const format_def_t *fmt = alloc_data(img);
+ if (!fmt)
+ return (-1);
+
+ unsigned w = zbar_image_get_width(img);
+ unsigned h = zbar_image_get_height(img);
+ uint8_t *data = (void *)zbar_image_get_data(img);
+ assert(data);
+ uint8_t *p = data;
+ switch (fmt->type) {
+ case GRAY:
+ case YUVP: /* planar YUV */
+ case YVUP:
+ p = fill_bars_y(p, w, h);
+ if (fmt->type != GRAY) {
+ w = (w + fmt->xdiv - 1) / fmt->xdiv;
+ h = (h + fmt->ydiv - 1) / fmt->ydiv;
+ } else
+ break;
+
+ if (fmt->format == fourcc('N', 'V', '1', '2') ||
+ fmt->format == fourcc('N', 'V', '2', '1'))
+ p = fill_bars_nv(p, w, h, fmt->type);
+ else if (fmt->type == YUVP || fmt->type == YVUP) {
+ p = fill_bars_uv(p, w, h, (fmt->type == YUVP) ? Cb : Cr);
+ p = fill_bars_uv(p, w, h, (fmt->type == YUVP) ? Cr : Cb);
+ }
+ break;
+
+ case YUYV: /* packed YUV */
+ case YVYU:
+ case UYVY:
+ p = fill_bars_yuv(p, w, h, fmt->type);
+ break;
+
+ default: /* RGB */
+ p = fill_bars_rgb(p, w, h, fmt->type, fmt->bpp);
+ break;
+ }
+
+ assert(p == data + zbar_image_get_data_length(img));
+ return (0);
+}
+
+int test_image_ean13(zbar_image_t *img)
+{
+ unsigned w = 114, h = 85;
+ zbar_image_set_size(img, w, h);
+
+ const format_def_t *fmt = alloc_data(img);
+ if (!fmt)
+ return (-1);
+
+ uint8_t *data = (void *)zbar_image_get_data(img);
+ unsigned int datalen = zbar_image_get_data_length(img);
+ assert(data && datalen);
+
+ uint8_t *p = data;
+ /* FIXME randomize? */
+ memset(data, 0x80, datalen);
+
+ int nrep = 1, nskip = 0;
+ switch (fmt->type) {
+ case YUVP: /* planar YUV */
+ case YVUP:
+ case GRAY:
+ break;
+
+ case UYVY: /* packed YUV */
+ p++;
+ case YUYV:
+ case YVYU:
+ nskip = 1;
+ break;
+
+ default: /* RGB */
+ nrep = fmt->bpp / 8;
+ }
+
+ int y = 0, x, i;
+ for (; y < 10 && y < h; y++)
+ for (x = 0; x < w; x++) {
+ for (i = 0; i < nrep; i++)
+ *p++ = 0xff;
+ p += nskip;
+ }
+
+ for (; y < h - 10; y++) {
+ uint8_t color = 0xff;
+ const char *c;
+ for (x = 0, c = encoded_widths; *c; c++) {
+ int dx;
+ if (*c == ' ')
+ continue;
+ for (dx = *c - '0'; dx > 0; dx--) {
+ for (i = 0; i < nrep; i++)
+ *p++ = color;
+ p += nskip;
+ x++;
+ }
+ color = ~color;
+ }
+ assert(!color);
+ for (; x < w; x++) {
+ for (i = 0; i < nrep; i++)
+ *p++ = 0xff;
+ p += nskip;
+ }
+ assert(x == w);
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++) {
+ for (i = 0; i < nrep; i++)
+ *p++ = 0xff;
+ p += nskip;
+ }
+
+ if (fmt->type == UYVY)
+ p--;
+ assert(p == data + datalen);
+ return (0);
+}