diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 00:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 00:06:44 +0000 |
commit | 44cf8ec67278bd1ab6c7f83a9993f7a5686a9541 (patch) | |
tree | 5eec4b0d1a3f163d279c3c27c03324ba49fa235a /test/test_images.c | |
parent | Initial commit. (diff) | |
download | zbar-44cf8ec67278bd1ab6c7f83a9993f7a5686a9541.tar.xz zbar-44cf8ec67278bd1ab6c7f83a9993f7a5686a9541.zip |
Adding upstream version 0.23.93.upstream/0.23.93upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/test_images.c')
-rw-r--r-- | test/test_images.c | 533 |
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); +} |