...
 
Commits (3)
0.22:
* zbarcam-qt: allow changing resolutions in real time
* zbarcam-qt: better support ZBar options
* zbarcam-qt: do several visual improvements
* zbarcam-qt: make it remember the geometry
* zbarcam-qt: allow show/hide control and options bars
* zbarcam-qt: remember lastly used settings and camera controls
* zbarcam-qt: allow changing ZBar decode options via GUI
* Add API to allow get/set resolutions
* img_scanner: add handler for color-inverted codes
* img_scanner: fix get_config parameter validation
* scan_video: improve logic to remove duplicated/invalid devnodes
* symbol.c: fix symbol hash logic (prevents crash with QR options)
* configure.ac: fix an error at libv4l2 package check
* fix some typos
* exit gracefully when decoding split QR codes
0.21:
* zbarcam-qt: allow selecting codes via GUI interface
......@@ -21,7 +39,7 @@
* Ignore ENOTTY errors when calling VIDIOC_S_CROP
* doc/Makefile.am.inc: clean html generated files
* Add --disable-doc configure option to disable building docs
* Fix function protoype to be compatible with recent libjpeg
* Fix function prototype to be compatible with recent libjpeg
* Wrap logical not operations into parentheses
* INSTALL: warn that autoconf should be called before configure
* code128: fix error logic
......
......@@ -11,7 +11,7 @@ code images and using a video device (eg, webcam) as a bar code scanner.
For application developers, language bindings are included for C, C++,
Python 2 and Perl as well as GUI widgets for Qt, GTK and PyGTK 2.0.
Zbar also supports sending the scaned codes via dbus, allowing its
Zbar also supports sending the scanned codes via dbus, allowing its
integration with other applications.
Check the ZBar home page for the latest release, mailing lists, etc.:
......@@ -27,7 +27,7 @@ BUILDING
See `INSTALL.md` for generic configuration and build instructions.
The scanner/decoder library itself only requires a few standard
library functions which should be avilable almost anywhere.
library functions which should be available almost anywhere.
The zbarcam program uses the video4linux API (v4l1 or v4l2) to access
the video device. This interface is part of the linux kernel, a 3.16
......
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
AC_INIT([zbar], [0.21], [mchehab+samsung@kernel.org])
AC_INIT([zbar], [0.22], [mchehab+samsung@kernel.org])
m4_ifndef([AC_LANG_DEFINES_PROVIDED],
[m4_define([AC_LANG_DEFINES_PROVIDED])])
AC_CONFIG_AUX_DIR(config)
......@@ -14,7 +14,7 @@ LT_INIT([dlopen win32-dll])
LT_LANG([Windows Resource])
AM_SILENT_RULES([yes])
dnl update these just before each release (along w/pacakge version above)
dnl update these just before each release (along w/package version above)
dnl LIB_VERSION update instructions copied from libtool docs:
dnl library version follows the form current:revision:age
dnl - If the library source code has changed at all since the last update,
......@@ -241,18 +241,19 @@ AS_IF([test "x$enable_video" = "xno"],
AC_CHECK_HEADERS([linux/videodev2.h], [have_v4l2="yes"])
AC_CHECK_HEADERS([libv4l2.h], [have_libv4l="yes"])
AS_IF([test "x$have_v4l2" = "xno" && test "x$have_v4l1" = "xno"],
[AC_MSG_FAILURE([test for video support failed!
[AC_MSG_FAILURE([test for video support failed!
rebuild your kernel to include video4linux support or
configure --disable-video to skip building video support.])],
[test "x$have_v4l2" = "xno"],
[AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])])],
[AS_IF([test "x$have_v4l2" = "xno"],
[AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])])]
)],
[AC_CHECK_HEADERS([vfw.h], [with_video="vfw"],
[AC_MSG_FAILURE([test for VfW video support failed!
configure --disable-video to skip building video support.])])])
AS_IF([test "x$have_libv4l" = "xyes"],
PKG_CHECK_MODULES([V4L2], [libv4l2], [],
[AC_MSG_FAILURE([unable to find libv4l.so])]),
[PKG_CHECK_MODULES([V4L2], [libv4l2], [],
[AC_MSG_FAILURE([unable to find libv4l2.so])])],
[AC_MSG_WARN([libv4l not detected. Install it to support more cameras!])])
AM_CONDITIONAL([HAVE_VIDEO], [test "x$enable_video" != "xno"])
......@@ -404,7 +405,7 @@ AS_IF([test "x$with_imagemagick" = "xno"], [],
[MAGICK_VERSION=`$PKG_CONFIG MagickWand --modversion`],
[dnl
dnl Wand is deprecated in favor of MagickWand,
dnl but the latter doesn't exist in older verisons (bug #2848437)
dnl but the latter doesn't exist in older versions (bug #2848437)
saved_error=$MAGICK_PKG_ERRORS
PKG_CHECK_MODULES([MAGICK], [Wand >= 6.2.6],
[MAGICK_VERSION=`$PKG_CONFIG Wand --modversion`],
......
zbar (0.22-1) unstable; urgency=medium
* QA upload.
* New upstream release (2019-02-20).
* debian/patches: Drop all patches, merged upstream.
* debian/control: Also mark libzbar-dev and libzbargtk-dev as
Multi-Arch: same.
-- Boyuan Yang <byang@debian.org> Wed, 20 Feb 2019 10:18:30 -0500
zbar (0.21-3) unstable; urgency=medium
* QA upload.
......
......@@ -44,6 +44,7 @@ Description: bar code scanner and decoder (Perl bindings)
Package: libzbar-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends:
libmagick++-dev,
libx11-dev,
......@@ -74,6 +75,7 @@ Description: bar code scanner and decoder (library)
Package: libzbargtk-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends:
libgtk2.0-dev,
libzbar-dev (= ${binary:Version}),
......
......@@ -7,6 +7,7 @@ libzbar.so.0 libzbar0 #MINVER#
zbar_decoder_create@Base 0.10
zbar_decoder_destroy@Base 0.10
zbar_decoder_get_color@Base 0.10
zbar_decoder_get_config@Base 0.22
zbar_decoder_get_configs@Base 0.21
zbar_decoder_get_data@Base 0.10
zbar_decoder_get_data_length@Base 0.10
......@@ -45,6 +46,7 @@ libzbar.so.0 libzbar0 #MINVER#
zbar_image_scanner_create@Base 0.10
zbar_image_scanner_destroy@Base 0.10
zbar_image_scanner_enable_cache@Base 0.10
zbar_image_scanner_get_config@Base 0.22
zbar_image_scanner_get_results@Base 0.10
zbar_image_scanner_recycle_image@Base 0.10
zbar_image_scanner_request_dbus@Base 0.21
......@@ -124,6 +126,7 @@ libzbar.so.0 libzbar0 #MINVER#
zbar_video_get_fd@Base 0.10
zbar_video_get_format@Base 0.10
zbar_video_get_height@Base 0.10
zbar_video_get_resolutions@Base 0.22
zbar_video_get_width@Base 0.10
zbar_video_init@Base 0.10
zbar_video_next_image@Base 0.10
......
From: Javier Serrano Polo <javier@jasp.net>
Date: Wed, 13 Feb 2019 10:06:11 +0100
Subject: debian, zbar, zbarimg: exit gracefully when decoding split QR codes
Applied-Upstream: https://github.com/mchehab/zbar/commit/dc9f5d1377ac82deab63cdadb0c86b7ecccc3098
Structured QR codes are split in several barcodes. ZBar decodes them if they
are combined in one image; otherwise, it fails with an assert error. Thus,
handle this error gracefully and add a warning hint.
Closes Debian #719013.
Signed-off-by: Javier Serrano Polo <javier@jasp.net>
---
zbar/qrcode/qrdectxt.c | 8 ++++++--
zbarimg/zbarimg.c | 2 ++
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/zbar/qrcode/qrdectxt.c b/zbar/qrcode/qrdectxt.c
index b011dbb..2ab7b9b 100644
--- a/zbar/qrcode/qrdectxt.c
+++ b/zbar/qrcode/qrdectxt.c
@@ -454,8 +454,12 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist,
}
syms->data = sa_text + syms->datalen;
next = (syms->next) ? syms->next->datalen : sa_ntext;
- assert(next > syms->datalen);
- syms->datalen = next - syms->datalen - 1;
+ if (next > syms->datalen)
+ syms->datalen = next - syms->datalen - 1;
+ else {
+ zprintf(1, "Assertion `next > syms->datalen' failed\n");
+ syms->datalen = 0;
+ }
}
if(xmax >= -1) {
sym_add_point(sa_sym, xmin, ymin);
diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c
index bf09d0f..b354747 100644
--- a/zbarimg/zbarimg.c
+++ b/zbarimg/zbarimg.c
@@ -125,6 +125,8 @@ static const char *warning_not_found =
" - is the barcode large enough in the image?\n"
" - is the barcode mostly in focus?\n"
" - is there sufficient contrast/illumination?\n"
+ " - If the symbol is split in several barcodes, are they combined in one "
+ "image?\n"
" - Did you enable the barcode type?\n"
" some EAN/UPC codes are disabled by default. To enable all, use:\n"
" $ zbarimg -S*.enable <files>\n"
From: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Date: Thu, 14 Feb 2019 07:10:57 -0200
Subject: zbar: fix some typos
Applied-Upstream: https://github.com/mchehab/zbar/commit/d27ea213fc0ceb44fe1a244d27ee86dbd0a3881d
Use Linux Kernel's checkpatch.pl script to detect and fix
some typos:
../kernel/checkpatch.pl --test-only=misspelled --codespellfile ../kernel/scripts/spelling.txt $(find . -name *.h) $(find . -name *.c) $(find . -name *.cpp) --fix-inplace
Reported-by: Boyuan Yang
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
include/zbar.h | 4 ++--
include/zbar/Processor.h | 2 +-
zbar/decoder/code128.c | 2 +-
zbar/processor.h | 2 +-
zbar/qrcode/qrdec.c | 2 +-
zbarimg/zbarimg.c | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/include/zbar.h b/include/zbar.h
index de5dec6..5ef8fab 100644
--- a/include/zbar.h
+++ b/include/zbar.h
@@ -924,7 +924,7 @@ static inline int zbar_processor_parse_config (zbar_processor_t *processor,
zbar_processor_set_config(processor, sym, cfg, val));
}
-/** retrieve the current state of the ouput window.
+/** retrieve the current state of the output window.
* @returns 1 if the output window is currently displayed, 0 if not.
* @returns -1 if an error occurs
*/
@@ -987,7 +987,7 @@ extern int zbar_process_image(zbar_processor_t *processor,
zbar_image_t *image);
/** enable dbus IPC API.
- * @returns 0 succesful
+ * @returns 0 successful
*/
int zbar_processor_request_dbus(zbar_processor_t *proc,
int req_dbus_enabled);
diff --git a/include/zbar/Processor.h b/include/zbar/Processor.h
index 2622ee8..cb99adf 100644
--- a/include/zbar/Processor.h
+++ b/include/zbar/Processor.h
@@ -101,7 +101,7 @@ class Processor {
return(zbar_processor_parse_config(_processor, cfgstr.c_str()));
}
- /// retrieve the current state of the ouput window.
+ /// retrieve the current state of the output window.
/// see zbar_processor_is_visible()
bool is_visible ()
{
diff --git a/zbar/decoder/code128.c b/zbar/decoder/code128.c
index 9dd28e0..bd1ae12 100644
--- a/zbar/decoder/code128.c
+++ b/zbar/decoder/code128.c
@@ -283,7 +283,7 @@ static inline unsigned postprocess_c (zbar_decoder_t *dcode,
{
unsigned i, j;
- /* expand buffer to accomodate 2x set C characters (2 digits per-char) */
+ /* expand buffer to accommodate 2x set C characters (2 digits per-char) */
unsigned delta = end - start;
unsigned newlen = dcode->code128.character + delta;
if (size_buf(dcode, newlen)) {
diff --git a/zbar/processor.h b/zbar/processor.h
index e311d98..d5e9fef 100644
--- a/zbar/processor.h
+++ b/zbar/processor.h
@@ -56,7 +56,7 @@ typedef struct proc_waiter_s {
/* high-level API events */
#define EVENT_INPUT 0x01 /* user input */
#define EVENT_OUTPUT 0x02 /* decoded output data available */
-#define EVENT_CANCELED 0x80 /* cancelation flag */
+#define EVENT_CANCELED 0x80 /* cancellation flag */
#define EVENTS_PENDING (EVENT_INPUT | EVENT_OUTPUT)
struct zbar_processor_s {
diff --git a/zbar/qrcode/qrdec.c b/zbar/qrcode/qrdec.c
index 5d3d265..2bf7e07 100644
--- a/zbar/qrcode/qrdec.c
+++ b/zbar/qrcode/qrdec.c
@@ -531,7 +531,7 @@ static void qr_line_fit(qr_line _l,int _x0,int _y0,
v=-_sxy<<1;
w=qr_ihypot(u,v);
/*Computations in later stages can easily overflow with moderate sizes, so we
- compute a shift factor to scale things down into a managable range.
+ compute a shift factor to scale things down into a manageable range.
We ensure that the product of any two of _l[0] and _l[1] fits within _res
bits, which allows computation of line intersections without overflow.*/
dshift=QR_MAXI(0,QR_MAXI(qr_ilog(u),qr_ilog(abs(v)))+1-(_res+1>>1));
diff --git a/zbarimg/zbarimg.c b/zbarimg/zbarimg.c
index b354747..171c555 100644
--- a/zbarimg/zbarimg.c
+++ b/zbarimg/zbarimg.c
@@ -131,7 +131,7 @@ static const char *warning_not_found =
" some EAN/UPC codes are disabled by default. To enable all, use:\n"
" $ zbarimg -S*.enable <files>\n"
" Please also notice that some variants take precedence over others.\n"
- " Due to that, if you want, for example, ISBN-10, you shoud do:\n"
+ " Due to that, if you want, for example, ISBN-10, you should do:\n"
" $ zbarimg -Sisbn10.enable <files>\n"
"\n";
From: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Date: Fri, 15 Feb 2019 04:56:11 -0200
Subject: configure.ac: fix an error at libv4l2 package check
Writing m4 logic is hard, as it is required to properly
mark begin/end of each block.
In the case of the libv4l detection check, there's a missing
[] for PKG_CHECK_MODULES(). This causes it to produce a wrong
code, ending by having 2 errors when the script runs:
checking for libv4l2.h... yes
./configure: line 15166: V4L2_CFLAGS: command not found
./configure: line 15167: V4L2_LIBS: command not found
While here, better ident the blocks and fix the error message
when libv4l2.so is not found.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
configure.ac | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/configure.ac b/configure.ac
index da334e7..7e9cac6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -241,18 +241,19 @@ AS_IF([test "x$enable_video" = "xno"],
AC_CHECK_HEADERS([linux/videodev2.h], [have_v4l2="yes"])
AC_CHECK_HEADERS([libv4l2.h], [have_libv4l="yes"])
AS_IF([test "x$have_v4l2" = "xno" && test "x$have_v4l1" = "xno"],
- [AC_MSG_FAILURE([test for video support failed!
+ [AC_MSG_FAILURE([test for video support failed!
rebuild your kernel to include video4linux support or
configure --disable-video to skip building video support.])],
- [test "x$have_v4l2" = "xno"],
- [AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])])],
+ [AS_IF([test "x$have_v4l2" = "xno"],
+ [AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])])]
+ )],
[AC_CHECK_HEADERS([vfw.h], [with_video="vfw"],
[AC_MSG_FAILURE([test for VfW video support failed!
configure --disable-video to skip building video support.])])])
AS_IF([test "x$have_libv4l" = "xyes"],
- PKG_CHECK_MODULES([V4L2], [libv4l2], [],
- [AC_MSG_FAILURE([unable to find libv4l.so])]),
+ [PKG_CHECK_MODULES([V4L2], [libv4l2], [],
+ [AC_MSG_FAILURE([unable to find libv4l2.so])])],
[AC_MSG_WARN([libv4l not detected. Install it to support more cameras!])])
AM_CONDITIONAL([HAVE_VIDEO], [test "x$enable_video" != "xno"])
This diff is collapsed.
0001-debian-zbar-zbarimg-exit-gracefully-when-decoding-sp.patch
0002-zbar-fix-some-typos.patch
0003-configure.ac-fix-an-error-at-libv4l2-package-check.patch
0004-Fix-typos-found-by-codespell.patch
......@@ -121,6 +121,17 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>test-inverted</option></term>
<listitem>
<simpara>Specially for QR code images, sometimes the image
is inverted, e. g. lines are written in white instead of black.
This option makes ZBar to invert the image and parse again, in
case it fails using the normal order. Enabling it affects all
decoders.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><option>min-length=<replaceable class="parameter">n</replaceable></option></term>
<term><option>max-length=<replaceable class="parameter">n</replaceable></option></term>
......
......@@ -10,8 +10,9 @@ aebbdbed0b32d7fd72f1245e3fb384822d492062 zbarimg databar.png
b350ca7efad7a50c5ac082d5c683a8e8d8d380a7 zbarimg qr-code.png
84c0ce7072e2227073dc8bd1e5f4518d8f42ae3d zbarimg sqcode1-generated.png
84c0ce7072e2227073dc8bd1e5f4518d8f42ae3d zbarimg sqcode1-scanned.png
5ab2b518e2c9d827cedc5825d2e3c9646d43713a zbarimg ean2 ean-2.png
668fef8cb9caac34df8cb8564c2cde62e4af5e65 zbarimg ean5 ean-5.png
b567e550216fe24f7652f683146365a9fe7ee867 zbarimg isbn10 ean-13.png
d0f37aa076d42c270f7231c5490beea5605e2ba0 zbarimg isbn13 ean-13.png
3f041225df3b8364b5fd0daf9cf402e8a4731f9b zbarimg upca code-upc-a.png
5ab2b518e2c9d827cedc5825d2e3c9646d43713a zbarimg -Sean2.enable ean-2.png
668fef8cb9caac34df8cb8564c2cde62e4af5e65 zbarimg -Sean5.enable ean-5.png
b567e550216fe24f7652f683146365a9fe7ee867 zbarimg -Sisbn10.enable ean-13.png
d0f37aa076d42c270f7231c5490beea5605e2ba0 zbarimg -Sisbn13.enable ean-13.png
3f041225df3b8364b5fd0daf9cf402e8a4731f9b zbarimg -Supca.enable code-upc-a.png
b350ca7efad7a50c5ac082d5c683a8e8d8d380a7 zbarimg -Stest-inverted qr-code-inverted.png
......@@ -108,6 +108,11 @@ typedef enum zbar_symbol_type_e {
ZBAR_CODE93 = 93, /**< Code 93. @since 0.11 */
ZBAR_CODE128 = 128, /**< Code 128 */
/*
* Please see _zbar_get_symbol_hash() if adding
* anything after 128
*/
/** mask for base symbol type.
* @deprecated in 0.11, remove this from existing code
*/
......@@ -174,6 +179,7 @@ typedef enum zbar_config_e {
ZBAR_CFG_UNCERTAINTY = 0x40,/**< required video consistency frames */
ZBAR_CFG_POSITION = 0x80, /**< enable scanner to collect position data */
ZBAR_CFG_TEST_INVERTED, /**< if fails to decode, test inverted */
ZBAR_CFG_X_DENSITY = 0x100, /**< image scanner vertical scan density */
ZBAR_CFG_Y_DENSITY, /**< image scanner horizontal scan density */
......@@ -244,6 +250,17 @@ typedef struct video_controls_s {
// video drivers may add extra private data in the end of this struct
} video_controls_t;
/** store a video resolution
* @param width width of the video window
* @param height length of the video window
* @param max_fps maximum streaming speed, in frames per second
* @since 0.22
*/
struct video_resolution_s {
unsigned int width, height;
float max_fps;
};
/** retrieve runtime library version information.
* @param major set to the running major version (unless NULL)
* @param minor set to the running minor version (unless NULL)
......@@ -924,7 +941,7 @@ static inline int zbar_processor_parse_config (zbar_processor_t *processor,
zbar_processor_set_config(processor, sym, cfg, val));
}
/** retrieve the current state of the ouput window.
/** retrieve the current state of the output window.
* @returns 1 if the output window is currently displayed, 0 if not.
* @returns -1 if an error occurs
*/
......@@ -987,7 +1004,7 @@ extern int zbar_process_image(zbar_processor_t *processor,
zbar_image_t *image);
/** enable dbus IPC API.
* @returns 0 succesful
* @returns 0 successful
*/
int zbar_processor_request_dbus(zbar_processor_t *proc,
int req_dbus_enabled);
......@@ -1141,6 +1158,14 @@ extern struct video_controls_s
*zbar_video_get_controls (const zbar_video_t *video,
int index);
/** get available video resolutions from video source
* @returns 0 for success, non-0 for failure
* @since 0.22
*/
extern struct video_resolution_s
*zbar_video_get_resolutions (const zbar_video_t *vdo,
int index);
/** display detail for last video error to stderr.
* @returns a non-zero value suitable for passing to exit()
*/
......@@ -1311,6 +1336,16 @@ extern int zbar_image_scanner_set_config(zbar_image_scanner_t *scanner,
zbar_config_t config,
int value);
/** get config for indicated symbology
* @returns 0 for success, non-0 for failure (config does not apply to
* specified symbology, or value out of range). On success, *value is filled.
* @since 0.22
*/
extern int zbar_image_scanner_get_config(zbar_image_scanner_t *scanner,
zbar_symbol_type_t symbology,
zbar_config_t config,
int *value);
/** parse configuration string using zbar_parse_config()
* and apply to image scanner using zbar_image_scanner_set_config().
* @returns 0 for success, non-0 for failure
......@@ -1403,6 +1438,17 @@ extern int zbar_decoder_set_config(zbar_decoder_t *decoder,
zbar_config_t config,
int value);
/** get config for indicated symbology
* @returns 0 for success, non-0 for failure (config does not apply to
* specified symbology, or value out of range). On success, *value is filled.
* @since 0.22
*/
extern int zbar_decoder_get_config(zbar_decoder_t *decoder,
zbar_symbol_type_t symbology,
zbar_config_t config,
int *value);
/** parse configuration string using zbar_parse_config()
* and apply to decoder using zbar_decoder_set_config().
* @returns 0 for success, non-0 for failure
......
......@@ -84,6 +84,17 @@ public:
config, value));
}
/// set config for indicated symbology (0 for all) to specified value.
/// @see zbar_image_scanner_set_config()
/// @since 0.22
int get_config (zbar_symbol_type_t symbology,
zbar_config_t config,
int &value)
{
return(zbar_image_scanner_get_config(_scanner, symbology,
config, &value));
}
/// set config parsed from configuration string.
/// @see zbar_image_scanner_parse_config()
/// @since 0.4
......
......@@ -101,7 +101,7 @@ class Processor {
return(zbar_processor_parse_config(_processor, cfgstr.c_str()));
}
/// retrieve the current state of the ouput window.
/// retrieve the current state of the output window.
/// see zbar_processor_is_visible()
bool is_visible ()
{
......
......@@ -159,6 +159,13 @@ public Q_SLOTS:
int set_config(zbar_symbol_type_t symbology,
zbar_config_t config,
int value);
int get_config(zbar_symbol_type_t symbology,
zbar_config_t config,
int &value);
void request_size(unsigned width, unsigned height, bool trigger = true);
int get_resolution(int index, unsigned &width, unsigned &height, float &max_fps);
unsigned videoWidth();
unsigned videoHeight();
int request_dbus(bool enabled);
Q_SIGNALS:
......
......@@ -210,6 +210,14 @@ public:
return ret;
}
/// get the information about a control at a given index
/// see zbar_video_get_resolutions()
/// @since 0.22
struct video_resolution_s *get_resolution(int index)
{
return(zbar_video_get_resolutions(_video, index));
}
private:
zbar_video_t *_video;
};
......
......@@ -8,7 +8,7 @@ version 1.3.1:
* Lion and Xcode updates
- fix new warnings/errors
- find missing buddy
- fix SDK bg image: force resoution to 72dpi
- fix SDK bg image: force resolution to 72dpi
* Fix EmbedReader example rotation interaction
version 1.2.2:
......
......@@ -152,7 +152,7 @@ Class Methods
Returns an array with the single element
``UIImagePickerControllerCameraCaptureModeVideo`` if the device is
avilable, otherwise returns an empty array.
available, otherwise returns an empty array.
Instance Methods
......
......@@ -144,7 +144,7 @@ Additionally, to avoid "casual requests" from nefarious types that just want
to inconvenience you, also consider charging a fee for the distribution of
this material (as permitted by the license); just add up the cost of burning
and shipping a disk. If this cost is "large" compared to the price of your
app, the likelyhood of a request is reduced even further.
app, the likelihood of a request is reduced even further.
Using the Unmodified Library
......
......@@ -161,7 +161,7 @@ default setting.
For some devices, the "torch" can be enabled to provide additional
illumination for the camera in low-light conditions. The reader sets the
torch to automatic by default, so it should turn on only when needeed...
torch to automatic by default, so it should turn on only when needed...
There have been some reports that the torch turns on inappropriately, washing
out the image. If you find that this occurs, you should instead set the
:member:`~ZBarReaderView::torchMode` property of the :class:`ZBarReaderView`
......@@ -244,7 +244,7 @@ the image. The density of the passes is configured at the scanner as a pixel
stride for each axis. ``ZBAR_CFG_Y_DENSITY`` (``ZBAR_CFG_X_DENSITY``)
controls the number of pixel rows (columns) that are skipped between
successive horizontal (vertical) scan passes. (Note that "density" is really
not a good name for the configuation settings... "stride" might be more
not a good name for the configuration settings... "stride" might be more
appropriate.)
Decreasing the scan density (by increasing the stride setting) is a great way
......
......@@ -57,7 +57,7 @@ video and to optionally display a video/image preview to a window.
This interface is not well suited for integration with an existing
GUI, as the library manages the optional preview window and any user
interaction. Use a Barcode::ZBar::ImageScanner or Investigate the
avilable widget interfaces for GUI applications.
available widget interfaces for GUI applications.
=head1 REFERENCE
......
......@@ -91,7 +91,7 @@ A negative value indicates that this result is still uncertain
=item *
A zero value indicates the first occurance of this result with high
A zero value indicates the first occurrence of this result with high
confidence
=item *
......
......@@ -114,7 +114,7 @@ incpaths, each preceded by '-I'.
=head2 check_lib_or_exit
This behaves exactly the same as C<assert_lib()> except that instead of
dieing, it warns (with exactly the same error message) and exits.
dying, it warns (with exactly the same error message) and exits.
This is intended for use in Makefile.PL / Build.PL
when you might want to prompt the user for various paths and
things before checking that what they've told you is sane.
......
......@@ -112,6 +112,40 @@ int QZBar::get_controls(int index, char **name, char **group,
min, max, def, step);
}
void QZBar::request_size(unsigned width, unsigned height, bool trigger)
{
if(!thread)
return;
thread->request_size(width, height);
if (trigger)
thread->pushEvent(new QEvent((QEvent::Type)QZBarThread::ReOpen));
}
int QZBar::get_resolution(int index, unsigned &width, unsigned &height, float &max_fps)
{
if(!thread)
return 0;
return thread->get_resolution(index, width, height, max_fps);
}
unsigned QZBar::videoWidth()
{
if(!thread)
return 0;
return thread->reqWidth;
}
unsigned QZBar::videoHeight()
{
if(!thread)
return 0;
return thread->reqHeight;
}
QVector< QPair< int , QString > > QZBar::get_menu(int index)
{
if(!thread) {
......@@ -173,6 +207,16 @@ int QZBar::set_config(zbar_symbol_type_t symbology,
return thread->set_config(symbology, config, value);
}
int QZBar::get_config(zbar_symbol_type_t symbology,
zbar_config_t config,
int &value)
{
if(!thread)
return 0;
return thread->get_config(symbology, config, value);
}
int QZBar::request_dbus(bool enabled)
{
if(!thread)
......
......@@ -102,8 +102,6 @@ void QZBarThread::openVideo (const QString &device)
{
QMutexLocker locker(&mutex);
videoEnabled = _videoOpened = false;
reqWidth = DEFAULT_WIDTH;
reqHeight = DEFAULT_HEIGHT;
}
// ensure old video doesn't have image ref
......@@ -123,6 +121,10 @@ void QZBarThread::openVideo (const QString &device)
try {
std::string devstr = device.toStdString();
video = new Video(devstr);
if (reqWidth != DEFAULT_WIDTH || reqHeight != DEFAULT_HEIGHT)
video->request_size(reqWidth, reqHeight);
negotiate_format(*video, window);
{
QMutexLocker locker(&mutex);
......@@ -130,6 +132,8 @@ void QZBarThread::openVideo (const QString &device)
reqWidth = video->get_width();
reqHeight = video->get_height();
}
currentDevice = device;
emit videoOpened(true);
}
catch(std::exception &e) {
......@@ -138,7 +142,6 @@ void QZBarThread::openVideo (const QString &device)
}
}
void QZBarThread::videoDeviceEvent (VideoDeviceEvent *e)
{
openVideo(e->device);
......@@ -183,6 +186,9 @@ bool QZBarThread::event (QEvent *e)
enableVideo(false);
running = false;
break;
case ReOpen:
openVideo(currentDevice);
break;
default:
return(false);
}
......@@ -338,3 +344,27 @@ int QZBarThread::get_control(char *name, int *value)
return video->get_control(name, value);
}
void QZBarThread::request_size(unsigned width, unsigned height)
{
reqWidth = width;
reqHeight = height;
}
int QZBarThread::get_resolution(int index, unsigned &width, unsigned &height, float &max_fps)
{
struct video_resolution_s *res;
if(!video)
return 0;
res = video->get_resolution(index);
if (!res)
return 0;
width = res->width;
height = res->height;
max_fps = res->max_fps;
return 1;
}
......@@ -47,6 +47,7 @@ public:
VideoDevice = QEvent::User,
VideoEnabled,
ScanImage,
ReOpen,
Exit = QEvent::MaxUser
};
......@@ -124,6 +125,17 @@ public:
return scanner.set_config(symbology, config, value);
}
int get_config(zbar_symbol_type_t symbology,
zbar_config_t config,
int &value)
{
return scanner.get_config(symbology, config, value);
}
void request_size(unsigned width, unsigned height);
int get_resolution(int index, unsigned &width, unsigned &height, float &max_fps);
int request_dbus(bool enabled)
{
return scanner.request_dbus(enabled);
......@@ -169,6 +181,7 @@ private:
Video *video;
ImageScanner scanner;
QZBarImage *image;
QString currentDevice;
bool running;
bool videoRunning;
bool videoEnabled;
......
......@@ -70,11 +70,12 @@ ZBARIMG = @abs_top_builddir@/zbarimg/zbarimg --nodbus
gen_checksum: all
for i in $(NORMAL_IMAGES); do $(ZBARIMG) $(EXAMPLES)/$$i 2>/dev/null|sha1sum|sed "s,-,zbarimg $$i,"; done >$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sean2.enable $(EXAMPLES)/ean-2.png 2>/dev/null|sha1sum|sed "s,-,zbarimg ean2 ean-2.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sean5.enable $(EXAMPLES)/ean-5.png 2>/dev/null|sha1sum|sed "s,-,zbarimg ean5 ean-5.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sisbn10.enable $(EXAMPLES)/ean-13.png 2>/dev/null|sha1sum|sed "s,-,zbarimg isbn10 ean-13.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sisbn13.enable $(EXAMPLES)/ean-13.png 2>/dev/null|sha1sum|sed "s,-,zbarimg isbn13 ean-13.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Supca.enable $(EXAMPLES)/code-upc-a.png 2>/dev/null|sha1sum|sed "s,-,zbarimg upca code-upc-a.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sean2.enable $(EXAMPLES)/ean-2.png 2>/dev/null|sha1sum|sed "s,-,zbarimg -Sean2.enable ean-2.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sean5.enable $(EXAMPLES)/ean-5.png 2>/dev/null|sha1sum|sed "s,-,zbarimg -Sean5.enable ean-5.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sisbn10.enable $(EXAMPLES)/ean-13.png 2>/dev/null|sha1sum|sed "s,-,zbarimg -Sisbn10.enable ean-13.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Sisbn13.enable $(EXAMPLES)/ean-13.png 2>/dev/null|sha1sum|sed "s,-,zbarimg -Sisbn13.enable ean-13.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Supca.enable $(EXAMPLES)/code-upc-a.png 2>/dev/null|sha1sum|sed "s,-,zbarimg -Supca.enable code-upc-a.png," >>$(EXAMPLES)/sha1sum
$(ZBARIMG) -Stest-inverted $(EXAMPLES)/qr-code-inverted.png 2>/dev/null|sha1sum|sed "s,-,zbarimg -Stest-inverted qr-code-inverted.png," >>$(EXAMPLES)/sha1sum
test_progs: $(check_PROGRAMS)
@$(MAKE) $(check_PROGRAMS)
......
......@@ -15,7 +15,7 @@ test()
j="$1"
fi;
if [ "$2" != "" ]; then
CMD="$ZBARIMG -S$1.enable"
CMD="$ZBARIMG $1"
else
CMD="$ZBARIMG"
fi
......@@ -53,13 +53,13 @@ if [ "@ENABLE_DATABAR@" == "1" ]; then
fi
if [ "@ENABLE_EAN@" == "1" ]; then
test ean2 ean-2.png
test ean5 ean-5.png
test -Sean2.enable ean-2.png
test -Sean5.enable ean-5.png
test ean-8.png
test ean-13.png
test isbn10 ean-13.png
test isbn13 ean-13.png
test upca code-upc-a.png
test -Sisbn10.enable ean-13.png
test -Sisbn13.enable ean-13.png
test -Supca.enable code-upc-a.png
fi
if [ "@ENABLE_I25@" == "1" ]; then
......@@ -68,11 +68,12 @@ fi
if [ "@ENABLE_QRCODE@" == "1" ]; then
test qr-code.png
test -Stest-inverted qr-code-inverted.png
fi
if [ "@ENABLE_SQCODE@" == "1" ]; then
test sqcode1-generated.png
test sqcode1-scanned.png
test sqcode1-scanned.png
fi
# The pdf417 code is incomplete: it doesn't output any results
......
......@@ -149,6 +149,8 @@ int zbar_parse_config (const char *cfgstr,
*cfg = ZBAR_CFG_EMIT_CHECK;
else if(!strncmp(cfgstr, "uncertainty", len))
*cfg = ZBAR_CFG_UNCERTAINTY;
else if(!strncmp(cfgstr, "test-inverted", len))
*cfg = ZBAR_CFG_TEST_INVERTED;
else if(!strncmp(cfgstr, "position", len))
*cfg = ZBAR_CFG_POSITION;
else
......
......@@ -488,6 +488,63 @@ static inline int decoder_set_config_int (zbar_decoder_t *dcode,
return(0);
}
int zbar_decoder_get_config(zbar_decoder_t *dcode,
zbar_symbol_type_t sym,
zbar_config_t cfg,
int *val)
{
const unsigned *config = decoder_get_configp(dcode, sym);
/* Return error if symbol doesn't have config */
if(sym <= ZBAR_PARTIAL || sym > ZBAR_CODE128 || sym == ZBAR_COMPOSITE)
return 1;
/* Return decoder boolean configs */
if (cfg < ZBAR_CFG_NUM) {
*val = (*config & (1 << cfg)) != 0;
return 0;
}
/* Return decoder integer configs */
if(cfg >= ZBAR_CFG_MIN_LEN && cfg <= ZBAR_CFG_MAX_LEN) {
switch(sym) {
#if ENABLE_I25 == 1
case ZBAR_I25:
*val = CFG(dcode->i25, cfg);
return 0;
#endif
#if ENABLE_CODABAR == 1
case ZBAR_CODABAR:
*val = CFG(dcode->codabar, cfg);
return 0;
#endif
#if ENABLE_CODE39 == 1
case ZBAR_CODE39:
*val = CFG(dcode->code39, cfg);
return 0;
#endif
#if ENABLE_CODE93 == 1
case ZBAR_CODE93:
*val = CFG(dcode->code93, cfg);
return 0;
#endif
#if ENABLE_CODE128 == 1
case ZBAR_CODE128:
*val = CFG(dcode->code128, cfg);
return 0;
#endif
#if ENABLE_PDF417 == 1
case ZBAR_PDF417:
*val = CFG(dcode->pdf417, cfg);
return 0;
#endif
default:
return 1;
}
}
return 1;
}
int zbar_decoder_set_config (zbar_decoder_t *dcode,
zbar_symbol_type_t sym,
zbar_config_t cfg,
......
......@@ -283,7 +283,7 @@ static inline unsigned postprocess_c (zbar_decoder_t *dcode,
{
unsigned i, j;
/* expand buffer to accomodate 2x set C characters (2 digits per-char) */
/* expand buffer to accommodate 2x set C characters (2 digits per-char) */
unsigned delta = end - start;
unsigned newlen = dcode->code128.character + delta;
if (size_buf(dcode, newlen)) {
......
......@@ -201,15 +201,7 @@ void *zbar_image_get_userdata (const zbar_image_t *img)
zbar_image_t *zbar_image_copy (const zbar_image_t *src)
{
zbar_image_t *dst = zbar_image_create();
dst->format = src->format;
_zbar_image_copy_size(dst, src);
dst->datalen = src->datalen;
dst->data = malloc(src->datalen);
assert(dst->data);
memcpy((void*)dst->data, src->data, src->datalen);
dst->cleanup = zbar_image_free_data;
return(dst);
return _zbar_image_copy(src, 0);
}
const zbar_symbol_set_t *zbar_image_get_symbols (const zbar_image_t *img)
......
......@@ -139,4 +139,42 @@ static inline void _zbar_image_copy_size (zbar_image_t *dst,
dst->crop_h = src->crop_h;
}
static inline zbar_image_t *_zbar_image_copy (const zbar_image_t *src,
int inverted)
{
zbar_image_t *dst;
if (inverted && (src->format != fourcc('Y','8','0','0'))
&& (src->format != fourcc('G','R','E','Y')) )
return NULL;
dst = zbar_image_create();
dst->format = src->format;
_zbar_image_copy_size(dst, src);
dst->datalen = src->datalen;
dst->data = malloc(src->datalen);
assert(dst->data);
if (!inverted) {
memcpy((void*)dst->data, src->data, src->datalen);
} else {
int i, len = src->datalen;
long *sp = (void *)src->data, *dp = (void *)dst->data;
char *spc, *dpc;
/* Do it word per word, in order to speedup */
for (i = 0; i < len; i+= sizeof(long))
*dp++ = ~(*sp++);
/* Deal with non-aligned remains, if any */
len -= i;
spc = (char *)sp;
dpc = (char *)dp;
for (i = 0; i < len; i++)
*dpc++ = ~(*spc++);
}
dst->cleanup = zbar_image_free_data;
return(dst);
}
#endif
......@@ -517,6 +517,7 @@ zbar_image_scanner_t *zbar_image_scanner_create ()
CFG(iscn, ZBAR_CFG_Y_DENSITY) = 1;
zbar_image_scanner_set_config(iscn, 0, ZBAR_CFG_POSITION, 1);
zbar_image_scanner_set_config(iscn, 0, ZBAR_CFG_UNCERTAINTY, 2);
zbar_image_scanner_set_config(iscn, 0, ZBAR_CFG_TEST_INVERTED, 0);
zbar_image_scanner_set_config(iscn, ZBAR_QRCODE, ZBAR_CFG_UNCERTAINTY, 0);
zbar_image_scanner_set_config(iscn, ZBAR_CODE128, ZBAR_CFG_UNCERTAINTY, 0);
zbar_image_scanner_set_config(iscn, ZBAR_CODE93, ZBAR_CFG_UNCERTAINTY, 0);
......@@ -621,6 +622,7 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn,
return(0);
}
/* Image scanner parameters apply only to ZBAR_PARTIAL */
if(sym > ZBAR_PARTIAL)
return(1);
......@@ -629,8 +631,6 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn,
return(0);
}
if(cfg > ZBAR_CFG_POSITION)
return(1);
cfg -= ZBAR_CFG_POSITION;
if(!val)
......@@ -643,6 +643,45 @@ int zbar_image_scanner_set_config (zbar_image_scanner_t *iscn,
return(0);
}
int zbar_image_scanner_get_config(zbar_image_scanner_t *iscn,
zbar_symbol_type_t sym,
zbar_config_t cfg,
int *val)
{
/* Return error if symbol doesn't have config */
if(sym < ZBAR_PARTIAL || sym > ZBAR_CODE128 || sym == ZBAR_COMPOSITE)
return 1;
if (cfg < ZBAR_CFG_UNCERTAINTY)
return zbar_decoder_get_config(iscn->dcode, sym, cfg, val);
if(cfg < ZBAR_CFG_POSITION) {
if(sym == ZBAR_PARTIAL)
return(1);
int i = _zbar_get_symbol_hash(sym);
*val = iscn->sym_configs[cfg - ZBAR_CFG_UNCERTAINTY][i];
return 0;
}
/* Image scanner parameters apply only to ZBAR_PARTIAL */
if(sym > ZBAR_PARTIAL)
return(1);
if(cfg < ZBAR_CFG_X_DENSITY) {
*val = (iscn->config & (1 << (cfg - ZBAR_CFG_POSITION))) != 0;
return 0;
}
if(cfg <= ZBAR_CFG_Y_DENSITY) {
*val = CFG(iscn, cfg);
return 0;
}
return 1;
}
void zbar_image_scanner_enable_cache (zbar_image_scanner_t *iscn,
int enable)
{
......@@ -814,8 +853,8 @@ static void zbar_send_code_via_dbus(zbar_image_t *img)
p += (dx) + ((uintptr_t)(dy) * w); \
} while(0);
int zbar_scan_image (zbar_image_scanner_t *iscn,
zbar_image_t *img)
static void *_zbar_scan_image(zbar_image_scanner_t *iscn,
zbar_image_t *img)
{
zbar_symbol_set_t *syms;
const uint8_t *data;
......@@ -839,7 +878,7 @@ int zbar_scan_image (zbar_image_scanner_t *iscn,
/* image must be in grayscale format */
if(img->format != fourcc('Y','8','0','0') &&
img->format != fourcc('G','R','E','Y'))
return(-1);
return NULL;
iscn->img = img;
/* recycle previous scanner and image results */
......@@ -1067,6 +1106,31 @@ int zbar_scan_image (zbar_image_scanner_t *iscn,
_zbar_image_scanner_add_sym(iscn, ean_sym);
}
}
return syms;
}
int zbar_scan_image(zbar_image_scanner_t *iscn,
zbar_image_t *img)
{
zbar_symbol_set_t *syms;
zbar_image_t *inv = NULL;
syms = _zbar_scan_image(iscn, img);
if (!syms)
return -1;
if(!syms->nsyms && TEST_CFG(iscn, ZBAR_CFG_TEST_INVERTED)) {
inv = _zbar_image_copy (img, 1);
if (inv) {
if(iscn->cache) {
/* recycle all cached syms, if any */
_zbar_image_scanner_recycle_syms(iscn, iscn->cache);
iscn->cache = NULL;
}
syms = _zbar_scan_image(iscn, inv);
_zbar_image_swap_symbols(img, inv);
}
}
if(syms->nsyms && iscn->handler)
iscn->handler(img, iscn->userdata);
......@@ -1076,6 +1140,10 @@ int zbar_scan_image (zbar_image_scanner_t *iscn,
#endif
svg_close();
if (inv)
zbar_image_destroy(inv);
return(syms->nsyms);
}
......
......@@ -56,7 +56,7 @@ typedef struct proc_waiter_s {
/* high-level API events */
#define EVENT_INPUT 0x01 /* user input */
#define EVENT_OUTPUT 0x02 /* decoded output data available */
#define EVENT_CANCELED 0x80 /* cancelation flag */
#define EVENT_CANCELED 0x80 /* cancellation flag */
#define EVENTS_PENDING (EVENT_INPUT | EVENT_OUTPUT)
struct zbar_processor_s {
......
......@@ -531,7 +531,7 @@ static void qr_line_fit(qr_line _l,int _x0,int _y0,
v=-_sxy<<1;
w=qr_ihypot(u,v);
/*Computations in later stages can easily overflow with moderate sizes, so we
compute a shift factor to scale things down into a managable range.
compute a shift factor to scale things down into a manageable range.
We ensure that the product of any two of _l[0] and _l[1] fits within _res
bits, which allows computation of line intersections without overflow.*/
dshift=QR_MAXI(0,QR_MAXI(qr_ilog(u),qr_ilog(abs(v)))+1-(_res+1>>1));
......
......@@ -454,8 +454,12 @@ int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist,
}
syms->data = sa_text + syms->datalen;
next = (syms->next) ? syms->next->datalen : sa_ntext;
assert(next > syms->datalen);
syms->datalen = next - syms->datalen - 1;
if (next > syms->datalen)
syms->datalen = next - syms->datalen - 1;
else {
zprintf(1, "Assertion `next > syms->datalen' failed\n");
syms->datalen = 0;
}
}
if(xmax >= -1) {
sym_add_point(sa_sym, xmin, ymin);
......
......@@ -392,7 +392,7 @@ static void rs_calc_syndrome(const rs_gf256 *_gf,int _m0,
Error correction is done using the error-evaluator equation on p. 207.
@BOOK{CC81,
author="George C. Clark, Jr and J. Bibb Cain",
title="Error-Correction Coding for Digitial Communications",
title="Error-Correction Coding for Digital Communications",
series="Applications of Communications Theory",
publisher="Springer",
address="New York, NY",
......
......@@ -32,7 +32,7 @@ unsigned qr_isqrt(unsigned _val){
/*Computes sqrt(_x*_x+_y*_y) using CORDIC.
This implementation is valid for all 32-bit inputs and returns a result
accurate to about 27 bits of precision.
It has been tested for all postiive 16-bit inputs, where it returns correctly
It has been tested for all positive 16-bit inputs, where it returns correctly
rounded results in 99.998% of cases and the maximum error is
0.500137134862598032 (for _x=48140, _y=63018).
Very nearly all results less than (1<<16) are correctly rounded.
......
......@@ -99,18 +99,40 @@ const char *zbar_get_orientation_name (zbar_orientation_t orient)
int _zbar_get_symbol_hash (zbar_symbol_type_t sym)
{
static const signed char hash[0x20] = {
0x00, 0x01, 0x10, 0x11, -1, 0x11, 0x16, 0x0c,
0x05, 0x06, 0x08, -1, 0x04, 0x03, 0x07, 0x12,
-1, -1, -1, -1, -1, -1, -1, 0x02,
-1, 0x00, 0x12, 0x0c, 0x0b, 0x1d, 0x0a, 0x00,
};
int g0 = hash[sym & 0x1f];
int g1 = hash[~(sym >> 4) & 0x1f];
assert(g0 >= 0 && g1 >= 0);
if(g0 < 0 || g1 < 0)
return(0);
return((g0 + g1) & 0x1f);
static const signed char hash[ZBAR_CODE128 + 1] = {
[0 ... ZBAR_CODE128] = -1,
/* [ZBAR_FOO] = 0, is empty */
[ZBAR_SQCODE] = 1,
[ZBAR_CODE128] = 2,
[ZBAR_EAN13] = 3,
[ZBAR_UPCA] = 4,
[ZBAR_EAN8] = 5,
[ZBAR_UPCE] = 6,
[ZBAR_ISBN13] = 7,
[ZBAR_ISBN10] = 8,
[ZBAR_CODE39] = 9,
[ZBAR_I25] = 10,
[ZBAR_PDF417] = 11,
[ZBAR_QRCODE] = 12,
[ZBAR_DATABAR] = 13,
[ZBAR_DATABAR_EXP] = 14,
[ZBAR_CODE93] = 15,
[ZBAR_EAN2] = 16,
[ZBAR_EAN5] = 17,
[ZBAR_COMPOSITE] = 18,
[ZBAR_CODABAR] = 19,
/* Please update NUM_SYMS accordingly */
};
int h;
assert (sym >= ZBAR_PARTIAL && sym <= ZBAR_CODE128);
h = hash[sym];
assert (h >= 0 && h < NUM_SYMS);
return h;
}
void _zbar_symbol_free (zbar_symbol_t *sym)
......
......@@ -438,3 +438,22 @@ struct video_controls_s *zbar_video_get_controls (const zbar_video_t *vdo,
return p;
}
struct video_resolution_s *zbar_video_get_resolutions (const zbar_video_t *vdo,
int index)
{
int i = 0;
struct video_resolution_s *p = vdo->res;
while (i != index) {
if (!p->width || !p->height)
return NULL;
i++;
p++;
}
if (!p->width || !p->height)
return NULL;
return p;
}
......@@ -71,6 +71,8 @@ struct zbar_video_s {
uint32_t *formats; /* 0 terminated list of supported formats */
uint32_t *emu_formats; /* 0 terminated list of emulated formats */
struct video_resolution_s *res; /* 0 terminated list of resolutions */
struct video_controls_s *controls; /* linked list of controls */
unsigned long datalen; /* size of image data for selected format */
......
......@@ -1090,6 +1090,113 @@ static int v4l2_g_control(zbar_video_t *vdo,
}
#endif /* VIDIOC_QUERY_EXT_CTRL */
static int v4l2_sort_resolutions(const void *__a, const void *__b)
{
const struct video_resolution_s *a = __a;
const struct video_resolution_s *b = __b;
int r;
r = (int)b->width - a->width;
if (!r)
r = (int)b->height - a->height;
return r;
}
static float v4l2_get_max_fps_discrete(zbar_video_t *vdo,
struct v4l2_frmsizeenum *frmsize)
{
struct v4l2_frmivalenum frmival = { 0 };
float fps, max_fps = -1;
frmival.width = frmsize->discrete.width;
frmival.height = frmsize->discrete.height;
frmival.pixel_format = frmsize->pixel_format;
frmival.index = 0;
for (frmival.index = 0;
!v4l2_ioctl(vdo->fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival);
frmival.index++) {
fps = ((float)frmival.discrete.denominator)/frmival.discrete.numerator;
if (fps > max_fps)
max_fps = fps;
}
return max_fps;
}
static void v4l2_insert_resolution(zbar_video_t *vdo,
unsigned int *n_res,
unsigned int width, unsigned int height,
float max_fps)
{
unsigned int i;
for (i = 0; i < *n_res; i++) {
if (vdo->res[i].width == width && vdo->res[i].height == height)
return;
}
vdo->res = realloc(vdo->res, (*n_res + 1) * sizeof(struct video_resolution_s));
vdo->res[*n_res].width = width;
vdo->res[*n_res].height = height;
vdo->res[*n_res].max_fps = max_fps;
(*n_res)++;
}
static int v4l2_get_supported_resolutions(zbar_video_t *vdo)
{
struct v4l2_fmtdesc fmt = { 0 };
struct v4l2_frmsizeenum frmsize = { 0 };
int i;
unsigned int width, height, n_res = 0;
vdo->res = NULL;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (fmt.index = 0;
!v4l2_ioctl(vdo->fd, VIDIOC_ENUM_FMT, &fmt);
fmt.index++) {
if (vdo->format != fmt.pixelformat)
continue;
frmsize.pixel_format = fmt.pixelformat;
frmsize.index = 0;
while (!v4l2_ioctl(vdo->fd, VIDIOC_ENUM_FRAMESIZES, &frmsize)) {
if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
v4l2_insert_resolution(vdo, &n_res, frmsize.discrete.width,
frmsize.discrete.height,
v4l2_get_max_fps_discrete(vdo, &frmsize));
} else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
for (i = 0; i <= 4; i++) {
width = frmsize.stepwise.min_width +
i * (frmsize.stepwise.max_width -
frmsize.stepwise.min_width) / 4;
height = frmsize.stepwise.min_height +
i * (frmsize.stepwise.max_height -
frmsize.stepwise.min_height) / 4;
v4l2_insert_resolution(vdo, &n_res, width, height, -1);
}
}
frmsize.index++;
}
}
qsort(vdo->res, n_res, sizeof(struct video_resolution_s),
v4l2_sort_resolutions);
for (i = 0; i < n_res; i++) {
zprintf(1, "%dx%d (%0.2f fps)\n",
vdo->res[i].width, vdo->res[i].height, vdo->res[i].max_fps);
}
/* Make the list zero-terminated */
v4l2_insert_resolution(vdo, &n_res, 0, 0, 0);
return 0;
}
int _zbar_v4l2_probe (zbar_video_t *vdo)
{
/* check capabilities */
......@@ -1124,6 +1231,9 @@ int _zbar_v4l2_probe (zbar_video_t *vdo)
if (v4l2_query_controls(vdo))
return(-1);
if (v4l2_get_supported_resolutions(vdo))
return(-1);
/* FIXME report error and fallback to readwrite? (if supported...) */
if(vdo->iomode != VIDEO_READWRITE &&
(vcap.device_caps & V4L2_CAP_STREAMING) &&
......
......@@ -244,7 +244,7 @@ static int vfw_set_format (zbar_video_t *vdo,
bih->biClrUsed = bih->biClrImportant = 0;
bih->biCompression = fmt;
zprintf(8, "seting format: %.4s(%08x) " BIH_FMT "\n",
zprintf(8, "setting format: %.4s(%08x) " BIH_FMT "\n",
(char*)&fmt, fmt, BIH_FIELDS(bih));
if(!capSetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size))
......
......@@ -21,43 +21,163 @@
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
#include <fcntl.h>
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ftw.h>
#include <unistd.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
typedef void (cb_t) (void *userdata, const char *device);
static cb_t *add_dev;
static void *userdata;
static int idx;
static const char *default_dev;
static int default_idx;
struct devnodes {
char *fname;
int minor;
int is_valid;
};
static unsigned int n_devices = 0;
static struct devnodes *devices = NULL;
/*
* Sort order:
*
* - Valid devices comes first
* - Lowest minors comes first
*
* For devnode names, it sorts on this order:
* - custom udev given names
* - /dev/v4l/by-id/
* - /dev/v4l/by-path/
* - /dev/video
* - /dev/char/
*
* - Device name is sorted alphabetically if follows same pattern
*/
static int sort_devices(const void *__a, const void *__b)
{
const struct devnodes *a = __a;
const struct devnodes *b = __b;
int val_a, val_b;
if (a->is_valid != b->is_valid)
return !a->is_valid - !b->is_valid;
if (a->minor != b->minor)
return a->minor - b->minor;
/* Ensure that /dev/video* devices will stay at the top */
if (strstr(a->fname, "by-id"))
val_a = 1;
if (strstr(a->fname, "by-path"))
val_a = 2;
else if (strstr(a->fname, "/dev/video"))
val_a = 3;
else if (strstr(a->fname, "char"))
val_a = 4;
else /* Customized names comes first */
val_a = 0;
if (strstr(b->fname, "by-id"))
val_b = 1;
if (strstr(b->fname, "by-path"))
val_b = 2;
else if (strstr(b->fname, "/dev/video"))
val_b = 3;
else if (strstr(b->fname, "char"))
val_b = 4;
else /* Customized names comes first */
val_b = 0;
if (val_a != val_b)
return val_a - val_b;
/* Finally, just use alphabetic order */
return strcmp(a->fname, b->fname);
}
static int video_filter (const char *fpath,
const struct stat *sb,
int typeflag)
static int handle_video_devs(const char *file,
const struct stat *st,
int flag)
{
if(S_ISCHR(sb->st_mode) && (sb->st_rdev >> 8) == 81 && fpath) {
int active = default_dev && !strcmp(default_dev, fpath);
if(strncmp(fpath, "/dev/", 5)) {
char abs[strlen(fpath) + 6];
strcpy(abs, "/dev/");
if(fpath[0] == '/')
abs[4] = '\0';