2012-05-04 02:58:42 +02:00
|
|
|
Quirc
|
|
|
|
=====
|
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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:
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* 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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* 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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* It is easy to use, with a simple API described in a single commented header
|
|
|
|
file (see below for an overview).
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* It is small and easily embeddable, with no dependencies other than standard C
|
|
|
|
functions.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* It has a very small memory footprint: one byte per image pixel, plus a few kB
|
|
|
|
per decoder object.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* It uses no global mutable state, and is safe to use in a multithreaded
|
|
|
|
application.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* BSD-licensed, with almost no restrictions regarding use and/or modification.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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. All of them require libjpeg, and two (`quirc-demo` and `inspect`)
|
|
|
|
require SDL. The camera demos use Linux-specific APIs:
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
### quirc-demo
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2021-03-22 06:43:35 +01:00
|
|
|
This requires SDL and V4L2.
|
|
|
|
|
2021-04-08 02:35:40 +02:00
|
|
|
### quirc-demo-opencv
|
|
|
|
|
|
|
|
A demo similar to `quirc-demo`.
|
|
|
|
But this version uses OpenCV instead of other libraries.
|
|
|
|
|
|
|
|
This requires OpenCV.
|
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
### quirc-scanner
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2021-03-22 06:43:35 +01:00
|
|
|
This requires V4L2.
|
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
### qrtest
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
### inspect
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2021-03-22 06:43:35 +01:00
|
|
|
This requires SDL.
|
|
|
|
|
2012-05-04 02:58:42 +02:00
|
|
|
Installation
|
|
|
|
------------
|
2019-10-23 09:37:24 +02:00
|
|
|
To build the library and associated demos/tests, type `make`. If you need to
|
|
|
|
decode "large" image files build with `CFLAGS="-DQUIRC_MAX_REGIONS=65534" make`
|
|
|
|
instead. Note that this will increase the memory usage, it is discouraged for
|
|
|
|
low resource devices (i.e. embedded).
|
|
|
|
|
|
|
|
Type `make install` to install the library, header file and camera demos.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
You can specify one or several of the following targets if you don't want, or
|
|
|
|
are unable to build everything:
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
* libquirc.a
|
|
|
|
* libquirc.so
|
|
|
|
* qrtest
|
|
|
|
* inspect
|
|
|
|
* quirc-scanner
|
|
|
|
* quirc-demo
|
2021-04-08 02:35:40 +02:00
|
|
|
* quirc-demo-opencv
|
2012-05-04 02:58:42 +02:00
|
|
|
|
|
|
|
Library use
|
|
|
|
-----------
|
2019-09-25 11:07:20 +02:00
|
|
|
All of the library's functionality is exposed through a single header file,
|
|
|
|
which you should include:
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
```C
|
|
|
|
#include <quirc.h>
|
|
|
|
```
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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`:
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
```C
|
|
|
|
struct quirc *qr;
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
qr = quirc_new();
|
|
|
|
if (!qr) {
|
|
|
|
perror("Failed to allocate memory");
|
|
|
|
abort();
|
|
|
|
}
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
/* ... */
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
quirc_destroy(qr);
|
|
|
|
```
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
Having obtained a decoder object, you need to set the image size that you'll be
|
|
|
|
working with, which is done using `quirc_resize`:
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
```C
|
|
|
|
if (quirc_resize(qr, 640, 480) < 0) {
|
|
|
|
perror("Failed to allocate video memory");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
```
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
`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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
|
|
|
Processing frames is done in two stages. The first stage is an
|
2019-09-25 11:07:20 +02:00
|
|
|
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:
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
```C
|
|
|
|
uint8_t *image;
|
|
|
|
int w, h;
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
image = quirc_begin(qr, &w, &h);
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
/* 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.
|
|
|
|
*/
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
quirc_end(qr);
|
|
|
|
```
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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`.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
```C
|
|
|
|
int num_codes;
|
|
|
|
int i;
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
/* We've previously fed an image to the decoder via
|
|
|
|
* quirc_begin/quirc_end.
|
|
|
|
*/
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
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;
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
quirc_extract(qr, i, &code);
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
/* Decoding stage */
|
|
|
|
err = quirc_decode(&code, &data);
|
|
|
|
if (err)
|
|
|
|
printf("DECODE FAILED: %s\n", quirc_strerror(err));
|
|
|
|
else
|
|
|
|
printf("Data: %s\n", data.payload);
|
|
|
|
}
|
|
|
|
```
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2019-09-25 11:07:20 +02:00
|
|
|
`quirc_code` and `quirc_data` are flat structures which don't need to be
|
|
|
|
initialized or freed after use.
|
2012-05-04 02:58:42 +02:00
|
|
|
|
2020-09-22 12:22:06 +02:00
|
|
|
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);
|
|
|
|
```
|
|
|
|
|
2012-05-04 02:58:42 +02:00
|
|
|
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.
|