A copy of espressif/quirc 1.2.0.

Signed-off-by: lbuque <1102390310@qq.com>
This commit is contained in:
lbuque
2026-01-22 16:11:39 +08:00
commit 31e982fa89
37 changed files with 7122 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
3be250a06364f0d71a7903b66ac93084d2ce3998c2e75a168b9f1f0621dd6218
+1
View File
File diff suppressed because one or more lines are too long
+9
View File
@@ -0,0 +1,9 @@
idf_component_register(SRCS quirc/lib/decode.c
quirc/lib/identify.c
quirc/lib/quirc.c
quirc/lib/version_db.c
INCLUDE_DIRS quirc/lib)
# Perfomance optimization; see quirc README.md for an explanation of these options
target_compile_definitions(${COMPONENT_LIB} PRIVATE QUIRC_FLOAT_TYPE=float)
target_compile_definitions(${COMPONENT_LIB} PRIVATE QUIRC_USE_TGMATH)
+19
View File
@@ -0,0 +1,19 @@
quirc -- QR-code recognition library
Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>
ISC License
===========
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.
+9
View File
@@ -0,0 +1,9 @@
# Quirc QR code decoding library
[![Component Registry](https://components.espressif.com/components/espressif/quirc/badge.svg)](https://components.espressif.com/components/espressif/quirc)
This is an ESP-IDF component for [quirc](https://github.com/dlbeer/quirc), a QR code decoding library.
Please refer to https://github.com/dlbeer/quirc#library-use for the introduction to this library.
See also the `qrcode` component for generation of QR codes ([registry](https://components.espressif.com/components/espressif/qrcode), [source](../qrcode/README.md)).
+9
View File
@@ -0,0 +1,9 @@
dependencies:
idf:
version: '>=4.3.0'
description: Quirc QR code decoding library
documentation: https://github.com/dlbeer/quirc#library-use
issues: https://github.com/espressif/idf-extra-components/issues
repository: https://github.com/espressif/idf-extra-components.git
url: https://github.com/espressif/idf-extra-components/tree/master/quirc
version: 1.2.0
+12
View File
@@ -0,0 +1,12 @@
*.o
*.lo
quirc-demo
quirc-scanner
qrtest
inspect
libquirc.a
libquirc.so*
.*.swp
*~
.DS_Store
.idea
+19
View File
@@ -0,0 +1,19 @@
quirc -- QR-code recognition library
Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>
ISC License
===========
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.
+115
View File
@@ -0,0 +1,115 @@
# 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 2>&1)
SDL_LIBS = $(shell pkg-config --libs sdl)
LIB_VERSION = 1.2
CFLAGS ?= -O3 -Wall -fPIC
QUIRC_CFLAGS = -Ilib $(CFLAGS) $(SDL_CFLAGS)
LIB_OBJ = \
lib/decode.o \
lib/identify.o \
lib/quirc.o \
lib/version_db.o
DEMO_OBJ = \
demo/camera.o \
demo/mjpeg.o \
demo/convert.o
DEMO_UTIL_OBJ = \
demo/dthash.o \
demo/demoutil.o
OPENCV_CFLAGS := $(shell pkg-config --cflags opencv4 2>&1)
OPENCV_LIBS = $(shell pkg-config --libs opencv4)
QUIRC_CXXFLAGS = $(QUIRC_CFLAGS) $(OPENCV_CFLAGS) --std=c++17
.PHONY: all v4l sdl opencv install uninstall clean
all: libquirc.so qrtest
v4l: quirc-scanner
sdl: inspect quirc-demo
opencv: inspect-opencv quirc-demo-opencv
qrtest: tests/dbgutil.o tests/qrtest.o libquirc.a
$(CC) -o $@ tests/dbgutil.o tests/qrtest.o libquirc.a $(LDFLAGS) -lm -ljpeg -lpng
inspect: tests/dbgutil.o tests/inspect.o libquirc.a
$(CC) -o $@ tests/dbgutil.o tests/inspect.o libquirc.a $(LDFLAGS) -lm -ljpeg -lpng $(SDL_LIBS) -lSDL_gfx
inspect-opencv: tests/dbgutil.o tests/inspect_opencv.o libquirc.a
$(CXX) -o $@ tests/dbgutil.o tests/inspect_opencv.o libquirc.a $(LDFLAGS) -lm -ljpeg -lpng $(OPENCV_LIBS)
quirc-demo: $(DEMO_OBJ) $(DEMO_UTIL_OBJ) demo/demo.o libquirc.a
$(CC) -o $@ $(DEMO_OBJ) $(DEMO_UTIL_OBJ) demo/demo.o libquirc.a $(LDFLAGS) -lm -ljpeg $(SDL_LIBS) -lSDL_gfx
quirc-demo-opencv: $(DEMO_UTIL_OBJ) demo/demo_opencv.o libquirc.a
$(CXX) -o $@ $(DEMO_UTIL_OBJ) demo/demo_opencv.o libquirc.a $(LDFLAGS) -lm $(OPENCV_LIBS)
quirc-scanner: $(DEMO_OBJ) $(DEMO_UTIL_OBJ) demo/scanner.o libquirc.a
$(CC) -o $@ $(DEMO_OBJ) $(DEMO_UTIL_OBJ) demo/scanner.o libquirc.a $(LDFLAGS) -lm -ljpeg
libquirc.a: $(LIB_OBJ)
rm -f $@
ar cru $@ $(LIB_OBJ)
ranlib $@
.PHONY: libquirc.so
libquirc.so: libquirc.so.$(LIB_VERSION)
libquirc.so.$(LIB_VERSION): $(LIB_OBJ)
$(CC) -shared -o $@ $(LIB_OBJ) $(LDFLAGS) -lm
.c.o:
$(CC) $(QUIRC_CFLAGS) -o $@ -c $<
.SUFFIXES: .cxx
.cxx.o:
$(CXX) $(QUIRC_CXXFLAGS) -o $@ -c $<
install: libquirc.a libquirc.so.$(LIB_VERSION) 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.$(LIB_VERSION) \
$(DESTDIR)$(PREFIX)/lib
install -o root -g root -m 0755 quirc-demo $(DESTDIR)$(PREFIX)/bin
# install -o root -g root -m 0755 quirc-demo-opencv $(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/libquirc.a
rm -f $(DESTDIR)$(PREFIX)/bin/quirc-demo
rm -f $(DESTDIR)$(PREFIX)/bin/quirc-demo-opencv
rm -f $(DESTDIR)$(PREFIX)/bin/quirc-scanner
clean:
rm -f */*.o
rm -f */*.lo
rm -f libquirc.a
rm -f libquirc.so.$(LIB_VERSION)
rm -f qrtest
rm -f inspect
rm -f inspect-opencv
rm -f quirc-demo
rm -f quirc-demo-opencv
rm -f quirc-scanner
+283
View File
@@ -0,0 +1,283 @@
Quirc
=====
QR codes are a type of high-density matrix barcodes, and quirc is a library for
extracting and decoding them from images. It has several features which make it
a good choice for this purpose:
* It is fast enough to be used with realtime video: extracting and decoding
from VGA frame takes about 50 ms on a modern x86 core.
* It has a robust and tolerant recognition algorithm. It can correctly
recognise and decode QR codes which are rotated and/or oblique to the camera.
It can also distinguish and decode multiple codes within the same image.
* It is easy to use, with a simple API described in a single commented header
file (see below for an overview).
* It is small and easily embeddable, with no dependencies other than standard C
functions.
* It has a very small memory footprint: one byte per image pixel, plus a few kB
per decoder object.
* It uses no global mutable state, and is safe to use in a multithreaded
application.
* BSD-licensed, with almost no restrictions regarding use and/or modification.
The distribution comes with, in addition to the library, several test programs.
While the core library is very portable, these programs have some additional
dependencies as documented below.
### quirc-demo
This is an real-time demo which requires a camera and a graphical display. The
video stream is displayed on screen as it's received, and any QR codes
recognised are highlighted in the image, with the decoded information both
displayed on the image and printed on stdout.
This requires: libjpeg, libpng, SDL, V4L2
### quirc-demo-opencv
A demo similar to `quirc-demo`.
But this version uses OpenCV instead of other libraries.
This requires: OpenCV
### quirc-scanner
This program turns your camera into a barcode scanner. It's almost the same as
the `demo` application, but it doesn't display the video stream, and thus
doesn't require a graphical display.
This requires: libjpeg, V4L2
### qrtest
This test is used to evaluate the performance of library. Given a directory
tree containing a bunch of JPEG images, it will attempt to locate and decode QR
codes in each image. Speed and success statistics are collected and printed on
stdout.
This requires: libjpeg, libpng
### inspect
This test is used for debugging. Given a single JPEG image, it will display a
diagram showing the internal state of the decoder as well as printing
additional information on stdout.
This requires: libjpeg, libpng, SDL
### inspect-opencv
A test similar to `inspect`.
But this version uses OpenCV instead of other libraries.
This requires: libjpeg, libpng, OpenCV
Build-time requirements
-----------------------
### make
While we are trying to keep our makefiles portable,
it might be incompatible with some versions of make.
#### GNU make
Version 4.x and later works. We recommend to use it.
Version prior to 4.0 doesn't work because it doesn't support `!=`.
*Note*: macOS's default version of make is GNU make 3.81 as of writing this.
#### BSD make
It also works.
You might need to specify the `-r` make option because some of
the default macros like CFLAGS from sys.mk can cause unintended effects.
Installation
------------
To build the library and associated demos/tests, type `make`.
Several options can be adjusted at compile time by passing additional arguments
to `make`. See [Compile-time options](#compile-time-options) section below for details.
Type `make install` to install the library, header file and camera demos.
You can specify one or several of the following targets if you don't want, or
are unable to build everything:
* libquirc.a
* libquirc.so
* qrtest
* inspect
* inspect-opencv
* quirc-scanner
* quirc-demo
* quirc-demo-opencv
Library use
-----------
All of the library's functionality is exposed through a single header file,
which you should include:
```C
#include <quirc.h>
```
To decode images, you'll need to instantiate a `struct quirc` object, which is
done with the `quirc_new` function. Later, when you no longer need to decode
anything, you should release the allocated memory with `quirc_destroy`:
```C
struct quirc *qr;
qr = quirc_new();
if (!qr) {
perror("Failed to allocate memory");
abort();
}
/* ... */
quirc_destroy(qr);
```
Having obtained a decoder object, you need to set the image size that you'll be
working with, which is done using `quirc_resize`:
```C
if (quirc_resize(qr, 640, 480) < 0) {
perror("Failed to allocate video memory");
abort();
}
```
`quirc_resize` and `quirc_new` are the only library functions which allocate
memory. If you plan to process a series of frames (or a video stream), you
probably want to allocate and size a single decoder and hold onto it to process
each frame.
Processing frames is done in two stages. The first stage is an
image-recognition stage called identification, which takes a grayscale image
and searches for QR codes. Using `quirc_begin` and `quirc_end`, you can feed a
grayscale image directly into the buffer that `quirc` uses for image
processing:
```C
uint8_t *image;
int w, h;
image = quirc_begin(qr, &w, &h);
/* Fill out the image buffer here.
* image is a pointer to a w*h bytes.
* One byte per pixel, w pixels per line, h lines in the buffer.
*/
quirc_end(qr);
```
Note that `quirc_begin` simply returns a pointer to a previously allocated
buffer. The buffer will contain uninitialized data. After the call to
`quirc_end`, the decoder holds a list of detected QR codes which can be queried
via `quirc_count` and `quirc_extract`.
At this point, the second stage of processing occurs -- decoding. This is done
via the call to `quirc_decode`, which is not associated with a decoder object.
```C
int num_codes;
int i;
/* We've previously fed an image to the decoder via
* quirc_begin/quirc_end.
*/
num_codes = quirc_count(qr);
for (i = 0; i < num_codes; i++) {
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
quirc_extract(qr, i, &code);
/* Decoding stage */
err = quirc_decode(&code, &data);
if (err)
printf("DECODE FAILED: %s\n", quirc_strerror(err));
else
printf("Data: %s\n", data.payload);
}
```
`quirc_code` and `quirc_data` are flat structures which don't need to be
initialized or freed after use.
In case you also need to support horizontally flipped QR-codes (mirrored
images according to ISO 18004:2015, pages 6 and 62), you can make a second
decode attempt with the flipped image data whenever you get an ECC failure:
```C
err = quirc_decode(&code, &data);
if (err == QUIRC_ERROR_DATA_ECC) {
quirc_flip(&code);
err = quirc_decode(&code, &data);
}
if (err)
printf("DECODE FAILED: %s\n", quirc_strerror(err));
else
printf("Data: %s\n", data.payload);
```
Compile-time options
--------------------
The following compile-time options can be used to adjust the library to a
particular use case.
Each option is a C preprocessor macro. To set an option, add it to CFLAGS
using `-DOPTION=VALUE` syntax, for example:
```bash
make CFLAGS="-DQUIRC_MAX_REGIONS=65534"
```
* `QUIRC_MAX_REGIONS`: If you need to decode "large" image files, set
`QUIRC_MAX_REGIONS=65534`. Note that since this will increase the memory
usage, it is discouraged for low resource devices (i.e. embedded).
* `QUIRC_FLOAT_TYPE`: If defined, it sets the type name to use
in floating point calculations. For example, on an embedded system
with only a single precision FPU, set `QUIRC_FLOAT_TYPE=float` to
improve performance.
* `QUIRC_USE_TGMATH`: if defined, quirc will internally use `<tgmath.h>`
header instead of `<math.h>`, ensuring that the math function calls
use the same precision as the arguments. Define this option if you are
setting `QUIRC_FLOAT_TYPE=float` and the compiler supports C99 or later
language standard.
Copyright
---------
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.
+591
View File
File diff suppressed because it is too large Load Diff
+104
View File
@@ -0,0 +1,104 @@
/* quirc -- QR-code recognition library
* Copyright (C) 2010-2014 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.
*/
#ifndef CAMERA_H_
#define CAMERA_H_
#include <stddef.h>
#define CAMERA_MAX_BUFFERS 32
typedef enum {
CAMERA_FORMAT_UNKNOWN = 0,
CAMERA_FORMAT_MJPEG,
CAMERA_FORMAT_YUYV
} camera_format_t;
struct camera_parms {
camera_format_t format;
int width;
int height;
int pitch_bytes;
int interval_n;
int interval_d;
};
struct camera_buffer {
void *addr;
size_t size;
unsigned long offset;
};
struct camera {
int fd;
struct camera_parms parms;
struct camera_buffer buf_desc[CAMERA_MAX_BUFFERS];
int buf_count;
/* Stream state */
int s_on;
int s_qc;
int s_qhead;
};
/* Initialize/destroy a camera. No resources are allocated. */
void camera_init(struct camera *c);
void camera_destroy(struct camera *c);
/* Open/close the camera device */
int camera_open(struct camera *c, const char *path,
int target_w, int target_h,
int tr_n, int tr_d);
void camera_close(struct camera *c);
static inline int camera_get_fd(const struct camera *c)
{
return c->fd;
}
static inline const struct camera_parms *camera_get_parms
(const struct camera *c)
{
return &c->parms;
}
/* Map buffers */
int camera_map(struct camera *c, int buf_count);
void camera_unmap(struct camera *c);
static inline int camera_get_buf_count(const struct camera *c)
{
return c->buf_count;
}
/* Switch streaming on/off */
int camera_on(struct camera *c);
void camera_off(struct camera *c);
/* Enqueue/dequeue buffers (count = 0 means enqueue all) */
int camera_enqueue_all(struct camera *c);
int camera_dequeue_one(struct camera *c);
/* Fetch the oldest dequeued buffer */
static inline const struct camera_buffer *camera_get_head
(const struct camera *c)
{
return &c->buf_desc[(c->s_qhead + c->buf_count - 1) % c->buf_count];
}
#endif
+103
View File
@@ -0,0 +1,103 @@
/* 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.
*/
#include "convert.h"
#define CHANNEL_CLAMP(dst, tmp, lum, chrom) \
(tmp) = ((lum) + (chrom)) >> 8; \
if ((tmp) < 0) \
(tmp) = 0; \
if ((tmp) > 255) \
(tmp) = 255; \
(dst) = (tmp);
void yuyv_to_rgb32(const uint8_t *src, int src_pitch,
int w, int h,
uint8_t *dst, int dst_pitch)
{
int y;
for (y = 0; y < h; y++) {
int x;
const uint8_t *srow = src + y * src_pitch;
uint8_t *drow = dst + y * dst_pitch;
for (x = 0; x < w; x += 2) {
/* ITU-R colorspace assumed */
int y0 = (int)srow[0] * 256;
int y1 = (int)srow[2] * 256;
int cr = (int)srow[3] - 128;
int cb = (int)srow[1] - 128;
int r = cr * 359;
int g = -cb * 88 - 128 * cr;
int b = 454 * cb;
int z;
CHANNEL_CLAMP(drow[0], z, y0, b);
CHANNEL_CLAMP(drow[1], z, y0, g);
CHANNEL_CLAMP(drow[2], z, y0, r);
CHANNEL_CLAMP(drow[4], z, y1, b);
CHANNEL_CLAMP(drow[5], z, y1, g);
CHANNEL_CLAMP(drow[6], z, y1, r);
srow += 4;
drow += 8;
}
}
}
void yuyv_to_luma(const uint8_t *src, int src_pitch,
int w, int h,
uint8_t *dst, int dst_pitch)
{
int y;
for (y = 0; y < h; y++) {
int x;
const uint8_t *srow = src + y * src_pitch;
uint8_t *drow = dst + y * dst_pitch;
for (x = 0; x < w; x += 2) {
*(drow++) = srow[0];
*(drow++) = srow[2];
srow += 4;
}
}
}
void rgb32_to_luma(const uint8_t *src, int src_pitch,
int w, int h,
uint8_t *dst, int dst_pitch)
{
int y;
for (y = 0; y < h; y++) {
const uint8_t *rgb32 = src + src_pitch * y;
uint8_t *gray = dst + y * dst_pitch;
int i;
for (i = 0; i < w; i++) {
/* ITU-R colorspace assumed */
int r = (int)rgb32[2];
int g = (int)rgb32[1];
int b = (int)rgb32[0];
int sum = r * 59 + g * 150 + b * 29;
*(gray++) = sum >> 8;
rgb32 += 4;
}
}
}
+39
View File
@@ -0,0 +1,39 @@
/* 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.
*/
#ifndef CONVERT_H_
#define CONVERT_H_
#include <stdint.h>
/* Convert 4:2:2 YUYV format to RGB32 format. The source and destination
* frames are expected to be the same size.
*/
void yuyv_to_rgb32(const uint8_t *src, int src_pitch,
int w, int h,
uint8_t *dst, int dst_pitch);
/* Extract the luma channel from a 4:2:2 YUYV image. */
void yuyv_to_luma(const uint8_t *src, int src_pitch,
int w, int h,
uint8_t *dst, int dst_pitch);
/* Extract the luma channel from an RGB32 image. */
void rgb32_to_luma(const uint8_t *src, int src_pitch,
int w, int h,
uint8_t *dst, int dst_pitch);
#endif
+333
View File
@@ -0,0 +1,333 @@
/* 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.
*/
#include <unistd.h>
#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include <quirc.h>
#include <time.h>
#include <getopt.h>
#include "camera.h"
#include "mjpeg.h"
#include "convert.h"
#include "dthash.h"
#include "demoutil.h"
/* Collected command-line arguments */
static const char *camera_path = "/dev/video0";
static int video_width = 640;
static int video_height = 480;
static int want_frame_rate = 0;
static int want_verbose = 0;
static int printer_timeout = 2;
static void fat_text(SDL_Surface *screen, int x, int y, const char *text)
{
int i, j;
for (i = -1; i <= 1; i++)
for (j = -1; j <= 1; j++)
stringColor(screen, x + i, y + j, text, 0xffffffff);
stringColor(screen, x, y, text, 0x008000ff);
}
static void fat_text_cent(SDL_Surface *screen, int x, int y, const char *text)
{
x -= strlen(text) * 4;
fat_text(screen, x, y, text);
}
static void draw_qr(SDL_Surface *screen, struct quirc *q, struct dthash *dt)
{
int count = quirc_count(q);
int i;
for (i = 0; i < count; i++) {
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
int j;
int xc = 0;
int yc = 0;
char buf[128];
quirc_extract(q, i, &code);
for (j = 0; j < 4; j++) {
struct quirc_point *a = &code.corners[j];
struct quirc_point *b = &code.corners[(j + 1) % 4];
xc += a->x;
yc += a->y;
lineColor(screen, a->x, a->y, b->x, b->y, 0x008000ff);
}
xc /= 4;
yc /= 4;
if (want_verbose) {
snprintf(buf, sizeof(buf), "Code size: %d cells",
code.size);
fat_text_cent(screen, xc, yc - 20, buf);
}
err = quirc_decode(&code, &data);
if (err) {
if (want_verbose)
fat_text_cent(screen, xc, yc,
quirc_strerror(err));
} else {
fat_text_cent(screen, xc, yc, (char *)data.payload);
print_data(&data, dt, want_verbose);
if (want_verbose) {
snprintf(buf, sizeof(buf),
"Ver: %d, ECC: %c, Mask: %d, Type: %d",
data.version, "MLHQ"[data.ecc_level],
data.mask, data.data_type);
fat_text_cent(screen, xc, yc + 20, buf);
}
}
}
}
static int main_loop(struct camera *cam, SDL_Surface *screen,
struct quirc *q, struct mjpeg_decoder *mj)
{
SDL_Event ev;
time_t last_rate = 0;
int frame_count = 0;
char rate_text[64];
struct dthash dt;
rate_text[0] = 0;
dthash_init(&dt, printer_timeout);
for (;;) {
time_t now = time(NULL);
const struct camera_buffer *head;
const struct camera_parms *parms = camera_get_parms(cam);
if (camera_dequeue_one(cam) < 0) {
perror("camera_dequeue_one");
return -1;
}
head = camera_get_head(cam);
SDL_LockSurface(screen);
switch (parms->format) {
case CAMERA_FORMAT_MJPEG:
mjpeg_decode_rgb32(mj, head->addr, head->size,
screen->pixels, screen->pitch,
screen->w, screen->h);
break;
case CAMERA_FORMAT_YUYV:
yuyv_to_rgb32(head->addr, parms->width * 2,
parms->width, parms->height,
screen->pixels, screen->pitch);
break;
default:
fprintf(stderr, "Unknown frame format\n");
return -1;
}
if (camera_enqueue_all(cam) < 0) {
perror("camera_enqueue_all");
return -1;
}
rgb32_to_luma(screen->pixels, screen->pitch,
screen->w, screen->h,
quirc_begin(q, NULL, NULL),
screen->w);
quirc_end(q);
SDL_UnlockSurface(screen);
draw_qr(screen, q, &dt);
if (want_frame_rate)
fat_text(screen, 5, 5, rate_text);
SDL_Flip(screen);
while (SDL_PollEvent(&ev) > 0) {
if (ev.type == SDL_QUIT)
return 0;
if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == 'q')
return 0;
}
if (now != last_rate) {
snprintf(rate_text, sizeof(rate_text),
"Frame rate: %d fps", frame_count);
frame_count = 0;
last_rate = now;
}
frame_count++;
}
}
static int run_demo(void)
{
struct quirc *qr;
struct camera cam;
struct mjpeg_decoder mj;
const struct camera_parms *parms;
SDL_Surface *screen;
camera_init(&cam);
if (camera_open(&cam, camera_path, video_width, video_height,
25, 1) < 0) {
perror("camera_open");
goto fail_qr;
}
if (camera_map(&cam, 8) < 0) {
perror("camera_map");
goto fail_qr;
}
if (camera_on(&cam) < 0) {
perror("camera_on");
goto fail_qr;
}
if (camera_enqueue_all(&cam) < 0) {
perror("camera_enqueue_all");
goto fail_qr;
}
parms = camera_get_parms(&cam);
qr = quirc_new();
if (!qr) {
perror("couldn't allocate QR decoder");
goto fail_qr;
}
if (quirc_resize(qr, parms->width, parms->height) < 0) {
perror("couldn't allocate QR buffer");
goto fail_qr_resize;
}
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
perror("couldn't init SDL");
goto fail_sdl_init;
}
screen = SDL_SetVideoMode(parms->width, parms->height, 32,
SDL_SWSURFACE | SDL_DOUBLEBUF);
if (!screen) {
perror("couldn't init video mode");
goto fail_video_mode;
}
mjpeg_init(&mj);
if (main_loop(&cam, screen, qr, &mj) < 0)
goto fail_main_loop;
mjpeg_free(&mj);
SDL_Quit();
quirc_destroy(qr);
camera_destroy(&cam);
return 0;
fail_main_loop:
mjpeg_free(&mj);
fail_video_mode:
SDL_Quit();
fail_qr_resize:
fail_sdl_init:
quirc_destroy(qr);
fail_qr:
camera_destroy(&cam);
return -1;
}
static void usage(const char *progname)
{
printf("Usage: %s [options]\n\n"
"Valid options are:\n\n"
" -f Show frame rate on screen.\n"
" -v Show extra data for detected codes.\n"
" -d <device> Specify camera device path.\n"
" -s <WxH> Specify video dimensions.\n"
" -p <timeout> Set printer timeout (seconds).\n"
" --help Show this information.\n"
" --version Show library version information.\n",
progname);
}
int main(int argc, char **argv)
{
static const struct option longopts[] = {
{"help", 0, 0, 'H'},
{"version", 0, 0, 'V'},
{NULL, 0, 0, 0}
};
int opt;
printf("quirc demo\n");
printf("Copyright (C) 2010-2014 Daniel Beer <dlbeer@gmail.com>\n");
printf("\n");
while ((opt = getopt_long(argc, argv, "d:s:fvg:p:",
longopts, NULL)) >= 0)
switch (opt) {
case 'V':
printf("Library version: %s\n", quirc_version());
return 0;
case 'H':
usage(argv[0]);
return 0;
case 'v':
want_verbose = 1;
break;
case 'f':
want_frame_rate = 1;
break;
case 's':
if (parse_size(optarg, &video_width, &video_height) < 0)
return -1;
break;
case 'p':
printer_timeout = atoi(optarg);
break;
case 'd':
camera_path = optarg;
break;
case '?':
fprintf(stderr, "Try --help for usage information\n");
return -1;
}
return run_demo();
}
+263
View File
@@ -0,0 +1,263 @@
/* 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.
*/
#include <assert.h>
#include <unistd.h>
#include <quirc.h>
#include <time.h>
#include <getopt.h>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
#include "camera.h"
#include "convert.h"
#include "dthash.h"
#include "demoutil.h"
/* Collected command-line arguments */
static int want_frame_rate = 0;
static int want_verbose = 0;
static int printer_timeout = 2;
static const int font = FONT_HERSHEY_PLAIN;
static const int thickness = 2;
static const double font_scale = 1.5;
static Scalar blue = Scalar(255, 0, 8);
static void fat_text(Mat &screen, int x, int y, const char *text)
{
putText(screen, text, Point(x, y), font, font_scale, blue, thickness);
}
static void fat_text_cent(Mat &screen, int x, int y, const char *text)
{
int baseline;
Size size = getTextSize(text, font, font_scale, thickness, &baseline);
putText(screen, text, Point(x - size.width / 2, y - size.height /2),
font, font_scale, blue, thickness);
}
static void draw_qr(Mat &screen, struct quirc *q, struct dthash *dt)
{
int count = quirc_count(q);
int i;
for (i = 0; i < count; i++) {
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
int j;
int xc = 0;
int yc = 0;
char buf[128];
quirc_extract(q, i, &code);
for (j = 0; j < 4; j++) {
struct quirc_point *a = &code.corners[j];
struct quirc_point *b = &code.corners[(j + 1) % 4];
xc += a->x;
yc += a->y;
line(screen, Point(a->x, a->y), Point(b->x, b->y), blue, 8);
}
xc /= 4;
yc /= 4;
if (want_verbose) {
snprintf(buf, sizeof(buf), "Code size: %d cells",
code.size);
fat_text_cent(screen, xc, yc - 20, buf);
}
err = quirc_decode(&code, &data);
if (err) {
if (want_verbose)
fat_text_cent(screen, xc, yc, quirc_strerror(err));
} else {
fat_text_cent(screen, xc, yc, (const char *)data.payload);
print_data(&data, dt, want_verbose);
if (want_verbose) {
snprintf(buf, sizeof(buf),
"Ver: %d, ECC: %c, Mask: %d, Type: %d",
data.version, "MLHQ"[data.ecc_level],
data.mask, data.data_type);
fat_text_cent(screen, xc, yc + 20, buf);
}
}
}
}
static int main_loop(VideoCapture &cap, struct quirc *q)
{
time_t last_rate = 0;
int frame_count = 0;
char rate_text[64];
struct dthash dt;
rate_text[0] = 0;
dthash_init(&dt, printer_timeout);
Mat frame;
for (;;) {
time_t now = time(NULL);
cap.read(frame);
if (frame.empty()) {
perror("empty frame");
return 0;
}
int w;
int h;
uint8_t *buf = quirc_begin(q, &w, &h);
/* convert frame into buf */
assert(frame.cols == w);
assert(frame.rows == h);
Mat gray;
cvtColor(frame, gray, COLOR_BGR2GRAY, 0);
for (int y = 0; y < gray.rows; y++) {
for (int x = 0; x < gray.cols; x++) {
buf[(y * w + x)] = gray.at<uint8_t>(y, x);
}
}
quirc_end(q);
draw_qr(frame, q, &dt);
if (want_frame_rate)
fat_text(frame, 20, 20, rate_text);
imshow("quirc-demo-opencv", frame);
waitKey(5);
if (now != last_rate) {
snprintf(rate_text, sizeof(rate_text),
"Frame rate: %d fps", frame_count);
frame_count = 0;
last_rate = now;
}
frame_count++;
}
}
static int run_demo(void)
{
struct quirc *qr;
VideoCapture cap(0);
unsigned int width;
unsigned int height;
if (!cap.isOpened()) {
perror("camera_open");
goto fail_qr;
}
width = cap.get(CAP_PROP_FRAME_WIDTH);
height = cap.get(CAP_PROP_FRAME_HEIGHT);
qr = quirc_new();
if (!qr) {
perror("couldn't allocate QR decoder");
goto fail_qr;
}
if (quirc_resize(qr, width, height) < 0) {
perror("couldn't allocate QR buffer");
goto fail_qr_resize;
}
if (main_loop(cap, qr) < 0) {
goto fail_main_loop;
}
quirc_destroy(qr);
return 0;
fail_main_loop:
fail_qr_resize:
quirc_destroy(qr);
fail_qr:
return -1;
}
static void usage(const char *progname)
{
printf("Usage: %s [options]\n\n"
"Valid options are:\n\n"
" -f Show frame rate on screen.\n"
" -v Show extra data for detected codes.\n"
" -p <timeout> Set printer timeout (seconds).\n"
" --help Show this information.\n"
" --version Show library version information.\n",
progname);
}
int main(int argc, char **argv)
{
static const struct option longopts[] = {
{"help", 0, 0, 'H'},
{"version", 0, 0, 'V'},
{NULL, 0, 0, 0}
};
int opt;
printf("quirc demo with OpenCV\n");
printf("Copyright (C) 2010-2014 Daniel Beer <dlbeer@gmail.com>\n");
printf("\n");
while ((opt = getopt_long(argc, argv, "fvg:p:",
longopts, NULL)) >= 0)
switch (opt) {
case 'V':
printf("Library version: %s\n", quirc_version());
return 0;
case 'H':
usage(argv[0]);
return 0;
case 'v':
want_verbose = 1;
break;
case 'f':
want_frame_rate = 1;
break;
case 'p':
printer_timeout = atoi(optarg);
break;
case '?':
fprintf(stderr, "Try --help for usage information\n");
return -1;
}
return run_demo();
}
+71
View File
@@ -0,0 +1,71 @@
/* 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.
*/
#include <stdio.h>
#include <ctype.h>
#include "demoutil.h"
void print_data(const struct quirc_data *data, struct dthash *dt,
int want_verbose)
{
if (dthash_seen(dt, data))
return;
printf("==> %s\n", data->payload);
if (want_verbose)
printf(" Version: %d, ECC: %c, Mask: %d, Type: %d\n\n",
data->version, "MLHQ"[data->ecc_level],
data->mask, data->data_type);
}
int parse_size(const char *text, int *video_width, int *video_height)
{
int state = 0;
int w = 0, h = 0;
int i;
for (i = 0; text[i]; i++) {
if (text[i] == 'x' || text[i] == 'X') {
if (state == 0) {
state = 1;
} else {
fprintf(stderr, "parse_size: expected WxH\n");
return -1;
}
} else if (isdigit(text[i])) {
if (state == 0)
w = w * 10 + text[i] - '0';
else
h = h * 10 + text[i] - '0';
} else {
fprintf(stderr, "Invalid character in size: %c\n",
text[i]);
return -1;
}
}
if (w <= 0 || w >= 10000 || h <= 0 || h >= 10000) {
fprintf(stderr, "Invalid size: %dx%d\n", w, h);
return -1;
}
*video_width = w;
*video_height = h;
return 0;
}
+42
View File
@@ -0,0 +1,42 @@
/* 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.
*/
#ifndef DEMOUTIL_H_
#define DEMOUTIL_H_
#include "dthash.h"
#include "quirc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Check if we've seen the given code, and if not, print it on stdout.
* Include version info if requested.
*/
void print_data(const struct quirc_data *data, struct dthash *dt,
int want_verbose);
/* Parse a string of the form "WxH" and return width and height as
* integers. Returns 0 on success or -1 if a parser error occurs.
*/
int parse_size(const char *text, int *video_width, int *video_height);
#ifdef __cplusplus
}
#endif
#endif
+139
View File
@@ -0,0 +1,139 @@
/* 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.
*/
#include <string.h>
#include "dthash.h"
static const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
static uint32_t calc_crc(uint32_t crc, const uint8_t *buf, int len)
{
while (len--) {
crc = crc32_tab[(crc ^ *buf) & 0xff] ^ (crc >> 8);
buf++;
}
return crc;
}
static uint32_t code_hash(const struct quirc_data *data)
{
uint8_t extra[4] = {data->version, data->ecc_level,
data->mask, data->data_type};
uint32_t crc = calc_crc(0xffffffff, extra, 4);
return calc_crc(crc, data->payload, data->payload_len);
}
static void flush_old(struct dthash *d, time_t now)
{
int i;
for (i = 0; i < d->count; i++) {
struct dthash_code *c = &d->codes[i];
if (c->when + d->timeout <= now) {
if (i + 1 < d->count)
memcpy(c, &d->codes[d->count - 1], sizeof(*c));
d->count--;
}
}
}
void dthash_init(struct dthash *d, int timeout)
{
d->count = 0;
d->timeout = timeout;
}
int dthash_seen(struct dthash *d, const struct quirc_data *data)
{
time_t now = time(NULL);
uint32_t hash = code_hash(data);
struct dthash_code *c;
int i;
flush_old(d, now);
/* If the code is already seen, update its timestamp */
for (i = 0; i < d->count; i++) {
c = &d->codes[i];
if (c->hash == hash) {
c->when = now;
return 1;
}
}
/* Otherwise, find a place to put it. If necessary, push the
* oldset code out of the table.
*/
if (d->count + 1 < DTHASH_MAX_CODES) {
c = &d->codes[d->count++];
} else {
c = &d->codes[0];
for (i = 1; i < d->count; i++)
if (d->codes[i].when < c->when)
c = &d->codes[i];
}
c->hash = hash;
c->when = now;
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
/* 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.
*/
#ifndef DTHASH_H_
#define DTHASH_H_
#include <stdint.h>
#include <time.h>
#include "quirc.h"
/* Detector hash.
*
* This structure keeps track of codes that have been seen within the
* last N seconds, and allows us to print out codes at a reasonable
* rate as we see them.
*/
#define DTHASH_MAX_CODES 32
struct dthash_code {
uint32_t hash;
time_t when;
};
struct dthash {
struct dthash_code codes[DTHASH_MAX_CODES];
int count;
int timeout;
};
#ifdef __cplusplus
extern "C" {
#endif
/* Initialise a detector hash with the given timeout. */
void dthash_init(struct dthash *d, int timeout);
/* When a code is discovered, this function should be called to see if
* it should be printed. The hash will record having seen the code, and
* return non-zero if it's the first time we've seen it within the
* configured timeout period.
*/
int dthash_seen(struct dthash *d, const struct quirc_data *data);
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More