summaryrefslogtreecommitdiffstats
path: root/zbar/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'zbar/image.c')
-rw-r--r--zbar/image.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/zbar/image.c b/zbar/image.c
new file mode 100644
index 0000000..82aeeb8
--- /dev/null
+++ b/zbar/image.c
@@ -0,0 +1,342 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2010 (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"
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "error.h"
+#include "image.h"
+#include "refcnt.h"
+
+zbar_image_t *zbar_image_create()
+{
+ zbar_image_t *img = calloc(1, sizeof(zbar_image_t));
+ _zbar_refcnt_init();
+ _zbar_image_refcnt(img, 1);
+ img->srcidx = -1;
+ return (img);
+}
+
+void _zbar_image_free(zbar_image_t *img)
+{
+ if (img->syms) {
+ zbar_symbol_set_ref(img->syms, -1);
+ img->syms = NULL;
+ }
+ free(img);
+}
+
+void zbar_image_destroy(zbar_image_t *img)
+{
+ _zbar_image_refcnt(img, -1);
+}
+
+void zbar_image_ref(zbar_image_t *img, int refs)
+{
+ _zbar_image_refcnt(img, refs);
+}
+
+unsigned long zbar_image_get_format(const zbar_image_t *img)
+{
+ return (img->format);
+}
+
+unsigned zbar_image_get_sequence(const zbar_image_t *img)
+{
+ return (img->seq);
+}
+
+unsigned zbar_image_get_width(const zbar_image_t *img)
+{
+ return (img->width);
+}
+
+unsigned zbar_image_get_height(const zbar_image_t *img)
+{
+ return (img->height);
+}
+
+void zbar_image_get_size(const zbar_image_t *img, unsigned *w, unsigned *h)
+{
+ if (w)
+ *w = img->width;
+ if (h)
+ *h = img->height;
+}
+
+void zbar_image_get_crop(const zbar_image_t *img, unsigned *x, unsigned *y,
+ unsigned *w, unsigned *h)
+{
+ if (x)
+ *x = img->crop_x;
+ if (y)
+ *y = img->crop_y;
+ if (w)
+ *w = img->crop_w;
+ if (h)
+ *h = img->crop_h;
+}
+
+const void *zbar_image_get_data(const zbar_image_t *img)
+{
+ return (img->data);
+}
+
+unsigned long zbar_image_get_data_length(const zbar_image_t *img)
+{
+ return (img->datalen);
+}
+
+void zbar_image_set_format(zbar_image_t *img, unsigned long fmt)
+{
+ img->format = fmt;
+}
+
+void zbar_image_set_sequence(zbar_image_t *img, unsigned seq)
+{
+ img->seq = seq;
+}
+
+void zbar_image_set_size(zbar_image_t *img, unsigned w, unsigned h)
+{
+ img->crop_x = img->crop_y = 0;
+ img->width = img->crop_w = w;
+ img->height = img->crop_h = h;
+}
+
+void zbar_image_set_crop(zbar_image_t *img, unsigned x, unsigned y, unsigned w,
+ unsigned h)
+{
+ unsigned img_h;
+ unsigned img_w = img->width;
+ if (x > img_w)
+ x = img_w;
+ if (x + w > img_w)
+ w = img_w - x;
+ img->crop_x = x;
+ img->crop_w = w;
+
+ img_h = img->height;
+ if (y > img_h)
+ y = img_h;
+ if (y + h > img_h)
+ h = img_h - y;
+ img->crop_y = y;
+ img->crop_h = h;
+}
+
+inline void zbar_image_free_data(zbar_image_t *img)
+{
+ if (!img)
+ return;
+ if (img->src) {
+ zbar_image_t *newimg;
+ /* replace video image w/new copy */
+ assert(img->refcnt); /* FIXME needs lock */
+ newimg = zbar_image_create();
+ memcpy(newimg, img, sizeof(zbar_image_t));
+ /* recycle video image */
+ newimg->cleanup(newimg);
+ /* detach old image from src */
+ img->cleanup = NULL;
+ img->src = NULL;
+ img->srcidx = -1;
+ } else if (img->cleanup && img->data) {
+ if (img->cleanup != zbar_image_free_data) {
+ /* using function address to detect this case is a bad idea;
+ * windows link libraries add an extra layer of indirection...
+ * this works around that problem (bug #2796277)
+ */
+ zbar_image_cleanup_handler_t *cleanup = img->cleanup;
+ img->cleanup = zbar_image_free_data;
+ cleanup(img);
+ } else
+ free((void *)img->data);
+ }
+ img->data = NULL;
+}
+
+void zbar_image_set_data(zbar_image_t *img, const void *data, unsigned long len,
+ zbar_image_cleanup_handler_t *cleanup)
+{
+ zbar_image_free_data(img);
+ img->data = data;
+ img->datalen = len;
+ img->cleanup = cleanup;
+}
+
+void zbar_image_set_userdata(zbar_image_t *img, void *userdata)
+{
+ img->userdata = userdata;
+}
+
+void *zbar_image_get_userdata(const zbar_image_t *img)
+{
+ return (img->userdata);
+}
+
+zbar_image_t *zbar_image_copy(const zbar_image_t *src)
+{
+ return _zbar_image_copy(src, 0);
+}
+
+const zbar_symbol_set_t *zbar_image_get_symbols(const zbar_image_t *img)
+{
+ return (img->syms);
+}
+
+void zbar_image_set_symbols(zbar_image_t *img, const zbar_symbol_set_t *syms)
+{
+ if (syms)
+ zbar_symbol_set_ref(syms, 1);
+ if (img->syms)
+ zbar_symbol_set_ref(img->syms, -1);
+ img->syms = (zbar_symbol_set_t *)syms;
+}
+
+const zbar_symbol_t *zbar_image_first_symbol(const zbar_image_t *img)
+{
+ return ((img->syms) ? img->syms->head : NULL);
+}
+
+typedef struct zimg_hdr_s {
+ uint32_t magic, format;
+ uint16_t width, height;
+ uint32_t size;
+} zimg_hdr_t;
+
+int zbar_image_write(const zbar_image_t *img, const char *filebase)
+{
+ int len = strlen(filebase) + 16;
+ char *filename = malloc(len);
+ int n = 0, rc = 0;
+ FILE *f;
+ zimg_hdr_t hdr;
+ strcpy(filename, filebase);
+ if ((img->format & 0xff) >= ' ')
+ n = snprintf(filename, len, "%s.%.4s.zimg", filebase,
+ (char *)&img->format);
+ else
+ n = snprintf(filename, len, "%s.%08" PRIx32 ".zimg", filebase,
+ img->format);
+ assert(n < len - 1);
+ filename[len - 1] = '\0';
+
+ zprintf(1, "dumping %.4s(%08" PRIx32 ") image to %s\n",
+ (char *)&img->format, img->format, filename);
+
+ f = fopen(filename, "w");
+ if (!f) {
+#ifdef HAVE_ERRNO_H
+ rc = errno;
+ zprintf(1, "ERROR opening %s: %s\n", filename, strerror(rc));
+#else
+ rc = 1;
+#endif
+ goto error;
+ }
+
+ hdr.magic = 0x676d697a;
+ hdr.format = img->format;
+ hdr.width = img->width;
+ hdr.height = img->height;
+ hdr.size = img->datalen;
+
+ if (fwrite(&hdr, sizeof(hdr), 1, f) != 1 ||
+ fwrite(img->data, 1, img->datalen, f) != img->datalen) {
+#ifdef HAVE_ERRNO_H
+ rc = errno;
+ zprintf(1, "ERROR writing %s: %s\n", filename, strerror(rc));
+#else
+ rc = 1;
+#endif
+ fclose(f);
+ goto error;
+ }
+
+ rc = fclose(f);
+
+error:
+ free(filename);
+ return (rc);
+}
+
+#ifdef DEBUG_SVG
+#include <png.h>
+
+int zbar_image_write_png(const zbar_image_t *img, const char *filename)
+{
+ int rc = -1;
+ FILE *file = NULL;
+ png_struct *png = NULL;
+ png_info *info = NULL;
+ const uint8_t **rows = NULL;
+
+ rows = malloc(img->height * sizeof(*rows));
+ if (!rows)
+ goto done;
+
+ rows[0] = img->data;
+ int y;
+ for (y = 1; y < img->height; y++)
+ rows[y] = rows[y - 1] + img->width;
+
+ file = fopen(filename, "wb");
+ if (!file)
+ goto done;
+
+ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png)
+ goto done;
+
+ info = png_create_info_struct(png);
+ if (!info)
+ goto done;
+
+ if (setjmp(png_jmpbuf(png)))
+ goto done;
+
+ png_init_io(png, file);
+ png_set_compression_level(png, 9);
+ png_set_IHDR(png, info, img->width, img->height, 8, PNG_COLOR_TYPE_GRAY,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+
+ png_set_rows(png, info, (void *)rows);
+ png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
+
+ png_write_end(png, info);
+ rc = 0;
+
+done:
+ if (png)
+ png_destroy_write_struct(&png, &info);
+ if (rows)
+ free(rows);
+ if (file)
+ fclose(file);
+ return (rc);
+}
+
+#endif