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.

This commit is contained in:
Joachim Bauch 2013-01-09 15:52:56 +01:00
parent 74b72a89a4
commit bd473e9df2
12 changed files with 186 additions and 123 deletions

10
.gitignore vendored
View file

@ -8,3 +8,13 @@ libquirc.a
libquirc.so libquirc.so
.*.swp .*.swp
*~ *~
.libs
.deps
.dirstamp
Makefile
Makefile.in
*.m4
*.la
quirc-config.h
config.h
configure

View file

@ -1,93 +0,0 @@
# quirc -- QR-code recognition library
# Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>
#
# 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

52
Makefile.am Normal file
View file

@ -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

15
autogen.sh Executable file
View file

@ -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

44
configure.ac Normal file
View file

@ -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

View file

@ -14,6 +14,10 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@ -21,7 +25,11 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#ifdef HAVE_LINUX_VIDEODEV2_H
#include <linux/videodev2.h>
#else
#include <linux/videodev.h> #include <linux/videodev.h>
#endif
#include "camera.h" #include "camera.h"

View file

@ -132,7 +132,7 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to,
int left = x; int left = x;
int right = x; int right = x;
int i; 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) if (depth >= FLOOD_FILL_MAX_DEPTH)
return; 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 */ /* Seed new flood-fills */
if (y > 0) { if (y > 0) {
row = q->region_info + (y - 1) * q->w; row = q->image + (y - 1) * q->w;
for (i = left; i <= right; i++) for (i = left; i <= right; i++)
if (row[i] == from) 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) { 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++) for (i = left; i <= right; i++)
if (row[i] == from) if (row[i] == from)
@ -183,7 +183,7 @@ static void threshold(struct quirc *q)
int avg_w = 0; int avg_w = 0;
int avg_u = 0; int avg_u = 0;
int threshold_s = q->w / THRESHOLD_S_DEN; 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++) { for (y = 0; y < q->h; y++) {
int row_average[q->w]; 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) static int region_code(struct quirc *q, int x, int y)
{ {
int pixel; quirc_pixel_t pixel;
struct quirc_region *box; struct quirc_region *box;
int region; int region;
if (x < 0 || y < 0 || x >= q->w || y >= q->h) if (x < 0 || y < 0 || x >= q->w || y >= q->h)
return -1; return -1;
pixel = q->region_info[y * q->w + x]; pixel = q->image[y * q->w + x];
if (pixel >= QUIRC_PIXEL_REGION) if (pixel >= QUIRC_PIXEL_REGION)
return pixel; 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) 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 x;
int last_color; int last_color;
int run_length = 0; int run_length = 0;
@ -587,12 +587,12 @@ static int timing_scan(const struct quirc *q,
x = p0->x; x = p0->x;
y = p0->y; y = p0->y;
for (i = 0; i <= d; i++) { for (i = 0; i <= d; i++) {
int pixel; quirc_pixel_t pixel;
if (y < 0 || y >= q->h || x < 0 || x >= q->w) if (y < 0 || y >= q->h || x < 0 || x >= q->w)
break; break;
pixel = q->region_info[y * q->w + x]; pixel = q->image[y * q->w + x];
if (pixel) { if (pixel) {
if (run_length >= 2) 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) if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w)
return 0; 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) 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) if (p.y < 0 || p.y >= q->h || p.x < 0 || p.x >= q->w)
continue; continue;
if (q->region_info[p.y * q->w + p.x]) if (q->image[p.y * q->w + p.x])
score++; score++;
else else
score--; score--;
@ -1066,7 +1066,7 @@ static void test_grouping(struct quirc *q, int i)
test_neighbours(q, i, &hlist, &vlist); 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_regions = QUIRC_PIXEL_REGION;
q->num_capstones = 0; q->num_capstones = 0;
@ -1084,9 +1084,6 @@ void quirc_end(struct quirc *q)
{ {
int i; int i;
for (i = 0; i < q->w*q->h; i++)
q->region_info[i] = q->image[i];
threshold(q); threshold(q);
for (i = 0; i < q->h; i++) for (i = 0; i < q->h; i++)

View file

@ -38,25 +38,18 @@ void quirc_destroy(struct quirc *q)
{ {
if (q->image) if (q->image)
free(q->image); free(q->image);
if (q->region_info)
free(q->region_info);
free(q); free(q);
} }
int quirc_resize(struct quirc *q, int w, int h) int quirc_resize(struct quirc *q, int w, int h)
{ {
uint8_t *new_image = realloc(q->image, w * h); quirc_pixel_t *new_image = realloc(q->image, w * h * sizeof(quirc_pixel_t));
int *new_region_info = realloc(q->region_info, w * h * sizeof(int));
if (!new_image || !new_region_info) { if (!new_image)
free(new_image);
free(new_region_info);
return -1; return -1;
}
q->image = new_image; q->image = new_image;
q->region_info = new_region_info;
q->w = w; q->w = w;
q->h = h; q->h = h;

View file

@ -19,6 +19,14 @@
#include <stdint.h> #include <stdint.h>
#include <quirc-config.h>
#ifdef QUIRC__DECODE_LARGE_IMAGES
typedef uint16_t quirc_pixel_t;
#else
typedef uint8_t quirc_pixel_t;
#endif
struct quirc; struct quirc;
/* Obtain the library version string. */ /* 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. /* These functions are used to process images for QR-code recognition.
* quirc_begin() must first be called to obtain access to a buffer into * quirc_begin() must first be called to obtain access to a buffer into
* which the input image should be placed. Optionally, the current * which the input image should be placed. Values between 0x00 and 0xff
* width and height may be returned. * 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 * After filling the buffer, quirc_end() should be called to process
* the image for QR-code recognition. The locations and content of each * the image for QR-code recognition. The locations and content of each
* code may be obtained using accessor functions described below. * 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); void quirc_end(struct quirc *q);
/* This structure describes a location in the input image buffer. */ /* This structure describes a location in the input image buffer. */

View file

@ -18,12 +18,17 @@
#define QUIRC_INTERNAL_H_ #define QUIRC_INTERNAL_H_
#include "quirc.h" #include "quirc.h"
#include "quirc-config.h"
#define QUIRC_PIXEL_WHITE 0 #define QUIRC_PIXEL_WHITE 0
#define QUIRC_PIXEL_BLACK 1 #define QUIRC_PIXEL_BLACK 1
#define QUIRC_PIXEL_REGION 2 #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_CAPSTONES 32
#define QUIRC_MAX_GRIDS 8 #define QUIRC_MAX_GRIDS 8
@ -65,8 +70,7 @@ struct quirc_grid {
}; };
struct quirc { struct quirc {
uint8_t *image; quirc_pixel_t *image;
int *region_info;
int w; int w;
int h; int h;

1
m4/empty.dir Normal file
View file

@ -0,0 +1 @@
## empty directory

23
make-quirc-config.sed Normal file
View file

@ -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__/