From bd473e9df2a330b988b43e766318b01b58761cbd Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Wed, 9 Jan 2013 15:52:56 +0100 Subject: [PATCH] Added autoconf/automake scripts so support for decoding large images (i.e. an increased max. number of regions) in the library can be enabled at compile time. The samples don't support this yet. --- .gitignore | 10 +++++ Makefile | 93 ------------------------------------------- Makefile.am | 52 ++++++++++++++++++++++++ autogen.sh | 15 +++++++ configure.ac | 44 ++++++++++++++++++++ demo/camera.c | 8 ++++ lib/identify.c | 27 ++++++------- lib/quirc.c | 11 +---- lib/quirc.h | 15 +++++-- lib/quirc_internal.h | 10 +++-- m4/empty.dir | 1 + make-quirc-config.sed | 23 +++++++++++ 12 files changed, 186 insertions(+), 123 deletions(-) delete mode 100644 Makefile create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 m4/empty.dir create mode 100644 make-quirc-config.sed diff --git a/.gitignore b/.gitignore index e2b34bf..4d0ac0e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,13 @@ libquirc.a libquirc.so .*.swp *~ +.libs +.deps +.dirstamp +Makefile +Makefile.in +*.m4 +*.la +quirc-config.h +config.h +configure \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 455d6a8..0000000 --- a/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -# quirc -- QR-code recognition library -# Copyright (C) 2010-2012 Daniel Beer -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -CC ?= gcc -PREFIX ?= /usr/local -SDL_CFLAGS := $(shell pkg-config --cflags sdl) -SDL_LIBS := $(shell pkg-config --libs sdl) - -LIB_VERSION = 1.0 -LIB_SONAME = libquirc.so.1 - -QUIRC_CFLAGS = -O3 -Wall -Ilib $(CFLAGS) $(SDL_CFLAGS) -LIB_OBJ = \ - lib/decode.o \ - lib/identify.o \ - lib/quirc.o \ - lib/version_db.o -LIB_SOBJ = $(subst .o,.lo,$(LIB_OBJ)) -DEMO_OBJ = \ - demo/camera.o \ - demo/mjpeg.o \ - demo/convert.o \ - demo/dthash.o \ - demo/demoutil.o - -all: libquirc.so qrtest inspect quirc-demo quirc-scanner - -qrtest: tests/dbgutil.o tests/qrtest.o libquirc.a - $(CC) -o $@ $^ -lm -ljpeg - -inspect: tests/dbgutil.o tests/inspect.o libquirc.a - $(CC) -o $@ $^ -lm -ljpeg $(SDL_LIBS) -lSDL_gfx - -quirc-demo: $(DEMO_OBJ) demo/demo.o libquirc.a - $(CC) -o $@ $^ -lm -ljpeg $(SDL_LIBS) -lSDL_gfx - -quirc-scanner: $(DEMO_OBJ) demo/scanner.o libquirc.a - $(CC) -o $@ $^ -lm -ljpeg - -libquirc.a: $(LIB_OBJ) - rm -f $@ - ar cru $@ $^ - ranlib $@ - -libquirc.so: $(LIB_SOBJ) - $(CC) -shared -Wl,-soname=$(LIB_SONAME) -o $@ $^ -lm - -%.o: %.c - $(CC) $(QUIRC_CFLAGS) -o $*.o -c $*.c - -%.lo: %.c - $(CC) -fPIC $(QUIRC_CFLAGS) -o $*.lo -c $*.c - -install: libquirc.a libquirc.so quirc-demo quirc-scanner - install -o root -g root -m 0644 lib/quirc.h $(DESTDIR)$(PREFIX)/include - install -o root -g root -m 0644 libquirc.a $(DESTDIR)$(PREFIX)/lib - install -o root -g root -m 0755 libquirc.so \ - $(DESTDIR)$(PREFIX)/lib/libquirc.so.$(LIB_VERSION) - ln -sf libquirc.so.$(LIB_VERSION) $(DESTDIR)$(PREFIX)/lib/$(LIB_SONAME) - ln -sf libquirc.so.$(LIB_VERSION) $(DESTDIR)$(PREFIX)/lib/libquirc.so - install -o root -g root -m 0755 quirc-demo $(DESTDIR)$(PREFIX)/bin - install -o root -g root -m 0755 quirc-scanner $(DESTDIR)$(PREFIX)/bin - -uninstall: - rm -f $(DESTDIR)$(PREFIX)/include/quirc.h - rm -f $(DESTDIR)$(PREFIX)/lib/libquirc.so.$(LIB_VERSION) - rm -f $(DESTDIR)$(PREFIX)/lib/$(LIB_SONAME) - rm -f $(DESTDIR)$(PREFIX)/lib/libquirc.so - rm -f $(DESTDIR)$(PREFIX)/lib/libquirc.a - rm -f $(DESTDIR)$(PREFIX)/bin/quirc-demo - rm -f $(DESTDIR)$(PREFIX)/bin/quirc-scanner - -clean: - rm -f */*.o - rm -f */*.lo - rm -f libquirc.a - rm -f libquirc.so - rm -f qrtest - rm -f inspect - rm -f quirc-demo - rm -f quirc-scanner diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..71433ae --- /dev/null +++ b/Makefile.am @@ -0,0 +1,52 @@ +AUTOMAKE_OPTIONS = foreign subdir-objects + +ACLOCAL_AMFLAGS = -I m4 + +VERSION_INFO = 1:0:0 + +lib_LTLIBRARIES = libquirc.la +BUILT_SOURCES = lib/quirc-config.h +lib/quirc-config.h: config.h make-quirc-config.sed + $(AM_V_at)$(SED) -f $(srcdir)/make-quirc-config.sed < config.h > $@T + $(AM_V_at)mv -f $@T $@ + +include_HEADERS = lib/quirc.h \ + lib/quirc-config.h + +libquirc_la_SOURCES = lib/decode.c \ + lib/identify.c \ + lib/quirc.c \ + lib/version_db.c +libquirc_la_LIBADD = $(SYS_LIBS) +libquirc_la_LDFLAGS = -version-info $(VERSION_INFO) + +bin_PROGRAMS = quirc-demo \ + quirc-scanner + +noinst_PROGRAMS = qrtest \ + inspect + +DEMO_SOURCES = \ + demo/camera.c \ + demo/mjpeg.c \ + demo/convert.c \ + demo/dthash.c \ + demo/demoutil.c + +qrtest_SOURCES = tests/dbgutil.c tests/qrtest.c +qrtest_LDADD = libquirc.a -ljpeg + +inspect_SOURCES = tests/dbgutil.c tests/inspect.c +inspect_CFLAGS = $(sdl_CFLAGS) +inspect_LDADD = libquirc.a -ljpeg $(sdl_LIBS) -lSDL_gfx + +quirc_demo_SOURCES = $(DEMO_SOURCES) tests/dbgutil.c demo/demo.c +quirc_demo_CFLAGS = $(sdl_CFLAGS) +quirc_demo_LDADD = libquirc.a -ljpeg $(sdl_LIBS) -lSDL_gfx + +quirc_scanner_SOURCES = $(DEMO_SOURCES) tests/dbgutil.c demo/scanner.c +quirc_scanner_LDADD = libquirc.a -ljpeg + +AM_CPPFLAGS = -I$(srcdir)/lib $(SYS_INCLUDES) + +DISTCLEANFILES = ./lib/quirc-config.h diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..57eeb94 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,15 @@ +#!/bin/sh +if [ -x "`which autoreconf 2>/dev/null`" ] ; then + exec autoreconf -ivf +fi + +LIBTOOLIZE=libtoolize +SYSNAME=`uname` +if [ "x$SYSNAME" = "xDarwin" ] ; then + LIBTOOLIZE=glibtoolize +fi +aclocal -I m4 && \ + autoheader && \ + $LIBTOOLIZE && \ + autoconf && \ + automake --add-missing --force-missing --copy diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..4801486 --- /dev/null +++ b/configure.ac @@ -0,0 +1,44 @@ +AC_INIT([quirc], [1.0], [https://github.com/dlbeer/quirc/issues], [quirc], [https://github.com/dlbeer/quirc]) +AC_CONFIG_MACRO_DIR([m4]) +AM_CONFIG_HEADER(config.h:config.in) +AM_INIT_AUTOMAKE +dnl AM_SILENT_RULES req. automake 1.11. [no] defaults V=1 +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST + +PKG_PROG_PKG_CONFIG +AC_EXEEXT +AC_PROG_CC +AC_PROG_CPP +AC_PROG_LIBTOOL +AC_PROG_SED +AC_PROG_INSTALL +AC_PROG_LN_S + +AC_HEADER_STDC + +PKG_CHECK_MODULES(sdl, sdl) +AC_SUBST(sdl_CFLAGS) +AC_SUBST(sdl_LIBS) + +AC_CHECK_HEADERS(setjmp.h jpeglib.h) +AC_CHECK_HEADERS(linux/videodev2.h linux/videodev.h) +AC_SEARCH_LIBS([rint], [m]) + +AC_ARG_ENABLE(large-images, + [ --enable-large-images enable decoding of large images], + [large_images=true], + [large_images=false]) + +AC_MSG_CHECKING(whether to support decoding lage images) +if test "x$large_images" = "xtrue"; then + AC_DEFINE(DECODE_LARGE_IMAGES, 1, [Define if decoding of large images is enabled]) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/demo/camera.c b/demo/camera.c index 56b524e..bf86db8 100644 --- a/demo/camera.c +++ b/demo/camera.c @@ -14,6 +14,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -21,7 +25,11 @@ #include #include #include +#ifdef HAVE_LINUX_VIDEODEV2_H +#include +#else #include +#endif #include "camera.h" diff --git a/lib/identify.c b/lib/identify.c index d310d46..987908c 100644 --- a/lib/identify.c +++ b/lib/identify.c @@ -132,7 +132,7 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to, int left = x; int right = x; int i; - int *row = q->region_info + y * q->w; + quirc_pixel_t *row = q->image + y * q->w; if (depth >= FLOOD_FILL_MAX_DEPTH) return; @@ -152,7 +152,7 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to, /* Seed new flood-fills */ if (y > 0) { - row = q->region_info + (y - 1) * q->w; + row = q->image + (y - 1) * q->w; for (i = left; i <= right; i++) if (row[i] == from) @@ -161,7 +161,7 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to, } if (y < q->h - 1) { - row = q->region_info + (y + 1) * q->w; + row = q->image + (y + 1) * q->w; for (i = left; i <= right; i++) if (row[i] == from) @@ -183,7 +183,7 @@ static void threshold(struct quirc *q) int avg_w = 0; int avg_u = 0; int threshold_s = q->w / THRESHOLD_S_DEN; - int *row = q->region_info; + quirc_pixel_t *row = q->image; for (y = 0; y < q->h; y++) { int row_average[q->w]; @@ -229,14 +229,14 @@ static void area_count(void *user_data, int y, int left, int right) static int region_code(struct quirc *q, int x, int y) { - int pixel; + quirc_pixel_t pixel; struct quirc_region *box; int region; if (x < 0 || y < 0 || x >= q->w || y >= q->h) return -1; - pixel = q->region_info[y * q->w + x]; + pixel = q->image[y * q->w + x]; if (pixel >= QUIRC_PIXEL_REGION) return pixel; @@ -415,7 +415,7 @@ static void test_capstone(struct quirc *q, int x, int y, int *pb) static void finder_scan(struct quirc *q, int y) { - int *row = q->region_info + y * q->w; + quirc_pixel_t *row = q->image + y * q->w; int x; int last_color; int run_length = 0; @@ -587,12 +587,12 @@ static int timing_scan(const struct quirc *q, x = p0->x; y = p0->y; for (i = 0; i <= d; i++) { - int pixel; + quirc_pixel_t pixel; if (y < 0 || y >= q->h || x < 0 || x >= q->w) break; - pixel = q->region_info[y * q->w + x]; + pixel = q->image[y * q->w + x]; if (pixel) { if (run_length >= 2) @@ -670,7 +670,7 @@ static int read_cell(const struct quirc *q, int index, int x, int y) if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w) return 0; - return q->region_info[p.y * q->w + p.x] ? 1 : -1; + return q->image[p.y * q->w + p.x] ? 1 : -1; } static int fitness_cell(const struct quirc *q, int index, int x, int y) @@ -689,7 +689,7 @@ static int fitness_cell(const struct quirc *q, int index, int x, int y) if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w) continue; - if (q->region_info[p.y * q->w + p.x]) + if (q->image[p.y * q->w + p.x]) score++; else score--; @@ -1066,7 +1066,7 @@ static void test_grouping(struct quirc *q, int i) test_neighbours(q, i, &hlist, &vlist); } -uint8_t *quirc_begin(struct quirc *q, int *w, int *h) +quirc_pixel_t *quirc_begin(struct quirc *q, int *w, int *h) { q->num_regions = QUIRC_PIXEL_REGION; q->num_capstones = 0; @@ -1084,9 +1084,6 @@ void quirc_end(struct quirc *q) { int i; - for (i = 0; i < q->w*q->h; i++) - q->region_info[i] = q->image[i]; - threshold(q); for (i = 0; i < q->h; i++) diff --git a/lib/quirc.c b/lib/quirc.c index 1d46bfa..fb7592e 100644 --- a/lib/quirc.c +++ b/lib/quirc.c @@ -38,25 +38,18 @@ void quirc_destroy(struct quirc *q) { if (q->image) free(q->image); - if (q->region_info) - free(q->region_info); free(q); } int quirc_resize(struct quirc *q, int w, int h) { - uint8_t *new_image = realloc(q->image, w * h); - int *new_region_info = realloc(q->region_info, w * h * sizeof(int)); + quirc_pixel_t *new_image = realloc(q->image, w * h * sizeof(quirc_pixel_t)); - if (!new_image || !new_region_info) { - free(new_image); - free(new_region_info); + if (!new_image) return -1; - } q->image = new_image; - q->region_info = new_region_info; q->w = w; q->h = h; diff --git a/lib/quirc.h b/lib/quirc.h index 1932047..8a6e4af 100644 --- a/lib/quirc.h +++ b/lib/quirc.h @@ -19,6 +19,14 @@ #include +#include + +#ifdef QUIRC__DECODE_LARGE_IMAGES +typedef uint16_t quirc_pixel_t; +#else +typedef uint8_t quirc_pixel_t; +#endif + struct quirc; /* Obtain the library version string. */ @@ -42,14 +50,15 @@ int quirc_resize(struct quirc *q, int w, int h); /* These functions are used to process images for QR-code recognition. * quirc_begin() must first be called to obtain access to a buffer into - * which the input image should be placed. Optionally, the current - * width and height may be returned. + * which the input image should be placed. Values between 0x00 and 0xff + * must be used to store the grayscale level. + * Optionally, the current width and height may be returned. * * After filling the buffer, quirc_end() should be called to process * the image for QR-code recognition. The locations and content of each * code may be obtained using accessor functions described below. */ -uint8_t *quirc_begin(struct quirc *q, int *w, int *h); +quirc_pixel_t *quirc_begin(struct quirc *q, int *w, int *h); void quirc_end(struct quirc *q); /* This structure describes a location in the input image buffer. */ diff --git a/lib/quirc_internal.h b/lib/quirc_internal.h index 1aa9988..836890d 100644 --- a/lib/quirc_internal.h +++ b/lib/quirc_internal.h @@ -18,12 +18,17 @@ #define QUIRC_INTERNAL_H_ #include "quirc.h" +#include "quirc-config.h" #define QUIRC_PIXEL_WHITE 0 #define QUIRC_PIXEL_BLACK 1 #define QUIRC_PIXEL_REGION 2 -#define QUIRC_MAX_REGIONS 2048 +#ifdef QUIRC__DECODE_LARGE_IMAGES +#define QUIRC_MAX_REGIONS 65534 +#else +#define QUIRC_MAX_REGIONS 254 +#endif #define QUIRC_MAX_CAPSTONES 32 #define QUIRC_MAX_GRIDS 8 @@ -65,8 +70,7 @@ struct quirc_grid { }; struct quirc { - uint8_t *image; - int *region_info; + quirc_pixel_t *image; int w; int h; diff --git a/m4/empty.dir b/m4/empty.dir new file mode 100644 index 0000000..c9b9583 --- /dev/null +++ b/m4/empty.dir @@ -0,0 +1 @@ +## empty directory diff --git a/make-quirc-config.sed b/make-quirc-config.sed new file mode 100644 index 0000000..e32f63f --- /dev/null +++ b/make-quirc-config.sed @@ -0,0 +1,23 @@ +# Sed script to postprocess config.h into quirc-config.h. + +1i\ +/* quirc-config.h\ + *\ + * This file was generated by autoconf when quirc was built, and post-\ + * processed by quirc so that its macros would have a uniform prefix.\ + *\ + * DO NOT EDIT THIS FILE.\ + *\ + * Do not rely on macros in this file existing in later versions.\ + */\ +\ +#ifndef QUIRC_CONFIG_H_INCLUDED_\ +#define QUIRC_CONFIG_H_INCLUDED_\ + +$a\ +\ +#endif /* quirc-config.h */ + +s/#\( *\)define /#\1define QUIRC__/ +s/#\( *\)undef /#\1undef QUIRC__/ +s/#\( *\)if\(n*\)def /#\1if\2def QUIRC__/