summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am.inc162
-rwxr-xr-xtest/barcodetest.py413
-rw-r--r--test/check_dbus.sh.in39
-rw-r--r--test/dbg_scan.cpp218
-rw-r--r--test/pdf417_encode.h4674
-rw-r--r--test/test_convert.c60
-rw-r--r--test/test_cpp.cpp43
-rw-r--r--test/test_cpp_img.cpp214
-rw-r--r--test/test_dbus.c254
-rw-r--r--test/test_decode.c1356
-rw-r--r--test/test_examples.sh.in91
-rwxr-xr-xtest/test_gi.py216
-rw-r--r--test/test_images.c533
-rw-r--r--test/test_images.h46
-rw-r--r--test/test_jpeg.c158
-rwxr-xr-xtest/test_perl.pl47
-rw-r--r--test/test_proc.c170
-rwxr-xr-xtest/test_pygtk.py193
-rwxr-xr-xtest/test_python.py64
-rw-r--r--test/test_video.c237
-rw-r--r--test/test_window.c98
21 files changed, 9286 insertions, 0 deletions
diff --git a/test/Makefile.am.inc b/test/Makefile.am.inc
new file mode 100644
index 0000000..55b9814
--- /dev/null
+++ b/test/Makefile.am.inc
@@ -0,0 +1,162 @@
+check_PROGRAMS += test/test_decode
+test_test_decode_SOURCES = test/test_decode.c test/pdf417_encode.h
+test_test_decode_CFLAGS = -Wno-unused $(AM_CFLAGS)
+test_test_decode_LDADD = zbar/libzbar.la $(AM_LDADD)
+
+TEST_IMAGE_SOURCES = test/test_images.c test/test_images.h
+
+check_PROGRAMS += test/test_convert
+test_test_convert_SOURCES = test/test_convert.c $(TEST_IMAGE_SOURCES)
+test_test_convert_LDADD = zbar/libzbar.la $(AM_LDADD)
+
+#check_PROGRAMS += test/test_window
+#test_test_window_SOURCES = test/test_window.c $(TEST_IMAGE_SOURCES)
+#test_test_window_CPPFLAGS = -I$(srcdir)/zbar $(AM_CPPFLAGS)
+#test_test_window_LDADD = zbar/libzbar.la $(AM_LDADD)
+
+if HAVE_VIDEO
+check_PROGRAMS += test/test_video
+test_test_video_SOURCES = test/test_video.c $(TEST_IMAGE_SOURCES)
+test_test_video_LDADD = zbar/libzbar.la $(AM_LDADD)
+endif
+
+check_PROGRAMS += test/test_proc
+test_test_proc_SOURCES = test/test_proc.c $(TEST_IMAGE_SOURCES)
+test_test_proc_LDADD = zbar/libzbar.la $(AM_LDADD)
+
+check_PROGRAMS += test/test_cpp
+test_test_cpp_SOURCES = test/test_cpp.cpp
+test_test_cpp_LDADD = zbar/libzbar.la $(AM_LDADD)
+
+check_PROGRAMS += test/test_cpp_img
+test_test_cpp_img_SOURCES = test/test_cpp_img.cpp $(TEST_IMAGE_SOURCES)
+test_test_cpp_img_LDADD = zbar/libzbar.la $(AM_LDADD)
+
+if HAVE_JPEG
+check_PROGRAMS += test/test_jpeg
+test_test_jpeg_SOURCES = test/test_jpeg.c
+test_test_jpeg_LDADD = zbar/libzbar.la $(AM_LDADD)
+endif
+
+if HAVE_MAGICK
+EXTRA_PROGRAMS += test/dbg_scan
+test_dbg_scan_SOURCES = test/dbg_scan.cpp
+test_dbg_scan_CPPFLAGS = $(MAGICK_CFLAGS) $(AM_CPPFLAGS)
+test_dbg_scan_LDADD = $(MAGICK_LIBS) -lMagick++ zbar/libzbar.la $(AM_LDADD)
+endif
+
+if HAVE_DBUS
+check_PROGRAMS += test/test_dbus
+test_test_dbus_SOURCES = test/test_dbus.c
+test_test_dbus_LDFLAGS = $(DBUS_LIBS)
+endif
+
+EXTRA_DIST += test/test_pygtk.py test/test_perl.pl test/test_gi.py test/test_python.py
+
+# automake bug in "monolithic mode"?
+CLEANFILES += test/.libs/test_decode test/.libs/test_proc \
+ test/.libs/test_convert test/.libs/test_window \
+ test/.libs/test_video test/.libs/dbg_scan test/.libs/test_gtk
+
+
+# Images that work out of the box without needing to enable
+# an specific symbology
+NORMAL_IMAGES = codabar.png code-128.png code-39.png code-93.png \
+ databar.png databar-exp.png ean-13.png ean-8.png i2-5.png \
+ qr-code.png sqcode1-generated.png sqcode1-scanned.png
+
+EXAMPLES = @abs_top_builddir@/examples
+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 -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
+ $(ZBARIMG) --raw -Sbinary $(EXAMPLES)/qr-code-binary.png 2>/dev/null|head -c -1|sha1sum|sed "s,-,zbarimg --raw -Sbinary qr-code-binary.png," >>$(EXAMPLES)/sha1sum
+
+test_progs: $(check_PROGRAMS)
+ @$(MAKE) $(check_PROGRAMS)
+
+# Require X11 to work
+check-cpp: test/test_cpp_img
+ @abs_top_builddir@/test/test_cpp_img
+
+check-decoder: test/test_decode
+ @abs_top_builddir@/test/test_decode -q
+
+regress-decoder: test/test_decode
+ @abs_top_builddir@/test/test_decode -q -n 100000
+
+check-images-py: zbarimg/zbarimg
+ @PYTHON@ @abs_top_srcdir@/test/barcodetest.py
+
+check-images: zbarimg/zbarimg
+ @abs_top_builddir@/test/test_examples.sh
+
+check-convert: test/test_convert
+ @abs_top_srcdir@/test/test_convert
+ @if [ "`sha1sum /tmp/base.I420.zimg |cut -d' ' -f 1`" != \
+ "d697b0bb84617bef0f6413b3e5537ee38ba92312" ]; then \
+ echo "convert FAILED"; else echo "convert PASSED."; fi
+ @rm /tmp/base.I420.zimg 2>/dev/null
+
+if HAVE_PYGTK2
+check-pygtk: pygtk/zbarpygtk.la
+ PYTHONPATH=@abs_top_srcdir@/pygtk/.libs/ \
+ @PYTHON@ @abs_top_srcdir@/test/test_pygtk.py
+else
+check-pygtk:
+endif
+
+if HAVE_PYTHON
+check-python: python/zbar.la
+ PYTHONPATH=@abs_top_srcdir@/python/.libs/ \
+ @PYTHON@ @abs_top_srcdir@/test/test_python.py \
+ '@abs_top_srcdir@/examples/ean-13.png' '9789876543217'
+else
+check-python:
+endif
+
+check-gi: gtk/ZBar-1.0.typelib
+ LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):@abs_top_srcdir@/gtk/.libs:@abs_top_srcdir@/zbar/.libs \
+ GI_TYPELIB_PATH=@abs_top_srcdir@/gtk/ \
+ @PYTHON@ @abs_top_srcdir@/test/test_gi.py
+
+# Require a camera device for it to work
+check-video: test/test_video
+ if [ -d /dev/video0 ]; then @abs_top_srcdir@/test/test_video -q; fi
+
+check-jpeg: test/test_jpeg
+ @abs_top_srcdir@/test/test_jpeg -q
+
+if HAVE_DBUS
+# Require a working D-Bus - may fail with containers
+check-dbus: test/test_dbus
+ @abs_top_builddir@/test/check_dbus.sh
+else
+check-dbus:
+endif
+
+if HAVE_JAVA_UNIT
+check-java: zbar/libzbar.la
+ JAVA_HOME=${JAVA_HOME} $(MAKE) -C java check-java
+else
+check-java:
+endif
+
+regress: regress-decoder
+
+check-local: check-images-py check-decoder check-images check-java \
+ check-python regress
+
+other-tests: check-cpp check-convert check-video check-jpeg
+
+tests: check-local check-dbus other-tests
+
+.NOTPARALLEL: check-local regress tests
+
+PHONY += gen_checksum check-cpp check-decoder check-images check-dbus regress-decoder regress-images regress
diff --git a/test/barcodetest.py b/test/barcodetest.py
new file mode 100755
index 0000000..295832e
--- /dev/null
+++ b/test/barcodetest.py
@@ -0,0 +1,413 @@
+#!/usr/bin/env python
+# pylint: disable=C0103,C0114,C0115,C0116,C0209,R0912,R0915,W0511,W0603,W0613,W0707,W0212
+
+from __future__ import print_function
+
+import re
+import sys
+import unittest as UT
+import xml.etree.ElementTree as ET
+
+from errno import EISDIR, EINVAL, EACCES
+from io import StringIO
+from os import path, getcwd
+from subprocess import Popen, PIPE
+from traceback import format_exception
+
+try:
+ from urllib.error import HTTPError
+ from urllib.parse import urljoin, urlunparse
+ from urllib.request import urlopen
+except ImportError:
+ from urllib2 import urlopen, HTTPError
+ from urlparse import urljoin, urlunparse
+
+debug = False
+
+# program to run - None means we still need to search for it
+zbarimg = None
+# arguments to said program
+zbarimg_args = ['-q', '--xml', '--nodbus']
+
+
+# namespace support
+try:
+ register_namespace = ET.register_namespace
+except AttributeError:
+ def register_namespace(prefix, uri):
+ ET._namespace_map[uri] = prefix
+
+# barcode results
+BC = 'http://zbar.sourceforge.net/2008/barcode'
+register_namespace('bc', BC)
+
+# testcase extensions
+TS = 'http://zbar.sourceforge.net/2009/test-spec'
+register_namespace('test', TS)
+
+
+# printing support
+def fixtag(node):
+ return str(node.tag).split('}', 1)[-1]
+
+
+def toxml(node):
+ s = StringIO()
+ ET.ElementTree(node).write(s)
+ return s.getvalue()
+
+
+def hexdump(data):
+ print(data)
+ c = 0
+ for i, c in enumerate(data):
+ if i & 0x7 == 0:
+ print('[%04x]' % i, end=' ')
+ print(' %04x' % ord(c), end=' ')
+ if i & 0x7 == 0x7:
+ print()
+ if len(c) & 0x7 != 0x7:
+ print('\n')
+
+
+# search for a file in the distribution
+def distdir_search(search_subdir, base, suffixes=('',)):
+ # start with current dir,
+ # then try script invocation path
+ rundir = path.dirname(sys.argv[0])
+ search = ['', rundir]
+
+ # finally, attempt to follow VPATH if present
+ try:
+ with open('Makefile', 'r') as makefile:
+ for line in makefile:
+ if re.match(r'^VPATH\s*=', line):
+ vpath = line.split('=', 1)[1].strip()
+ if vpath and vpath != rundir:
+ search.append(vpath)
+ break
+ except IOError:
+ pass
+
+ # poke around for subdir
+ subdirs = tuple((search_subdir, path.join('..', search_subdir), '..', ''))
+
+ for prefix in search:
+ for subdir in subdirs:
+ for suffix in suffixes:
+ file = path.realpath(path.join(prefix, subdir, base + suffix))
+ if path.isfile(file):
+ return file
+ return None
+
+
+def find_zbarimg():
+ """search for zbarimg program to run.
+ """
+ global zbarimg
+ # look in dist dir first
+ zbarimg = distdir_search('zbarimg', 'zbarimg', ('', '.exe'))
+ if not zbarimg:
+ # fall back to PATH
+ zbarimg = 'zbarimg'
+ if debug:
+ print('using zbarimg from PATH')
+ elif debug:
+ print('using:', zbarimg)
+
+
+def run_zbarimg(images):
+ """invoke zbarimg for the specified files.
+
+ return results as an ET.Element
+ """
+ args = [zbarimg]
+ args.extend(zbarimg_args)
+ args.extend(images)
+ if debug:
+ print('running:', ' '.join(args))
+
+ # FIXME should be able to pipe (feed) parser straight from output
+ child = Popen(args, stdout=PIPE, stderr=PIPE)
+ (xml, err) = child.communicate()
+
+ rc = child.returncode
+ if debug:
+ print('zbarimg returned', rc)
+
+ # FIXME trim usage from error msg
+ assert rc in (0, 4), \
+ 'zbarimg returned error status (%d):\n\t%s\n' % (rc, str(err.decode()))
+
+ assert not err, err
+
+ result = ET.XML(xml)
+ assert result.tag == ET.QName(BC, 'barcodes')
+ return result
+
+
+class TestCase(UT.TestCase):
+ """single barcode source test.
+
+ must have source attribute set to an ET.Element representation of a
+ bc:source tag before test is run.
+ """
+
+ def __init__(self, methodName):
+ UT.TestCase.__init__(self, methodName)
+ self.source = None
+
+ def shortDescription(self):
+ return self.source.get('href')
+
+ def setUp(self):
+ if not zbarimg:
+ find_zbarimg()
+
+ def runTest(self):
+ expect = self.source
+ assert expect is not None
+ assert expect.tag == ET.QName(BC, 'source')
+ actual = run_zbarimg((expect.get('href'),))
+
+ self.assertEqual(len(actual), 1)
+
+ try:
+ compare_sources(expect, actual[0])
+ except AssertionError:
+ if expect.get(str(ET.QName(TS, 'exception'))) != 'TODO':
+ raise
+ # ignore
+
+
+class BuiltinTestCase(TestCase):
+ def __init__(self, methodName='runTest'):
+ TestCase.__init__(self, methodName)
+
+ href = distdir_search('examples', 'ean-13.png')
+ if not href:
+ href = 'https://git.linuxtv.org/zbar.git/plain/examples/ean-13.png'
+
+ self.source = src = ET.Element(ET.QName(BC, 'source'), href=href)
+ sym = ET.SubElement(src, ET.QName(BC, 'symbol'), type='EAN-13',
+ orientation='UP')
+ data = ET.SubElement(sym, ET.QName(BC, 'data'))
+ data.text = '9789876543217'
+
+
+def compare_maps(expect, actual, compare_func):
+ errors = []
+ notes = []
+ for key, iact in actual.items():
+ iexp = expect.pop(key, None)
+ if iexp is None:
+ errors.append('bonus unexpected result:\n' + toxml(iact))
+ continue
+
+ try:
+ compare_func(iexp, iact)
+ except BaseException:
+ errors.append(''.join(format_exception(*sys.exc_info())))
+
+ if iexp.get(str(ET.QName(TS, 'exception'))) == 'TODO':
+ notes.append('TODO unexpected result:\n' + toxml(iact))
+
+ for key, iexp in expect.items():
+
+ exc = iexp.get(str(ET.QName(TS, 'exception')))
+
+ if exc == 'TODO':
+ notes.append('TODO missing expected result:\n' + toxml(iexp))
+ elif exc is not None:
+ errors.append('missing expected result:\n' + toxml(iexp))
+
+ if len(notes) == 1:
+ print('(TODO)', end=' ', file=sys.stderr)
+ elif notes:
+ print('(%d TODO)' % len(notes), end=' ', file=sys.stderr)
+ assert not errors, '\n'.join(errors)
+
+
+def compare_sources(expect, actual):
+ assert actual.tag == ET.QName(BC, 'source')
+ assert actual.get('href').endswith(expect.get('href')), \
+ 'source href mismatch: %s != %s' % (actual, expect)
+
+ # FIXME process/trim test:* contents
+
+ def map_source(src):
+ if src == '' or src[0].tag != ET.QName(BC, 'index'):
+ # insert artificial hierarchy
+ syms = src[:]
+ del src[:]
+ idx = ET.SubElement(src, ET.QName(BC, 'index'), num='0')
+ idx[:] = syms
+ exc = src.get(str(ET.QName(TS, 'exception')))
+ if exc is not None:
+ idx.set(str(ET.QName(TS, 'exception')), exc)
+ return {'0': idx}
+ elif len(src):
+ assert src[0].tag != ET.QName(BC, 'symbol'), \
+ 'invalid source element: ' + \
+ 'expecting "index" or "symbol", got "%s"' % fixtag(src[0])
+
+ srcmap = {}
+ for idx in src:
+ srcmap[idx.get('num')] = idx
+ return srcmap
+
+ compare_maps(map_source(expect), map_source(actual), compare_indices)
+
+
+def compare_indices(expect, actual):
+ assert actual.tag == ET.QName(BC, 'index')
+ assert actual.get('num') == expect.get('num')
+
+ # FIXME process/trim test:* contents
+
+ def map_index(idx):
+ idxmap = {}
+ for sym in idx:
+ assert sym.tag == ET.QName(BC, 'symbol')
+ typ = sym.get('type')
+ assert typ is not None
+ data = sym.find(str(ET.QName(BC, 'data'))).text
+ idxmap[typ, data] = sym
+
+ return idxmap
+
+ try:
+ compare_maps(map_index(expect), map_index(actual), compare_symbols)
+ except AssertionError:
+ if expect.get(str(ET.QName(TS, 'exception'))) != 'TODO':
+ raise
+
+
+def compare_symbols(expect, actual):
+ orient = expect.get('orientation')
+ if orient:
+ assert actual.get('orientation') == orient
+
+# override unittest.TestLoader to populate tests from xml description
+
+
+class TestLoader:
+ suiteClass = UT.TestSuite
+
+ def __init__(self):
+ self.cwd = urlunparse(('file', '', getcwd() + '/', '', '', ''))
+ if debug:
+ print('cwd =', self.cwd)
+
+ def loadTestsFromModule(self, module):
+ return self.suiteClass([BuiltinTestCase()])
+
+ def loadTestsFromNames(self, names, module=None):
+ suites = [self.loadTestsFromName(name, module) for name in names]
+ return self.suiteClass(suites)
+
+ def loadTestsFromURL(self, url=None, file=None):
+ if debug:
+ print('loading url:', url)
+
+ target = None
+ if not file:
+ if not url:
+ return self.suiteClass([BuiltinTestCase()])
+
+ content = None
+ url = urljoin(self.cwd, url)
+ # FIXME grok fragment
+
+ try:
+ if debug:
+ print('trying:', url)
+ file = urlopen(url)
+ content = file.info().get('Content-Type')
+ except HTTPError:
+ # possible remote directory
+ pass
+ except IOError as e:
+ if e.errno not in (EISDIR, EINVAL, EACCES):
+ raise
+ # could be local directory
+
+ if (not file or
+ content == 'text/html' or
+ (isinstance(file, HTTPError) and file.code != 200)):
+ # could be directory, try opening index
+ try:
+ tmp = urljoin(url + '/', 'index.xml')
+ if debug:
+ print('trying index:', tmp)
+ file = urlopen(tmp)
+ content = file.info().get('Content-Type')
+ url = tmp
+ except IOError:
+ raise IOError('no test index found at: %s' % url)
+
+ if debug:
+ print('\tContent-Type:', content)
+
+ if content not in ('application/xml', 'text/xml'):
+ # assume url is image to test, try containing index
+ # FIXME should be able to keep searching up
+ try:
+ target = url.rsplit('/', 1)[1]
+ index = urljoin(url, 'index.xml')
+ if debug:
+ print('trying index:', index)
+ file = urlopen(index)
+ content = file.info().get('Content-Type')
+ if debug:
+ print('\tContent-Type:', content)
+ assert content in ('application/xml', 'text/xml')
+ url = index
+ except IOError:
+ raise IOError('no index found for: %s' % url)
+
+ index = ET.ElementTree(file=file).getroot()
+ assert index.tag == ET.QName(BC, 'barcodes')
+
+ suite = self.suiteClass()
+ for src in index:
+ # FIXME trim any meta info
+ href = src.get('href')
+ if target and target != href:
+ continue
+ if src.tag == ET.QName(BC, 'source'):
+ test = TestCase()
+ # convert file URLs to filesystem paths
+ href = urljoin(url, href)
+ href = re.sub(r'^file://', '', href)
+ src.set('href', href)
+ test.source = src
+ suite.addTest(test)
+ elif src.tag == ET.QName(TS, 'index'):
+ suite.addTest(self.loadTestsFromURL(urljoin(url, href)))
+ else:
+ raise AssertionError('malformed test index') # FIXME detail
+
+ assert suite.countTestCases(), 'empty test index: %s' % url
+ return suite
+
+ def loadTestsFromName(self, name=None, module=None):
+ return self.loadTestsFromURL(name)
+
+ def unsupported(self, *args, **kwargs):
+ raise TypeError("unsupported TestLoader API")
+
+ # FAKE discover method needed for python3 to work
+ def discover(self, start_dir, pattern, top_level_dir=None):
+ return self.loadTestsFromURL()
+
+ loadTestsFromTestCase = unsupported
+ getTestCaseNames = unsupported
+
+
+if __name__ == '__main__':
+ if '-d' in sys.argv:
+ debug = True
+ sys.argv.remove('-d')
+
+ UT.main(module=None, testLoader=TestLoader())
diff --git a/test/check_dbus.sh.in b/test/check_dbus.sh.in
new file mode 100644
index 0000000..3b97b36
--- /dev/null
+++ b/test/check_dbus.sh.in
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+DIR="@abs_top_srcdir@"
+BDIR="@abs_top_builddir@"
+LOG="/tmp/zbar_dbus_test_$$.log"
+LOG_BIN="/tmp/zbar_dbus_test_$$.bin"
+
+EXPECTED="7294377b69fb00c7e0811429ab7a42cc8cecfda0"
+EXPECTED_BIN="df896e459e47a7d392031a7d4962722a143e276b"
+
+
+$BDIR/test/test_dbus -c2 -t5 --log=$LOG --bin-log=$LOG_BIN &
+PID=$!
+
+trap "rm -r $LOG $LOG_BIN" EXIT
+
+$BDIR/zbarimg/zbarimg $DIR/examples/code-128.png 2>/dev/null >/dev/null
+$BDIR/zbarimg/zbarimg -Sbinary $DIR/examples/qr-code-binary.png 2>/dev/null >/dev/null
+
+wait $PID
+
+if [ ! -s $LOG ] || [ ! -s $LOG_BIN ]; then
+ echo "FAILED: nothing received via D-Bus"
+ exit -2
+fi
+
+CK="`cat $LOG |sha1sum |cut -d" " -f 1`"
+if [ "x$CK" != "x$EXPECTED" ]; then
+ echo "FAILED: $CK instead of $EXPECTED"
+ exit -2
+fi
+
+CK_BIN="`cat $LOG_BIN |sha1sum |cut -d" " -f 1`"
+if [ "x$CK_BIN" != "x$EXPECTED_BIN" ]; then
+ echo "FAILED: $CK_BIN instead of $EXPECTED_BIN"
+ exit -2
+fi
+
+echo "D-Bus PASSED."
diff --git a/test/dbg_scan.cpp b/test/dbg_scan.cpp
new file mode 100644
index 0000000..a496112
--- /dev/null
+++ b/test/dbg_scan.cpp
@@ -0,0 +1,218 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include <Magick++.h>
+#include <fstream>
+#include <iostream>
+#include <libgen.h>
+#include <zbar.h>
+
+using namespace std;
+using namespace zbar;
+
+#ifndef ZBAR_FIXED
+#define ZBAR_FIXED 5
+#endif
+
+#define ZBAR_FRAC (1 << ZBAR_FIXED)
+
+Decoder decoder;
+Scanner scanner;
+
+/* undocumented API for drawing cutesy debug graphics */
+extern "C" void zbar_scanner_get_state(const zbar_scanner_t *scn, unsigned *x,
+ unsigned *cur_edge, unsigned *last_edge,
+ int *y0, int *y1, int *y2,
+ int *y1_thresh);
+
+void scan_image(const char *filename)
+{
+ scanner.reset();
+ // normally scanner would reset associated decoder,
+ // but this debug program connects them manually
+ // (to make intermediate state more readily available)
+ // so decoder must also be reset manually
+ decoder.reset();
+
+ Magick::Image image;
+ image.read(filename);
+ string file = image.baseFilename();
+ size_t baseidx = file.rfind('/');
+ if (baseidx != string::npos)
+ file = file.substr(baseidx + 1, file.length() - baseidx - 1);
+ ofstream svg((file + ".svg").c_str());
+
+ unsigned inwidth = image.columns();
+ unsigned width = inwidth + 3;
+ unsigned height = image.rows();
+ unsigned midy = height / 2;
+ cerr << "x+: " << midy << endl;
+
+ image.crop(Magick::Geometry(inwidth, 1, 0, midy));
+
+ svg << "<?xml version='1.0'?>" << endl
+ << "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN'"
+ << " 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>" << endl
+ << "<svg version='1.1' id='top'"
+ << " width='10in' height='6in' preserveAspectRatio='xMinYMid slice'"
+ << " overflow='visible' viewBox='0,0 " << width * 2 << ",384'"
+ << " xmlns:xlink='http://www.w3.org/1999/xlink'"
+ << " xmlns='http://www.w3.org/2000/svg'>" << endl
+ << "<defs><style type='text/css'><![CDATA[" << endl
+ << " * { stroke-linejoin: round; stroke-linecap: round;"
+ << " stroke-width: .1; text-anchor: middle;"
+ << " image-rendering: optimizeSpeed;"
+ << " font-size: 6; font-weight: bold }" << endl
+ << " path { fill: none }" << endl
+ << " #zero { stroke: #00f }" << endl
+ << " #edges { stroke: #f00 }" << endl
+ << " #cur-edge { stroke: #f44 }" << endl
+ << " #raw { stroke: orange }" << endl
+ << " #y0 { stroke: yellow }" << endl
+ << " #y1 { stroke: #0c0 }" << endl
+ << " #y2 { stroke: #0aa }" << endl
+ << " .y1thr { stroke: #f0f }" << endl
+ << " rect.bar { fill: black }" << endl
+ << " text.bar { fill: white }" << endl
+ << " rect.space { fill: white }" << endl
+ << " text.space { fill: black }" << endl
+ << " text.data { fill: #44f; font-size: 16 }" << endl
+ << "]]></style></defs>" << endl
+ << "<image width='" << inwidth * 2 << "' height='384'"
+ << " preserveAspectRatio='none'"
+ << " xlink:href='" << file << ".png'/>" << endl
+ << "<g transform='translate(1,384) scale(2,-.5)'>" << endl;
+
+ // brute force
+ unsigned raw[inwidth];
+ {
+ // extract scan from image pixels
+ image.modifyImage();
+ Magick::Pixels view(image);
+ Magick::PixelPacket *pxp = view.get(0, 0, inwidth, 1);
+ Magick::ColorYUV y;
+ double max = 0;
+ svg << "<path id='raw' d='M";
+ unsigned i;
+ for (i = 0; i < inwidth; i++, pxp++) {
+ y = *pxp;
+ if (max < y.y())
+ max = y.y();
+ raw[i] = (unsigned)(y.y() * 0x100);
+ svg << ((i != 1) ? " " : " L ") << i << "," << raw[i];
+ y.u(0);
+ y.v(0);
+ *pxp = y;
+ }
+ view.sync();
+ svg << "'/>" << endl << "</g>" << endl;
+ }
+ image.depth(8);
+ image.write(file + ".png");
+
+ // process scan and capture calculated values
+ unsigned cur_edge[width], last_edge[width];
+ int y0[width], y1[width], y2[width], y1_thr[width];
+
+ svg << "<g transform='translate(-3)'>" << endl;
+ for (unsigned i = 0; i < width; i++) {
+ int edge;
+ if (i < inwidth)
+ edge = scanner.scan_y(raw[i]);
+ else
+ edge = scanner.flush();
+
+ unsigned x;
+ zbar_scanner_get_state(scanner, &x, &cur_edge[i], &last_edge[i], &y0[i],
+ &y1[i], &y2[i], &y1_thr[i]);
+ if (edge) {
+ unsigned w = scanner.get_width();
+ if (w)
+ svg << "<rect x='" << (2. * (last_edge[i] - w) / ZBAR_FRAC)
+ << "' width='" << (w * 2. / ZBAR_FRAC)
+ << "' height='32' class='"
+ << (scanner.get_color() ? "space" : "bar") << "'/>" << endl
+ << "<text transform='translate("
+ << ((2. * last_edge[i] - w) / ZBAR_FRAC) - 3
+ << ",16) rotate(90)' class='"
+ << (scanner.get_color() ? "space" : "bar") << "'>" << endl
+ << w << "</text>" << endl;
+ zbar_symbol_type_t sym = decoder.decode_width(w);
+ if (sym > ZBAR_PARTIAL) {
+ svg << "<text transform='translate("
+ << (2. * (last_edge[i] + w) / ZBAR_FRAC)
+ << ",208) rotate(90)' class='data'>"
+ << decoder.get_data_string() << "</text>" << endl;
+ }
+ } else if ((!i) ? last_edge[i] : last_edge[i] == last_edge[i - 1])
+ last_edge[i] = 0;
+ }
+
+ svg << "</g>" << endl
+ << "<g transform='translate(-3,384) scale(2,-.5)'>" << endl
+ << "<path id='edges' d='";
+ for (unsigned i = 0; i < width; i++)
+ if (last_edge[i])
+ svg << " M" << ((double)last_edge[i] / ZBAR_FRAC) << ",0v768";
+ svg << "'/>" << endl
+ << "</g>" << endl
+ << "<g transform='translate(-1,384) scale(2,-.5)'>" << endl
+ << "<path id='y0' d='M";
+ for (unsigned i = 0; i < width; i++)
+ svg << ((i != 1) ? " " : " L ") << i << "," << y0[i];
+ svg << "'/>" << endl << "</g>" << endl;
+
+ svg << "<g transform='translate(-1,128) scale(2,-1)'>" << endl
+ << "<line id='zero' x2='" << width << "'/>" << endl
+ << "<path id='cur-edge' d='";
+ for (unsigned i = 1; i < width - 1; i++)
+ if (!last_edge[i + 1] && (cur_edge[i] != cur_edge[i + 1]))
+ svg << " M" << ((double)cur_edge[i] / ZBAR_FRAC) - 1 << ",-32v64";
+ svg << "'/>" << endl << "<path class='y1thr' d='M";
+ for (unsigned i = 0; i < width; i++)
+ svg << ((i != 1) ? " " : " L ") << i << "," << y1_thr[i];
+ svg << "'/>" << endl << "<path class='y1thr' d='M";
+ for (unsigned i = 0; i < width; i++)
+ svg << ((i != 1) ? " " : " L ") << i << "," << -y1_thr[i];
+ svg << "'/>" << endl << "<path id='y1' d='M";
+ for (unsigned i = 0; i < width; i++)
+ svg << ((i != 1) ? " " : " L ") << (i - 0.5) << "," << y1[i];
+ svg << "'/>" << endl << "<path id='y2' d='M";
+ for (unsigned i = 0; i < width; i++)
+ svg << ((i != 1) ? " " : " L ") << i << "," << y2[i];
+ svg << "'/>" << endl << "</g>" << endl;
+
+ svg << "</svg>" << endl;
+}
+
+int main(int argc, const char *argv[])
+{
+ if (argc < 2) {
+ cerr << "ERROR: specify image file(s) to scan" << endl;
+ return (1);
+ }
+
+ for (int i = 1; i < argc; i++)
+ scan_image(argv[i]);
+ return (0);
+}
diff --git a/test/pdf417_encode.h b/test/pdf417_encode.h
new file mode 100644
index 0000000..eb70cf5
--- /dev/null
+++ b/test/pdf417_encode.h
@@ -0,0 +1,4674 @@
+/*------------------------------------------------------------------------
+ * Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+#ifndef _PDF417_ENCODE_H_
+#define _PDF417_ENCODE_H_
+
+unsigned long pdf417_encode[929][3] = {
+ {
+ 0x31111136,
+ 0x51111125,
+ 0x21111155,
+ }, /* 0 */
+ {
+ 0x41111144,
+ 0x61111133,
+ 0x31111163,
+ }, /* 1 */
+ {
+ 0x51111152,
+ 0x41111216,
+ 0x11111246,
+ }, /* 2 */
+ {
+ 0x31111235,
+ 0x51111224,
+ 0x21111254,
+ }, /* 3 */
+ {
+ 0x41111243,
+ 0x61111232,
+ 0x31111262,
+ }, /* 4 */
+ {
+ 0x51111251,
+ 0x41111315,
+ 0x11111345,
+ }, /* 5 */
+ {
+ 0x21111326,
+ 0x51111323,
+ 0x21111353,
+ }, /* 6 */
+ {
+ 0x31111334,
+ 0x61111331,
+ 0x31111361,
+ }, /* 7 */
+ {
+ 0x21111425,
+ 0x41111414,
+ 0x11111444,
+ }, /* 8 */
+ {
+ 0x11111516,
+ 0x51111422,
+ 0x21111452,
+ }, /* 9 */
+ {
+ 0x21111524,
+ 0x41111513,
+ 0x11111543,
+ }, /* 10 */
+ {
+ 0x11111615,
+ 0x51111521,
+ 0x61112114,
+ }, /* 11 */
+ {
+ 0x21112136,
+ 0x41111612,
+ 0x11112155,
+ }, /* 12 */
+ {
+ 0x31112144,
+ 0x41112125,
+ 0x21112163,
+ }, /* 13 */
+ {
+ 0x41112152,
+ 0x51112133,
+ 0x61112213,
+ }, /* 14 */
+ {
+ 0x21112235,
+ 0x61112141,
+ 0x11112254,
+ }, /* 15 */
+ {
+ 0x31112243,
+ 0x31112216,
+ 0x21112262,
+ }, /* 16 */
+ {
+ 0x41112251,
+ 0x41112224,
+ 0x61112312,
+ }, /* 17 */
+ {
+ 0x11112326,
+ 0x51112232,
+ 0x11112353,
+ }, /* 18 */
+ {
+ 0x21112334,
+ 0x31112315,
+ 0x21112361,
+ }, /* 19 */
+ {
+ 0x11112425,
+ 0x41112323,
+ 0x61112411,
+ }, /* 20 */
+ {
+ 0x11113136,
+ 0x51112331,
+ 0x11112452,
+ }, /* 21 */
+ {
+ 0x21113144,
+ 0x31112414,
+ 0x51113114,
+ }, /* 22 */
+ {
+ 0x31113152,
+ 0x41112422,
+ 0x61113122,
+ }, /* 23 */
+ {
+ 0x11113235,
+ 0x31112513,
+ 0x11113163,
+ }, /* 24 */
+ {
+ 0x21113243,
+ 0x41112521,
+ 0x51113213,
+ }, /* 25 */
+ {
+ 0x31113251,
+ 0x31112612,
+ 0x61113221,
+ }, /* 26 */
+ {
+ 0x11113334,
+ 0x31113125,
+ 0x11113262,
+ }, /* 27 */
+ {
+ 0x21113342,
+ 0x41113133,
+ 0x51113312,
+ }, /* 28 */
+ {
+ 0x11114144,
+ 0x51113141,
+ 0x11113361,
+ }, /* 29 */
+ {
+ 0x21114152,
+ 0x21113216,
+ 0x51113411,
+ }, /* 30 */
+ {
+ 0x11114243,
+ 0x31113224,
+ 0x41114114,
+ }, /* 31 */
+ {
+ 0x21114251,
+ 0x41113232,
+ 0x51114122,
+ }, /* 32 */
+ {
+ 0x11115152,
+ 0x21113315,
+ 0x41114213,
+ }, /* 33 */
+ {
+ 0x51116111,
+ 0x31113323,
+ 0x51114221,
+ }, /* 34 */
+ {
+ 0x31121135,
+ 0x41113331,
+ 0x41114312,
+ }, /* 35 */
+ {
+ 0x41121143,
+ 0x21113414,
+ 0x41114411,
+ }, /* 36 */
+ {
+ 0x51121151,
+ 0x31113422,
+ 0x31115114,
+ }, /* 37 */
+ {
+ 0x21121226,
+ 0x21113513,
+ 0x41115122,
+ }, /* 38 */
+ {
+ 0x31121234,
+ 0x31113521,
+ 0x31115213,
+ }, /* 39 */
+ {
+ 0x41121242,
+ 0x21113612,
+ 0x41115221,
+ }, /* 40 */
+ {
+ 0x21121325,
+ 0x21114125,
+ 0x31115312,
+ }, /* 41 */
+ {
+ 0x31121333,
+ 0x31114133,
+ 0x31115411,
+ }, /* 42 */
+ {
+ 0x11121416,
+ 0x41114141,
+ 0x21116114,
+ }, /* 43 */
+ {
+ 0x21121424,
+ 0x11114216,
+ 0x31116122,
+ }, /* 44 */
+ {
+ 0x31121432,
+ 0x21114224,
+ 0x21116213,
+ }, /* 45 */
+ {
+ 0x11121515,
+ 0x31114232,
+ 0x31116221,
+ }, /* 46 */
+ {
+ 0x21121523,
+ 0x11114315,
+ 0x21116312,
+ }, /* 47 */
+ {
+ 0x11121614,
+ 0x21114323,
+ 0x11121146,
+ }, /* 48 */
+ {
+ 0x21122135,
+ 0x31114331,
+ 0x21121154,
+ }, /* 49 */
+ {
+ 0x31122143,
+ 0x11114414,
+ 0x31121162,
+ }, /* 50 */
+ {
+ 0x41122151,
+ 0x21114422,
+ 0x11121245,
+ }, /* 51 */
+ {
+ 0x11122226,
+ 0x11114513,
+ 0x21121253,
+ }, /* 52 */
+ {
+ 0x21122234,
+ 0x21114521,
+ 0x31121261,
+ }, /* 53 */
+ {
+ 0x31122242,
+ 0x11115125,
+ 0x11121344,
+ }, /* 54 */
+ {
+ 0x11122325,
+ 0x21115133,
+ 0x21121352,
+ }, /* 55 */
+ {
+ 0x21122333,
+ 0x31115141,
+ 0x11121443,
+ }, /* 56 */
+ {
+ 0x31122341,
+ 0x11115224,
+ 0x21121451,
+ }, /* 57 */
+ {
+ 0x11122424,
+ 0x21115232,
+ 0x11121542,
+ }, /* 58 */
+ {
+ 0x21122432,
+ 0x11115323,
+ 0x61122113,
+ }, /* 59 */
+ {
+ 0x11123135,
+ 0x21115331,
+ 0x11122154,
+ }, /* 60 */
+ {
+ 0x21123143,
+ 0x11115422,
+ 0x21122162,
+ }, /* 61 */
+ {
+ 0x31123151,
+ 0x11116133,
+ 0x61122212,
+ }, /* 62 */
+ {
+ 0x11123234,
+ 0x21116141,
+ 0x11122253,
+ }, /* 63 */
+ {
+ 0x21123242,
+ 0x11116232,
+ 0x21122261,
+ }, /* 64 */
+ {
+ 0x11123333,
+ 0x11116331,
+ 0x61122311,
+ }, /* 65 */
+ {
+ 0x21123341,
+ 0x41121116,
+ 0x11122352,
+ }, /* 66 */
+ {
+ 0x11124143,
+ 0x51121124,
+ 0x11122451,
+ }, /* 67 */
+ {
+ 0x21124151,
+ 0x61121132,
+ 0x51123113,
+ }, /* 68 */
+ {
+ 0x11124242,
+ 0x41121215,
+ 0x61123121,
+ }, /* 69 */
+ {
+ 0x11124341,
+ 0x51121223,
+ 0x11123162,
+ }, /* 70 */
+ {
+ 0x21131126,
+ 0x61121231,
+ 0x51123212,
+ }, /* 71 */
+ {
+ 0x31131134,
+ 0x41121314,
+ 0x11123261,
+ }, /* 72 */
+ {
+ 0x41131142,
+ 0x51121322,
+ 0x51123311,
+ }, /* 73 */
+ {
+ 0x21131225,
+ 0x41121413,
+ 0x41124113,
+ }, /* 74 */
+ {
+ 0x31131233,
+ 0x51121421,
+ 0x51124121,
+ }, /* 75 */
+ {
+ 0x41131241,
+ 0x41121512,
+ 0x41124212,
+ }, /* 76 */
+ {
+ 0x11131316,
+ 0x41121611,
+ 0x41124311,
+ }, /* 77 */
+ {
+ 0x21131324,
+ 0x31122116,
+ 0x31125113,
+ }, /* 78 */
+ {
+ 0x31131332,
+ 0x41122124,
+ 0x41125121,
+ }, /* 79 */
+ {
+ 0x11131415,
+ 0x51122132,
+ 0x31125212,
+ }, /* 80 */
+ {
+ 0x21131423,
+ 0x31122215,
+ 0x31125311,
+ }, /* 81 */
+ {
+ 0x11131514,
+ 0x41122223,
+ 0x21126113,
+ }, /* 82 */
+ {
+ 0x11131613,
+ 0x51122231,
+ 0x31126121,
+ }, /* 83 */
+ {
+ 0x11132126,
+ 0x31122314,
+ 0x21126212,
+ }, /* 84 */
+ {
+ 0x21132134,
+ 0x41122322,
+ 0x21126311,
+ }, /* 85 */
+ {
+ 0x31132142,
+ 0x31122413,
+ 0x11131145,
+ }, /* 86 */
+ {
+ 0x11132225,
+ 0x41122421,
+ 0x21131153,
+ }, /* 87 */
+ {
+ 0x21132233,
+ 0x31122512,
+ 0x31131161,
+ }, /* 88 */
+ {
+ 0x31132241,
+ 0x31122611,
+ 0x11131244,
+ }, /* 89 */
+ {
+ 0x11132324,
+ 0x21123116,
+ 0x21131252,
+ }, /* 90 */
+ {
+ 0x21132332,
+ 0x31123124,
+ 0x11131343,
+ }, /* 91 */
+ {
+ 0x11132423,
+ 0x41123132,
+ 0x21131351,
+ }, /* 92 */
+ {
+ 0x11132522,
+ 0x21123215,
+ 0x11131442,
+ }, /* 93 */
+ {
+ 0x11133134,
+ 0x31123223,
+ 0x11131541,
+ }, /* 94 */
+ {
+ 0x21133142,
+ 0x41123231,
+ 0x61132112,
+ }, /* 95 */
+ {
+ 0x11133233,
+ 0x21123314,
+ 0x11132153,
+ }, /* 96 */
+ {
+ 0x21133241,
+ 0x31123322,
+ 0x21132161,
+ }, /* 97 */
+ {
+ 0x11133332,
+ 0x21123413,
+ 0x61132211,
+ }, /* 98 */
+ {
+ 0x11134142,
+ 0x31123421,
+ 0x11132252,
+ }, /* 99 */
+ {
+ 0x21141125,
+ 0x21123512,
+ 0x11132351,
+ }, /* 100 */
+ {
+ 0x31141133,
+ 0x21123611,
+ 0x51133112,
+ }, /* 101 */
+ {
+ 0x41141141,
+ 0x11124116,
+ 0x11133161,
+ }, /* 102 */
+ {
+ 0x11141216,
+ 0x21124124,
+ 0x51133211,
+ }, /* 103 */
+ {
+ 0x21141224,
+ 0x31124132,
+ 0x41134112,
+ }, /* 104 */
+ {
+ 0x31141232,
+ 0x11124215,
+ 0x41134211,
+ }, /* 105 */
+ {
+ 0x11141315,
+ 0x21124223,
+ 0x31135112,
+ }, /* 106 */
+ {
+ 0x21141323,
+ 0x31124231,
+ 0x31135211,
+ }, /* 107 */
+ {
+ 0x31141331,
+ 0x11124314,
+ 0x21136112,
+ }, /* 108 */
+ {
+ 0x11141414,
+ 0x21124322,
+ 0x21136211,
+ }, /* 109 */
+ {
+ 0x21141422,
+ 0x11124413,
+ 0x11141144,
+ }, /* 110 */
+ {
+ 0x11141513,
+ 0x21124421,
+ 0x21141152,
+ }, /* 111 */
+ {
+ 0x21141521,
+ 0x11124512,
+ 0x11141243,
+ }, /* 112 */
+ {
+ 0x11142125,
+ 0x11125124,
+ 0x21141251,
+ }, /* 113 */
+ {
+ 0x21142133,
+ 0x21125132,
+ 0x11141342,
+ }, /* 114 */
+ {
+ 0x31142141,
+ 0x11125223,
+ 0x11141441,
+ }, /* 115 */
+ {
+ 0x11142224,
+ 0x21125231,
+ 0x61142111,
+ }, /* 116 */
+ {
+ 0x21142232,
+ 0x11125322,
+ 0x11142152,
+ }, /* 117 */
+ {
+ 0x11142323,
+ 0x11125421,
+ 0x11142251,
+ }, /* 118 */
+ {
+ 0x21142331,
+ 0x11126132,
+ 0x51143111,
+ }, /* 119 */
+ {
+ 0x11142422,
+ 0x11126231,
+ 0x41144111,
+ }, /* 120 */
+ {
+ 0x11142521,
+ 0x41131115,
+ 0x31145111,
+ }, /* 121 */
+ {
+ 0x21143141,
+ 0x51131123,
+ 0x11151143,
+ }, /* 122 */
+ {
+ 0x11143331,
+ 0x61131131,
+ 0x21151151,
+ }, /* 123 */
+ {
+ 0x11151116,
+ 0x41131214,
+ 0x11151242,
+ }, /* 124 */
+ {
+ 0x21151124,
+ 0x51131222,
+ 0x11151341,
+ }, /* 125 */
+ {
+ 0x31151132,
+ 0x41131313,
+ 0x11152151,
+ }, /* 126 */
+ {
+ 0x11151215,
+ 0x51131321,
+ 0x11161142,
+ }, /* 127 */
+ {
+ 0x21151223,
+ 0x41131412,
+ 0x11161241,
+ }, /* 128 */
+ {
+ 0x31151231,
+ 0x41131511,
+ 0x12111146,
+ }, /* 129 */
+ {
+ 0x11151314,
+ 0x31132115,
+ 0x22111154,
+ }, /* 130 */
+ {
+ 0x21151322,
+ 0x41132123,
+ 0x32111162,
+ }, /* 131 */
+ {
+ 0x11151413,
+ 0x51132131,
+ 0x12111245,
+ }, /* 132 */
+ {
+ 0x21151421,
+ 0x31132214,
+ 0x22111253,
+ }, /* 133 */
+ {
+ 0x11151512,
+ 0x41132222,
+ 0x32111261,
+ }, /* 134 */
+ {
+ 0x11152124,
+ 0x31132313,
+ 0x12111344,
+ }, /* 135 */
+ {
+ 0x11152223,
+ 0x41132321,
+ 0x22111352,
+ }, /* 136 */
+ {
+ 0x11152322,
+ 0x31132412,
+ 0x12111443,
+ }, /* 137 */
+ {
+ 0x11161115,
+ 0x31132511,
+ 0x22111451,
+ }, /* 138 */
+ {
+ 0x31161131,
+ 0x21133115,
+ 0x12111542,
+ }, /* 139 */
+ {
+ 0x21161222,
+ 0x31133123,
+ 0x62112113,
+ }, /* 140 */
+ {
+ 0x21161321,
+ 0x41133131,
+ 0x12112154,
+ }, /* 141 */
+ {
+ 0x11161511,
+ 0x21133214,
+ 0x22112162,
+ }, /* 142 */
+ {
+ 0x32111135,
+ 0x31133222,
+ 0x62112212,
+ }, /* 143 */
+ {
+ 0x42111143,
+ 0x21133313,
+ 0x12112253,
+ }, /* 144 */
+ {
+ 0x52111151,
+ 0x31133321,
+ 0x22112261,
+ }, /* 145 */
+ {
+ 0x22111226,
+ 0x21133412,
+ 0x62112311,
+ }, /* 146 */
+ {
+ 0x32111234,
+ 0x21133511,
+ 0x12112352,
+ }, /* 147 */
+ {
+ 0x42111242,
+ 0x11134115,
+ 0x12112451,
+ }, /* 148 */
+ {
+ 0x22111325,
+ 0x21134123,
+ 0x52113113,
+ }, /* 149 */
+ {
+ 0x32111333,
+ 0x31134131,
+ 0x62113121,
+ }, /* 150 */
+ {
+ 0x42111341,
+ 0x11134214,
+ 0x12113162,
+ }, /* 151 */
+ {
+ 0x12111416,
+ 0x21134222,
+ 0x52113212,
+ }, /* 152 */
+ {
+ 0x22111424,
+ 0x11134313,
+ 0x12113261,
+ }, /* 153 */
+ {
+ 0x12111515,
+ 0x21134321,
+ 0x52113311,
+ }, /* 154 */
+ {
+ 0x22112135,
+ 0x11134412,
+ 0x42114113,
+ }, /* 155 */
+ {
+ 0x32112143,
+ 0x11134511,
+ 0x52114121,
+ }, /* 156 */
+ {
+ 0x42112151,
+ 0x11135123,
+ 0x42114212,
+ }, /* 157 */
+ {
+ 0x12112226,
+ 0x21135131,
+ 0x42114311,
+ }, /* 158 */
+ {
+ 0x22112234,
+ 0x11135222,
+ 0x32115113,
+ }, /* 159 */
+ {
+ 0x32112242,
+ 0x11135321,
+ 0x42115121,
+ }, /* 160 */
+ {
+ 0x12112325,
+ 0x11136131,
+ 0x32115212,
+ }, /* 161 */
+ {
+ 0x22112333,
+ 0x41141114,
+ 0x32115311,
+ }, /* 162 */
+ {
+ 0x12112424,
+ 0x51141122,
+ 0x22116113,
+ }, /* 163 */
+ {
+ 0x12112523,
+ 0x41141213,
+ 0x32116121,
+ }, /* 164 */
+ {
+ 0x12113135,
+ 0x51141221,
+ 0x22116212,
+ }, /* 165 */
+ {
+ 0x22113143,
+ 0x41141312,
+ 0x22116311,
+ }, /* 166 */
+ {
+ 0x32113151,
+ 0x41141411,
+ 0x21211145,
+ }, /* 167 */
+ {
+ 0x12113234,
+ 0x31142114,
+ 0x31211153,
+ }, /* 168 */
+ {
+ 0x22113242,
+ 0x41142122,
+ 0x41211161,
+ }, /* 169 */
+ {
+ 0x12113333,
+ 0x31142213,
+ 0x11211236,
+ }, /* 170 */
+ {
+ 0x12113432,
+ 0x41142221,
+ 0x21211244,
+ }, /* 171 */
+ {
+ 0x12114143,
+ 0x31142312,
+ 0x31211252,
+ }, /* 172 */
+ {
+ 0x22114151,
+ 0x31142411,
+ 0x11211335,
+ }, /* 173 */
+ {
+ 0x12114242,
+ 0x21143114,
+ 0x21211343,
+ }, /* 174 */
+ {
+ 0x12115151,
+ 0x31143122,
+ 0x31211351,
+ }, /* 175 */
+ {
+ 0x31211126,
+ 0x21143213,
+ 0x11211434,
+ }, /* 176 */
+ {
+ 0x41211134,
+ 0x31143221,
+ 0x21211442,
+ }, /* 177 */
+ {
+ 0x51211142,
+ 0x21143312,
+ 0x11211533,
+ }, /* 178 */
+ {
+ 0x31211225,
+ 0x21143411,
+ 0x21211541,
+ }, /* 179 */
+ {
+ 0x41211233,
+ 0x11144114,
+ 0x11211632,
+ }, /* 180 */
+ {
+ 0x51211241,
+ 0x21144122,
+ 0x12121145,
+ }, /* 181 */
+ {
+ 0x21211316,
+ 0x11144213,
+ 0x22121153,
+ }, /* 182 */
+ {
+ 0x31211324,
+ 0x21144221,
+ 0x32121161,
+ }, /* 183 */
+ {
+ 0x41211332,
+ 0x11144312,
+ 0x11212145,
+ }, /* 184 */
+ {
+ 0x21211415,
+ 0x11144411,
+ 0x12121244,
+ }, /* 185 */
+ {
+ 0x31211423,
+ 0x11145122,
+ 0x22121252,
+ }, /* 186 */
+ {
+ 0x41211431,
+ 0x11145221,
+ 0x11212244,
+ }, /* 187 */
+ {
+ 0x21211514,
+ 0x41151113,
+ 0x21212252,
+ }, /* 188 */
+ {
+ 0x31211522,
+ 0x51151121,
+ 0x22121351,
+ }, /* 189 */
+ {
+ 0x22121126,
+ 0x41151212,
+ 0x11212343,
+ }, /* 190 */
+ {
+ 0x32121134,
+ 0x41151311,
+ 0x12121442,
+ }, /* 191 */
+ {
+ 0x42121142,
+ 0x31152113,
+ 0x11212442,
+ }, /* 192 */
+ {
+ 0x21212126,
+ 0x41152121,
+ 0x12121541,
+ }, /* 193 */
+ {
+ 0x22121225,
+ 0x31152212,
+ 0x11212541,
+ }, /* 194 */
+ {
+ 0x32121233,
+ 0x31152311,
+ 0x62122112,
+ }, /* 195 */
+ {
+ 0x42121241,
+ 0x21153113,
+ 0x12122153,
+ }, /* 196 */
+ {
+ 0x21212225,
+ 0x31153121,
+ 0x22122161,
+ }, /* 197 */
+ {
+ 0x31212233,
+ 0x21153212,
+ 0x61213112,
+ }, /* 198 */
+ {
+ 0x41212241,
+ 0x21153311,
+ 0x62122211,
+ }, /* 199 */
+ {
+ 0x11212316,
+ 0x11154113,
+ 0x11213153,
+ }, /* 200 */
+ {
+ 0x12121415,
+ 0x21154121,
+ 0x12122252,
+ }, /* 201 */
+ {
+ 0x22121423,
+ 0x11154212,
+ 0x61213211,
+ }, /* 202 */
+ {
+ 0x32121431,
+ 0x11154311,
+ 0x11213252,
+ }, /* 203 */
+ {
+ 0x11212415,
+ 0x41161112,
+ 0x12122351,
+ }, /* 204 */
+ {
+ 0x21212423,
+ 0x41161211,
+ 0x11213351,
+ }, /* 205 */
+ {
+ 0x11212514,
+ 0x31162112,
+ 0x52123112,
+ }, /* 206 */
+ {
+ 0x12122126,
+ 0x31162211,
+ 0x12123161,
+ }, /* 207 */
+ {
+ 0x22122134,
+ 0x21163112,
+ 0x51214112,
+ }, /* 208 */
+ {
+ 0x32122142,
+ 0x21163211,
+ 0x52123211,
+ }, /* 209 */
+ {
+ 0x11213126,
+ 0x42111116,
+ 0x11214161,
+ }, /* 210 */
+ {
+ 0x12122225,
+ 0x52111124,
+ 0x51214211,
+ }, /* 211 */
+ {
+ 0x22122233,
+ 0x62111132,
+ 0x42124112,
+ }, /* 212 */
+ {
+ 0x32122241,
+ 0x42111215,
+ 0x41215112,
+ }, /* 213 */
+ {
+ 0x11213225,
+ 0x52111223,
+ 0x42124211,
+ }, /* 214 */
+ {
+ 0x21213233,
+ 0x62111231,
+ 0x41215211,
+ }, /* 215 */
+ {
+ 0x31213241,
+ 0x42111314,
+ 0x32125112,
+ }, /* 216 */
+ {
+ 0x11213324,
+ 0x52111322,
+ 0x31216112,
+ }, /* 217 */
+ {
+ 0x12122423,
+ 0x42111413,
+ 0x32125211,
+ }, /* 218 */
+ {
+ 0x11213423,
+ 0x52111421,
+ 0x31216211,
+ }, /* 219 */
+ {
+ 0x12123134,
+ 0x42111512,
+ 0x22126112,
+ }, /* 220 */
+ {
+ 0x22123142,
+ 0x42111611,
+ 0x22126211,
+ }, /* 221 */
+ {
+ 0x11214134,
+ 0x32112116,
+ 0x11221136,
+ }, /* 222 */
+ {
+ 0x12123233,
+ 0x42112124,
+ 0x21221144,
+ }, /* 223 */
+ {
+ 0x22123241,
+ 0x52112132,
+ 0x31221152,
+ }, /* 224 */
+ {
+ 0x11214233,
+ 0x32112215,
+ 0x11221235,
+ }, /* 225 */
+ {
+ 0x21214241,
+ 0x42112223,
+ 0x21221243,
+ }, /* 226 */
+ {
+ 0x11214332,
+ 0x52112231,
+ 0x31221251,
+ }, /* 227 */
+ {
+ 0x12124142,
+ 0x32112314,
+ 0x11221334,
+ }, /* 228 */
+ {
+ 0x11215142,
+ 0x42112322,
+ 0x21221342,
+ }, /* 229 */
+ {
+ 0x12124241,
+ 0x32112413,
+ 0x11221433,
+ }, /* 230 */
+ {
+ 0x11215241,
+ 0x42112421,
+ 0x21221441,
+ }, /* 231 */
+ {
+ 0x31221125,
+ 0x32112512,
+ 0x11221532,
+ }, /* 232 */
+ {
+ 0x41221133,
+ 0x32112611,
+ 0x11221631,
+ }, /* 233 */
+ {
+ 0x51221141,
+ 0x22113116,
+ 0x12131144,
+ }, /* 234 */
+ {
+ 0x21221216,
+ 0x32113124,
+ 0x22131152,
+ }, /* 235 */
+ {
+ 0x31221224,
+ 0x42113132,
+ 0x11222144,
+ }, /* 236 */
+ {
+ 0x41221232,
+ 0x22113215,
+ 0x12131243,
+ }, /* 237 */
+ {
+ 0x21221315,
+ 0x32113223,
+ 0x22131251,
+ }, /* 238 */
+ {
+ 0x31221323,
+ 0x42113231,
+ 0x11222243,
+ }, /* 239 */
+ {
+ 0x41221331,
+ 0x22113314,
+ 0x21222251,
+ }, /* 240 */
+ {
+ 0x21221414,
+ 0x32113322,
+ 0x11222342,
+ }, /* 241 */
+ {
+ 0x31221422,
+ 0x22113413,
+ 0x12131441,
+ }, /* 242 */
+ {
+ 0x21221513,
+ 0x32113421,
+ 0x11222441,
+ }, /* 243 */
+ {
+ 0x21221612,
+ 0x22113512,
+ 0x62132111,
+ }, /* 244 */
+ {
+ 0x22131125,
+ 0x22113611,
+ 0x12132152,
+ }, /* 245 */
+ {
+ 0x32131133,
+ 0x12114116,
+ 0x61223111,
+ }, /* 246 */
+ {
+ 0x42131141,
+ 0x22114124,
+ 0x11223152,
+ }, /* 247 */
+ {
+ 0x21222125,
+ 0x32114132,
+ 0x12132251,
+ }, /* 248 */
+ {
+ 0x22131224,
+ 0x12114215,
+ 0x11223251,
+ }, /* 249 */
+ {
+ 0x32131232,
+ 0x22114223,
+ 0x52133111,
+ }, /* 250 */
+ {
+ 0x11222216,
+ 0x32114231,
+ 0x51224111,
+ }, /* 251 */
+ {
+ 0x12131315,
+ 0x12114314,
+ 0x42134111,
+ }, /* 252 */
+ {
+ 0x31222232,
+ 0x22114322,
+ 0x41225111,
+ }, /* 253 */
+ {
+ 0x32131331,
+ 0x12114413,
+ 0x32135111,
+ }, /* 254 */
+ {
+ 0x11222315,
+ 0x22114421,
+ 0x31226111,
+ }, /* 255 */
+ {
+ 0x12131414,
+ 0x12114512,
+ 0x22136111,
+ }, /* 256 */
+ {
+ 0x22131422,
+ 0x12115124,
+ 0x11231135,
+ }, /* 257 */
+ {
+ 0x11222414,
+ 0x22115132,
+ 0x21231143,
+ }, /* 258 */
+ {
+ 0x21222422,
+ 0x12115223,
+ 0x31231151,
+ }, /* 259 */
+ {
+ 0x22131521,
+ 0x22115231,
+ 0x11231234,
+ }, /* 260 */
+ {
+ 0x12131612,
+ 0x12115322,
+ 0x21231242,
+ }, /* 261 */
+ {
+ 0x12132125,
+ 0x12115421,
+ 0x11231333,
+ }, /* 262 */
+ {
+ 0x22132133,
+ 0x12116132,
+ 0x21231341,
+ }, /* 263 */
+ {
+ 0x32132141,
+ 0x12116231,
+ 0x11231432,
+ }, /* 264 */
+ {
+ 0x11223125,
+ 0x51211115,
+ 0x11231531,
+ }, /* 265 */
+ {
+ 0x12132224,
+ 0x61211123,
+ 0x12141143,
+ }, /* 266 */
+ {
+ 0x22132232,
+ 0x11211164,
+ 0x22141151,
+ }, /* 267 */
+ {
+ 0x11223224,
+ 0x51211214,
+ 0x11232143,
+ }, /* 268 */
+ {
+ 0x21223232,
+ 0x61211222,
+ 0x12141242,
+ }, /* 269 */
+ {
+ 0x22132331,
+ 0x11211263,
+ 0x11232242,
+ }, /* 270 */
+ {
+ 0x11223323,
+ 0x51211313,
+ 0x12141341,
+ }, /* 271 */
+ {
+ 0x12132422,
+ 0x61211321,
+ 0x11232341,
+ }, /* 272 */
+ {
+ 0x12132521,
+ 0x11211362,
+ 0x12142151,
+ }, /* 273 */
+ {
+ 0x12133133,
+ 0x51211412,
+ 0x11233151,
+ }, /* 274 */
+ {
+ 0x22133141,
+ 0x51211511,
+ 0x11241134,
+ }, /* 275 */
+ {
+ 0x11224133,
+ 0x42121115,
+ 0x21241142,
+ }, /* 276 */
+ {
+ 0x12133232,
+ 0x52121123,
+ 0x11241233,
+ }, /* 277 */
+ {
+ 0x11224232,
+ 0x62121131,
+ 0x21241241,
+ }, /* 278 */
+ {
+ 0x12133331,
+ 0x41212115,
+ 0x11241332,
+ }, /* 279 */
+ {
+ 0x11224331,
+ 0x42121214,
+ 0x11241431,
+ }, /* 280 */
+ {
+ 0x11225141,
+ 0x61212131,
+ 0x12151142,
+ }, /* 281 */
+ {
+ 0x21231116,
+ 0x41212214,
+ 0x11242142,
+ }, /* 282 */
+ {
+ 0x31231124,
+ 0x51212222,
+ 0x12151241,
+ }, /* 283 */
+ {
+ 0x41231132,
+ 0x52121321,
+ 0x11242241,
+ }, /* 284 */
+ {
+ 0x21231215,
+ 0x41212313,
+ 0x11251133,
+ }, /* 285 */
+ {
+ 0x31231223,
+ 0x42121412,
+ 0x21251141,
+ }, /* 286 */
+ {
+ 0x41231231,
+ 0x41212412,
+ 0x11251232,
+ }, /* 287 */
+ {
+ 0x21231314,
+ 0x42121511,
+ 0x11251331,
+ }, /* 288 */
+ {
+ 0x31231322,
+ 0x41212511,
+ 0x12161141,
+ }, /* 289 */
+ {
+ 0x21231413,
+ 0x32122115,
+ 0x11252141,
+ }, /* 290 */
+ {
+ 0x31231421,
+ 0x42122123,
+ 0x11261132,
+ }, /* 291 */
+ {
+ 0x21231512,
+ 0x52122131,
+ 0x11261231,
+ }, /* 292 */
+ {
+ 0x21231611,
+ 0x31213115,
+ 0x13111145,
+ }, /* 293 */
+ {
+ 0x12141116,
+ 0x32122214,
+ 0x23111153,
+ }, /* 294 */
+ {
+ 0x22141124,
+ 0x42122222,
+ 0x33111161,
+ }, /* 295 */
+ {
+ 0x32141132,
+ 0x31213214,
+ 0x13111244,
+ }, /* 296 */
+ {
+ 0x11232116,
+ 0x41213222,
+ 0x23111252,
+ }, /* 297 */
+ {
+ 0x12141215,
+ 0x42122321,
+ 0x13111343,
+ }, /* 298 */
+ {
+ 0x22141223,
+ 0x31213313,
+ 0x23111351,
+ }, /* 299 */
+ {
+ 0x32141231,
+ 0x32122412,
+ 0x13111442,
+ }, /* 300 */
+ {
+ 0x11232215,
+ 0x31213412,
+ 0x13111541,
+ }, /* 301 */
+ {
+ 0x21232223,
+ 0x32122511,
+ 0x63112112,
+ }, /* 302 */
+ {
+ 0x31232231,
+ 0x31213511,
+ 0x13112153,
+ }, /* 303 */
+ {
+ 0x11232314,
+ 0x22123115,
+ 0x23112161,
+ }, /* 304 */
+ {
+ 0x12141413,
+ 0x32123123,
+ 0x63112211,
+ }, /* 305 */
+ {
+ 0x22141421,
+ 0x42123131,
+ 0x13112252,
+ }, /* 306 */
+ {
+ 0x11232413,
+ 0x21214115,
+ 0x13112351,
+ }, /* 307 */
+ {
+ 0x21232421,
+ 0x22123214,
+ 0x53113112,
+ }, /* 308 */
+ {
+ 0x11232512,
+ 0x32123222,
+ 0x13113161,
+ }, /* 309 */
+ {
+ 0x12142124,
+ 0x21214214,
+ 0x53113211,
+ }, /* 310 */
+ {
+ 0x22142132,
+ 0x31214222,
+ 0x43114112,
+ }, /* 311 */
+ {
+ 0x11233124,
+ 0x32123321,
+ 0x43114211,
+ }, /* 312 */
+ {
+ 0x12142223,
+ 0x21214313,
+ 0x33115112,
+ }, /* 313 */
+ {
+ 0x22142231,
+ 0x22123412,
+ 0x33115211,
+ }, /* 314 */
+ {
+ 0x11233223,
+ 0x21214412,
+ 0x23116112,
+ }, /* 315 */
+ {
+ 0x21233231,
+ 0x22123511,
+ 0x23116211,
+ }, /* 316 */
+ {
+ 0x11233322,
+ 0x21214511,
+ 0x12211136,
+ }, /* 317 */
+ {
+ 0x12142421,
+ 0x12124115,
+ 0x22211144,
+ }, /* 318 */
+ {
+ 0x11233421,
+ 0x22124123,
+ 0x32211152,
+ }, /* 319 */
+ {
+ 0x11234132,
+ 0x32124131,
+ 0x12211235,
+ }, /* 320 */
+ {
+ 0x11234231,
+ 0x11215115,
+ 0x22211243,
+ }, /* 321 */
+ {
+ 0x21241115,
+ 0x12124214,
+ 0x32211251,
+ }, /* 322 */
+ {
+ 0x31241123,
+ 0x22124222,
+ 0x12211334,
+ }, /* 323 */
+ {
+ 0x41241131,
+ 0x11215214,
+ 0x22211342,
+ }, /* 324 */
+ {
+ 0x21241214,
+ 0x21215222,
+ 0x12211433,
+ }, /* 325 */
+ {
+ 0x31241222,
+ 0x22124321,
+ 0x22211441,
+ }, /* 326 */
+ {
+ 0x21241313,
+ 0x11215313,
+ 0x12211532,
+ }, /* 327 */
+ {
+ 0x31241321,
+ 0x12124412,
+ 0x12211631,
+ }, /* 328 */
+ {
+ 0x21241412,
+ 0x11215412,
+ 0x13121144,
+ }, /* 329 */
+ {
+ 0x21241511,
+ 0x12124511,
+ 0x23121152,
+ }, /* 330 */
+ {
+ 0x12151115,
+ 0x12125123,
+ 0x12212144,
+ }, /* 331 */
+ {
+ 0x22151123,
+ 0x22125131,
+ 0x13121243,
+ }, /* 332 */
+ {
+ 0x32151131,
+ 0x11216123,
+ 0x23121251,
+ }, /* 333 */
+ {
+ 0x11242115,
+ 0x12125222,
+ 0x12212243,
+ }, /* 334 */
+ {
+ 0x12151214,
+ 0x11216222,
+ 0x22212251,
+ }, /* 335 */
+ {
+ 0x22151222,
+ 0x12125321,
+ 0x12212342,
+ }, /* 336 */
+ {
+ 0x11242214,
+ 0x11216321,
+ 0x13121441,
+ }, /* 337 */
+ {
+ 0x21242222,
+ 0x12126131,
+ 0x12212441,
+ }, /* 338 */
+ {
+ 0x22151321,
+ 0x51221114,
+ 0x63122111,
+ }, /* 339 */
+ {
+ 0x11242313,
+ 0x61221122,
+ 0x13122152,
+ }, /* 340 */
+ {
+ 0x12151412,
+ 0x11221163,
+ 0x62213111,
+ }, /* 341 */
+ {
+ 0x11242412,
+ 0x51221213,
+ 0x12213152,
+ }, /* 342 */
+ {
+ 0x12151511,
+ 0x61221221,
+ 0x13122251,
+ }, /* 343 */
+ {
+ 0x12152123,
+ 0x11221262,
+ 0x12213251,
+ }, /* 344 */
+ {
+ 0x11243123,
+ 0x51221312,
+ 0x53123111,
+ }, /* 345 */
+ {
+ 0x11243222,
+ 0x11221361,
+ 0x52214111,
+ }, /* 346 */
+ {
+ 0x11243321,
+ 0x51221411,
+ 0x43124111,
+ }, /* 347 */
+ {
+ 0x31251122,
+ 0x42131114,
+ 0x42215111,
+ }, /* 348 */
+ {
+ 0x31251221,
+ 0x52131122,
+ 0x33125111,
+ }, /* 349 */
+ {
+ 0x21251411,
+ 0x41222114,
+ 0x32216111,
+ }, /* 350 */
+ {
+ 0x22161122,
+ 0x42131213,
+ 0x23126111,
+ }, /* 351 */
+ {
+ 0x12161213,
+ 0x52131221,
+ 0x21311135,
+ }, /* 352 */
+ {
+ 0x11252213,
+ 0x41222213,
+ 0x31311143,
+ }, /* 353 */
+ {
+ 0x11252312,
+ 0x51222221,
+ 0x41311151,
+ }, /* 354 */
+ {
+ 0x11252411,
+ 0x41222312,
+ 0x11311226,
+ }, /* 355 */
+ {
+ 0x23111126,
+ 0x42131411,
+ 0x21311234,
+ }, /* 356 */
+ {
+ 0x33111134,
+ 0x41222411,
+ 0x31311242,
+ }, /* 357 */
+ {
+ 0x43111142,
+ 0x32132114,
+ 0x11311325,
+ }, /* 358 */
+ {
+ 0x23111225,
+ 0x42132122,
+ 0x21311333,
+ }, /* 359 */
+ {
+ 0x33111233,
+ 0x31223114,
+ 0x31311341,
+ }, /* 360 */
+ {
+ 0x13111316,
+ 0x32132213,
+ 0x11311424,
+ }, /* 361 */
+ {
+ 0x23111324,
+ 0x42132221,
+ 0x21311432,
+ }, /* 362 */
+ {
+ 0x33111332,
+ 0x31223213,
+ 0x11311523,
+ }, /* 363 */
+ {
+ 0x13111415,
+ 0x41223221,
+ 0x21311531,
+ }, /* 364 */
+ {
+ 0x23111423,
+ 0x31223312,
+ 0x11311622,
+ }, /* 365 */
+ {
+ 0x13111514,
+ 0x32132411,
+ 0x12221135,
+ }, /* 366 */
+ {
+ 0x13111613,
+ 0x31223411,
+ 0x22221143,
+ }, /* 367 */
+ {
+ 0x13112126,
+ 0x22133114,
+ 0x32221151,
+ }, /* 368 */
+ {
+ 0x23112134,
+ 0x32133122,
+ 0x11312135,
+ }, /* 369 */
+ {
+ 0x33112142,
+ 0x21224114,
+ 0x12221234,
+ }, /* 370 */
+ {
+ 0x13112225,
+ 0x22133213,
+ 0x22221242,
+ }, /* 371 */
+ {
+ 0x23112233,
+ 0x32133221,
+ 0x11312234,
+ }, /* 372 */
+ {
+ 0x33112241,
+ 0x21224213,
+ 0x21312242,
+ }, /* 373 */
+ {
+ 0x13112324,
+ 0x31224221,
+ 0x22221341,
+ }, /* 374 */
+ {
+ 0x23112332,
+ 0x21224312,
+ 0x11312333,
+ }, /* 375 */
+ {
+ 0x13112423,
+ 0x22133411,
+ 0x12221432,
+ }, /* 376 */
+ {
+ 0x13112522,
+ 0x21224411,
+ 0x11312432,
+ }, /* 377 */
+ {
+ 0x13113134,
+ 0x12134114,
+ 0x12221531,
+ }, /* 378 */
+ {
+ 0x23113142,
+ 0x22134122,
+ 0x11312531,
+ }, /* 379 */
+ {
+ 0x13113233,
+ 0x11225114,
+ 0x13131143,
+ }, /* 380 */
+ {
+ 0x23113241,
+ 0x12134213,
+ 0x23131151,
+ }, /* 381 */
+ {
+ 0x13113332,
+ 0x22134221,
+ 0x12222143,
+ }, /* 382 */
+ {
+ 0x13114142,
+ 0x11225213,
+ 0x13131242,
+ }, /* 383 */
+ {
+ 0x13114241,
+ 0x21225221,
+ 0x11313143,
+ }, /* 384 */
+ {
+ 0x32211125,
+ 0x11225312,
+ 0x12222242,
+ }, /* 385 */
+ {
+ 0x42211133,
+ 0x12134411,
+ 0x13131341,
+ }, /* 386 */
+ {
+ 0x52211141,
+ 0x11225411,
+ 0x11313242,
+ }, /* 387 */
+ {
+ 0x22211216,
+ 0x12135122,
+ 0x12222341,
+ }, /* 388 */
+ {
+ 0x32211224,
+ 0x11226122,
+ 0x11313341,
+ }, /* 389 */
+ {
+ 0x42211232,
+ 0x12135221,
+ 0x13132151,
+ }, /* 390 */
+ {
+ 0x22211315,
+ 0x11226221,
+ 0x12223151,
+ }, /* 391 */
+ {
+ 0x32211323,
+ 0x51231113,
+ 0x11314151,
+ }, /* 392 */
+ {
+ 0x42211331,
+ 0x61231121,
+ 0x11321126,
+ }, /* 393 */
+ {
+ 0x22211414,
+ 0x11231162,
+ 0x21321134,
+ }, /* 394 */
+ {
+ 0x32211422,
+ 0x51231212,
+ 0x31321142,
+ }, /* 395 */
+ {
+ 0x22211513,
+ 0x11231261,
+ 0x11321225,
+ }, /* 396 */
+ {
+ 0x32211521,
+ 0x51231311,
+ 0x21321233,
+ }, /* 397 */
+ {
+ 0x23121125,
+ 0x42141113,
+ 0x31321241,
+ }, /* 398 */
+ {
+ 0x33121133,
+ 0x52141121,
+ 0x11321324,
+ }, /* 399 */
+ {
+ 0x43121141,
+ 0x41232113,
+ 0x21321332,
+ }, /* 400 */
+ {
+ 0x22212125,
+ 0x51232121,
+ 0x11321423,
+ }, /* 401 */
+ {
+ 0x23121224,
+ 0x41232212,
+ 0x21321431,
+ }, /* 402 */
+ {
+ 0x33121232,
+ 0x42141311,
+ 0x11321522,
+ }, /* 403 */
+ {
+ 0x12212216,
+ 0x41232311,
+ 0x11321621,
+ }, /* 404 */
+ {
+ 0x13121315,
+ 0x32142113,
+ 0x12231134,
+ }, /* 405 */
+ {
+ 0x32212232,
+ 0x42142121,
+ 0x22231142,
+ }, /* 406 */
+ {
+ 0x33121331,
+ 0x31233113,
+ 0x11322134,
+ }, /* 407 */
+ {
+ 0x12212315,
+ 0x32142212,
+ 0x12231233,
+ }, /* 408 */
+ {
+ 0x22212323,
+ 0x31233212,
+ 0x22231241,
+ }, /* 409 */
+ {
+ 0x23121422,
+ 0x32142311,
+ 0x11322233,
+ }, /* 410 */
+ {
+ 0x12212414,
+ 0x31233311,
+ 0x21322241,
+ }, /* 411 */
+ {
+ 0x13121513,
+ 0x22143113,
+ 0x11322332,
+ }, /* 412 */
+ {
+ 0x12212513,
+ 0x32143121,
+ 0x12231431,
+ }, /* 413 */
+ {
+ 0x13122125,
+ 0x21234113,
+ 0x11322431,
+ }, /* 414 */
+ {
+ 0x23122133,
+ 0x31234121,
+ 0x13141142,
+ }, /* 415 */
+ {
+ 0x33122141,
+ 0x21234212,
+ 0x12232142,
+ }, /* 416 */
+ {
+ 0x12213125,
+ 0x22143311,
+ 0x13141241,
+ }, /* 417 */
+ {
+ 0x13122224,
+ 0x21234311,
+ 0x11323142,
+ }, /* 418 */
+ {
+ 0x32213141,
+ 0x12144113,
+ 0x12232241,
+ }, /* 419 */
+ {
+ 0x12213224,
+ 0x22144121,
+ 0x11323241,
+ }, /* 420 */
+ {
+ 0x22213232,
+ 0x11235113,
+ 0x11331125,
+ }, /* 421 */
+ {
+ 0x23122331,
+ 0x12144212,
+ 0x21331133,
+ }, /* 422 */
+ {
+ 0x12213323,
+ 0x11235212,
+ 0x31331141,
+ }, /* 423 */
+ {
+ 0x13122422,
+ 0x12144311,
+ 0x11331224,
+ }, /* 424 */
+ {
+ 0x12213422,
+ 0x11235311,
+ 0x21331232,
+ }, /* 425 */
+ {
+ 0x13123133,
+ 0x12145121,
+ 0x11331323,
+ }, /* 426 */
+ {
+ 0x23123141,
+ 0x11236121,
+ 0x21331331,
+ }, /* 427 */
+ {
+ 0x12214133,
+ 0x51241112,
+ 0x11331422,
+ }, /* 428 */
+ {
+ 0x13123232,
+ 0x11241161,
+ 0x11331521,
+ }, /* 429 */
+ {
+ 0x12214232,
+ 0x51241211,
+ 0x12241133,
+ }, /* 430 */
+ {
+ 0x13123331,
+ 0x42151112,
+ 0x22241141,
+ }, /* 431 */
+ {
+ 0x13124141,
+ 0x41242112,
+ 0x11332133,
+ }, /* 432 */
+ {
+ 0x12215141,
+ 0x42151211,
+ 0x12241232,
+ }, /* 433 */
+ {
+ 0x31311116,
+ 0x41242211,
+ 0x11332232,
+ }, /* 434 */
+ {
+ 0x41311124,
+ 0x32152112,
+ 0x12241331,
+ }, /* 435 */
+ {
+ 0x51311132,
+ 0x31243112,
+ 0x11332331,
+ }, /* 436 */
+ {
+ 0x31311215,
+ 0x32152211,
+ 0x13151141,
+ }, /* 437 */
+ {
+ 0x41311223,
+ 0x31243211,
+ 0x12242141,
+ }, /* 438 */
+ {
+ 0x51311231,
+ 0x22153112,
+ 0x11333141,
+ }, /* 439 */
+ {
+ 0x31311314,
+ 0x21244112,
+ 0x11341124,
+ }, /* 440 */
+ {
+ 0x41311322,
+ 0x22153211,
+ 0x21341132,
+ }, /* 441 */
+ {
+ 0x31311413,
+ 0x21244211,
+ 0x11341223,
+ }, /* 442 */
+ {
+ 0x41311421,
+ 0x12154112,
+ 0x21341231,
+ }, /* 443 */
+ {
+ 0x31311512,
+ 0x11245112,
+ 0x11341322,
+ }, /* 444 */
+ {
+ 0x22221116,
+ 0x12154211,
+ 0x11341421,
+ }, /* 445 */
+ {
+ 0x32221124,
+ 0x11245211,
+ 0x12251132,
+ }, /* 446 */
+ {
+ 0x42221132,
+ 0x51251111,
+ 0x11342132,
+ }, /* 447 */
+ {
+ 0x21312116,
+ 0x42161111,
+ 0x12251231,
+ }, /* 448 */
+ {
+ 0x22221215,
+ 0x41252111,
+ 0x11342231,
+ }, /* 449 */
+ {
+ 0x41312132,
+ 0x32162111,
+ 0x11351123,
+ }, /* 450 */
+ {
+ 0x42221231,
+ 0x31253111,
+ 0x21351131,
+ }, /* 451 */
+ {
+ 0x21312215,
+ 0x22163111,
+ 0x11351222,
+ }, /* 452 */
+ {
+ 0x31312223,
+ 0x21254111,
+ 0x11351321,
+ }, /* 453 */
+ {
+ 0x41312231,
+ 0x43111115,
+ 0x12261131,
+ }, /* 454 */
+ {
+ 0x21312314,
+ 0x53111123,
+ 0x11352131,
+ }, /* 455 */
+ {
+ 0x22221413,
+ 0x63111131,
+ 0x11361122,
+ }, /* 456 */
+ {
+ 0x32221421,
+ 0x43111214,
+ 0x11361221,
+ }, /* 457 */
+ {
+ 0x21312413,
+ 0x53111222,
+ 0x14111144,
+ }, /* 458 */
+ {
+ 0x31312421,
+ 0x43111313,
+ 0x24111152,
+ }, /* 459 */
+ {
+ 0x22221611,
+ 0x53111321,
+ 0x14111243,
+ }, /* 460 */
+ {
+ 0x13131116,
+ 0x43111412,
+ 0x24111251,
+ }, /* 461 */
+ {
+ 0x23131124,
+ 0x43111511,
+ 0x14111342,
+ }, /* 462 */
+ {
+ 0x33131132,
+ 0x33112115,
+ 0x14111441,
+ }, /* 463 */
+ {
+ 0x12222116,
+ 0x43112123,
+ 0x14112152,
+ }, /* 464 */
+ {
+ 0x13131215,
+ 0x53112131,
+ 0x14112251,
+ }, /* 465 */
+ {
+ 0x23131223,
+ 0x33112214,
+ 0x54113111,
+ }, /* 466 */
+ {
+ 0x33131231,
+ 0x43112222,
+ 0x44114111,
+ }, /* 467 */
+ {
+ 0x11313116,
+ 0x33112313,
+ 0x34115111,
+ }, /* 468 */
+ {
+ 0x12222215,
+ 0x43112321,
+ 0x24116111,
+ }, /* 469 */
+ {
+ 0x22222223,
+ 0x33112412,
+ 0x13211135,
+ }, /* 470 */
+ {
+ 0x32222231,
+ 0x33112511,
+ 0x23211143,
+ }, /* 471 */
+ {
+ 0x11313215,
+ 0x23113115,
+ 0x33211151,
+ }, /* 472 */
+ {
+ 0x21313223,
+ 0x33113123,
+ 0x13211234,
+ }, /* 473 */
+ {
+ 0x31313231,
+ 0x43113131,
+ 0x23211242,
+ }, /* 474 */
+ {
+ 0x23131421,
+ 0x23113214,
+ 0x13211333,
+ }, /* 475 */
+ {
+ 0x11313314,
+ 0x33113222,
+ 0x23211341,
+ }, /* 476 */
+ {
+ 0x12222413,
+ 0x23113313,
+ 0x13211432,
+ }, /* 477 */
+ {
+ 0x22222421,
+ 0x33113321,
+ 0x13211531,
+ }, /* 478 */
+ {
+ 0x11313413,
+ 0x23113412,
+ 0x14121143,
+ }, /* 479 */
+ {
+ 0x13131611,
+ 0x23113511,
+ 0x24121151,
+ }, /* 480 */
+ {
+ 0x13132124,
+ 0x13114115,
+ 0x13212143,
+ }, /* 481 */
+ {
+ 0x23132132,
+ 0x23114123,
+ 0x14121242,
+ }, /* 482 */
+ {
+ 0x12223124,
+ 0x33114131,
+ 0x13212242,
+ }, /* 483 */
+ {
+ 0x13132223,
+ 0x13114214,
+ 0x14121341,
+ }, /* 484 */
+ {
+ 0x23132231,
+ 0x23114222,
+ 0x13212341,
+ }, /* 485 */
+ {
+ 0x11314124,
+ 0x13114313,
+ 0x14122151,
+ }, /* 486 */
+ {
+ 0x12223223,
+ 0x23114321,
+ 0x13213151,
+ }, /* 487 */
+ {
+ 0x22223231,
+ 0x13114412,
+ 0x12311126,
+ }, /* 488 */
+ {
+ 0x11314223,
+ 0x13114511,
+ 0x22311134,
+ }, /* 489 */
+ {
+ 0x21314231,
+ 0x13115123,
+ 0x32311142,
+ }, /* 490 */
+ {
+ 0x13132421,
+ 0x23115131,
+ 0x12311225,
+ }, /* 491 */
+ {
+ 0x12223421,
+ 0x13115222,
+ 0x22311233,
+ }, /* 492 */
+ {
+ 0x13133132,
+ 0x13115321,
+ 0x32311241,
+ }, /* 493 */
+ {
+ 0x12224132,
+ 0x13116131,
+ 0x12311324,
+ }, /* 494 */
+ {
+ 0x13133231,
+ 0x52211114,
+ 0x22311332,
+ }, /* 495 */
+ {
+ 0x11315132,
+ 0x62211122,
+ 0x12311423,
+ }, /* 496 */
+ {
+ 0x12224231,
+ 0x12211163,
+ 0x22311431,
+ }, /* 497 */
+ {
+ 0x31321115,
+ 0x52211213,
+ 0x12311522,
+ }, /* 498 */
+ {
+ 0x41321123,
+ 0x62211221,
+ 0x12311621,
+ }, /* 499 */
+ {
+ 0x51321131,
+ 0x12211262,
+ 0x13221134,
+ }, /* 500 */
+ {
+ 0x31321214,
+ 0x52211312,
+ 0x23221142,
+ }, /* 501 */
+ {
+ 0x41321222,
+ 0x12211361,
+ 0x12312134,
+ }, /* 502 */
+ {
+ 0x31321313,
+ 0x52211411,
+ 0x13221233,
+ }, /* 503 */
+ {
+ 0x41321321,
+ 0x43121114,
+ 0x23221241,
+ }, /* 504 */
+ {
+ 0x31321412,
+ 0x53121122,
+ 0x12312233,
+ }, /* 505 */
+ {
+ 0x31321511,
+ 0x42212114,
+ 0x13221332,
+ }, /* 506 */
+ {
+ 0x22231115,
+ 0x43121213,
+ 0x12312332,
+ }, /* 507 */
+ {
+ 0x32231123,
+ 0x53121221,
+ 0x13221431,
+ }, /* 508 */
+ {
+ 0x42231131,
+ 0x42212213,
+ 0x12312431,
+ }, /* 509 */
+ {
+ 0x21322115,
+ 0x52212221,
+ 0x14131142,
+ }, /* 510 */
+ {
+ 0x22231214,
+ 0x42212312,
+ 0x13222142,
+ }, /* 511 */
+ {
+ 0x41322131,
+ 0x43121411,
+ 0x14131241,
+ }, /* 512 */
+ {
+ 0x21322214,
+ 0x42212411,
+ 0x12313142,
+ }, /* 513 */
+ {
+ 0x31322222,
+ 0x33122114,
+ 0x13222241,
+ }, /* 514 */
+ {
+ 0x32231321,
+ 0x43122122,
+ 0x12313241,
+ }, /* 515 */
+ {
+ 0x21322313,
+ 0x32213114,
+ 0x21411125,
+ }, /* 516 */
+ {
+ 0x22231412,
+ 0x33122213,
+ 0x31411133,
+ }, /* 517 */
+ {
+ 0x21322412,
+ 0x43122221,
+ 0x41411141,
+ }, /* 518 */
+ {
+ 0x22231511,
+ 0x32213213,
+ 0x11411216,
+ }, /* 519 */
+ {
+ 0x21322511,
+ 0x42213221,
+ 0x21411224,
+ }, /* 520 */
+ {
+ 0x13141115,
+ 0x32213312,
+ 0x31411232,
+ }, /* 521 */
+ {
+ 0x23141123,
+ 0x33122411,
+ 0x11411315,
+ }, /* 522 */
+ {
+ 0x33141131,
+ 0x32213411,
+ 0x21411323,
+ }, /* 523 */
+ {
+ 0x12232115,
+ 0x23123114,
+ 0x31411331,
+ }, /* 524 */
+ {
+ 0x13141214,
+ 0x33123122,
+ 0x11411414,
+ }, /* 525 */
+ {
+ 0x23141222,
+ 0x22214114,
+ 0x21411422,
+ }, /* 526 */
+ {
+ 0x11323115,
+ 0x23123213,
+ 0x11411513,
+ }, /* 527 */
+ {
+ 0x12232214,
+ 0x33123221,
+ 0x21411521,
+ }, /* 528 */
+ {
+ 0x22232222,
+ 0x22214213,
+ 0x11411612,
+ }, /* 529 */
+ {
+ 0x23141321,
+ 0x32214221,
+ 0x12321125,
+ }, /* 530 */
+ {
+ 0x11323214,
+ 0x22214312,
+ 0x22321133,
+ }, /* 531 */
+ {
+ 0x21323222,
+ 0x23123411,
+ 0x32321141,
+ }, /* 532 */
+ {
+ 0x13141412,
+ 0x22214411,
+ 0x11412125,
+ }, /* 533 */
+ {
+ 0x11323313,
+ 0x13124114,
+ 0x12321224,
+ }, /* 534 */
+ {
+ 0x12232412,
+ 0x23124122,
+ 0x22321232,
+ }, /* 535 */
+ {
+ 0x13141511,
+ 0x12215114,
+ 0x11412224,
+ }, /* 536 */
+ {
+ 0x12232511,
+ 0x13124213,
+ 0x21412232,
+ }, /* 537 */
+ {
+ 0x13142123,
+ 0x23124221,
+ 0x22321331,
+ }, /* 538 */
+ {
+ 0x23142131,
+ 0x12215213,
+ 0x11412323,
+ }, /* 539 */
+ {
+ 0x12233123,
+ 0x22215221,
+ 0x12321422,
+ }, /* 540 */
+ {
+ 0x13142222,
+ 0x12215312,
+ 0x11412422,
+ }, /* 541 */
+ {
+ 0x11324123,
+ 0x13124411,
+ 0x12321521,
+ }, /* 542 */
+ {
+ 0x12233222,
+ 0x12215411,
+ 0x11412521,
+ }, /* 543 */
+ {
+ 0x13142321,
+ 0x13125122,
+ 0x13231133,
+ }, /* 544 */
+ {
+ 0x11324222,
+ 0x12216122,
+ 0x23231141,
+ }, /* 545 */
+ {
+ 0x12233321,
+ 0x13125221,
+ 0x12322133,
+ }, /* 546 */
+ {
+ 0x13143131,
+ 0x12216221,
+ 0x13231232,
+ }, /* 547 */
+ {
+ 0x11325131,
+ 0x61311113,
+ 0x11413133,
+ }, /* 548 */
+ {
+ 0x31331114,
+ 0x11311154,
+ 0x12322232,
+ }, /* 549 */
+ {
+ 0x41331122,
+ 0x21311162,
+ 0x13231331,
+ }, /* 550 */
+ {
+ 0x31331213,
+ 0x61311212,
+ 0x11413232,
+ }, /* 551 */
+ {
+ 0x41331221,
+ 0x11311253,
+ 0x12322331,
+ }, /* 552 */
+ {
+ 0x31331312,
+ 0x21311261,
+ 0x11413331,
+ }, /* 553 */
+ {
+ 0x31331411,
+ 0x61311311,
+ 0x14141141,
+ }, /* 554 */
+ {
+ 0x22241114,
+ 0x11311352,
+ 0x13232141,
+ }, /* 555 */
+ {
+ 0x32241122,
+ 0x11311451,
+ 0x12323141,
+ }, /* 556 */
+ {
+ 0x21332114,
+ 0x52221113,
+ 0x11414141,
+ }, /* 557 */
+ {
+ 0x22241213,
+ 0x62221121,
+ 0x11421116,
+ }, /* 558 */
+ {
+ 0x32241221,
+ 0x12221162,
+ 0x21421124,
+ }, /* 559 */
+ {
+ 0x21332213,
+ 0x51312113,
+ 0x31421132,
+ }, /* 560 */
+ {
+ 0x31332221,
+ 0x61312121,
+ 0x11421215,
+ }, /* 561 */
+ {
+ 0x21332312,
+ 0x11312162,
+ 0x21421223,
+ }, /* 562 */
+ {
+ 0x22241411,
+ 0x12221261,
+ 0x31421231,
+ }, /* 563 */
+ {
+ 0x21332411,
+ 0x51312212,
+ 0x11421314,
+ }, /* 564 */
+ {
+ 0x13151114,
+ 0x52221311,
+ 0x21421322,
+ }, /* 565 */
+ {
+ 0x23151122,
+ 0x11312261,
+ 0x11421413,
+ }, /* 566 */
+ {
+ 0x12242114,
+ 0x51312311,
+ 0x21421421,
+ }, /* 567 */
+ {
+ 0x13151213,
+ 0x43131113,
+ 0x11421512,
+ }, /* 568 */
+ {
+ 0x23151221,
+ 0x53131121,
+ 0x11421611,
+ }, /* 569 */
+ {
+ 0x11333114,
+ 0x42222113,
+ 0x12331124,
+ }, /* 570 */
+ {
+ 0x12242213,
+ 0x43131212,
+ 0x22331132,
+ }, /* 571 */
+ {
+ 0x22242221,
+ 0x41313113,
+ 0x11422124,
+ }, /* 572 */
+ {
+ 0x11333213,
+ 0x51313121,
+ 0x12331223,
+ }, /* 573 */
+ {
+ 0x21333221,
+ 0x43131311,
+ 0x22331231,
+ }, /* 574 */
+ {
+ 0x13151411,
+ 0x41313212,
+ 0x11422223,
+ }, /* 575 */
+ {
+ 0x11333312,
+ 0x42222311,
+ 0x21422231,
+ }, /* 576 */
+ {
+ 0x12242411,
+ 0x41313311,
+ 0x11422322,
+ }, /* 577 */
+ {
+ 0x11333411,
+ 0x33132113,
+ 0x12331421,
+ }, /* 578 */
+ {
+ 0x12243122,
+ 0x43132121,
+ 0x11422421,
+ }, /* 579 */
+ {
+ 0x11334122,
+ 0x32223113,
+ 0x13241132,
+ }, /* 580 */
+ {
+ 0x11334221,
+ 0x33132212,
+ 0x12332132,
+ }, /* 581 */
+ {
+ 0x41341121,
+ 0x31314113,
+ 0x13241231,
+ }, /* 582 */
+ {
+ 0x31341311,
+ 0x32223212,
+ 0x11423132,
+ }, /* 583 */
+ {
+ 0x32251121,
+ 0x33132311,
+ 0x12332231,
+ }, /* 584 */
+ {
+ 0x22251212,
+ 0x31314212,
+ 0x11423231,
+ }, /* 585 */
+ {
+ 0x22251311,
+ 0x32223311,
+ 0x11431115,
+ }, /* 586 */
+ {
+ 0x13161113,
+ 0x31314311,
+ 0x21431123,
+ }, /* 587 */
+ {
+ 0x12252113,
+ 0x23133113,
+ 0x31431131,
+ }, /* 588 */
+ {
+ 0x11343113,
+ 0x33133121,
+ 0x11431214,
+ }, /* 589 */
+ {
+ 0x13161311,
+ 0x22224113,
+ 0x21431222,
+ }, /* 590 */
+ {
+ 0x12252311,
+ 0x23133212,
+ 0x11431313,
+ }, /* 591 */
+ {
+ 0x24111125,
+ 0x21315113,
+ 0x21431321,
+ }, /* 592 */
+ {
+ 0x14111216,
+ 0x22224212,
+ 0x11431412,
+ }, /* 593 */
+ {
+ 0x24111224,
+ 0x23133311,
+ 0x11431511,
+ }, /* 594 */
+ {
+ 0x14111315,
+ 0x21315212,
+ 0x12341123,
+ }, /* 595 */
+ {
+ 0x24111323,
+ 0x22224311,
+ 0x22341131,
+ }, /* 596 */
+ {
+ 0x34111331,
+ 0x21315311,
+ 0x11432123,
+ }, /* 597 */
+ {
+ 0x14111414,
+ 0x13134113,
+ 0x12341222,
+ }, /* 598 */
+ {
+ 0x24111422,
+ 0x23134121,
+ 0x11432222,
+ }, /* 599 */
+ {
+ 0x14111513,
+ 0x12225113,
+ 0x12341321,
+ }, /* 600 */
+ {
+ 0x24111521,
+ 0x13134212,
+ 0x11432321,
+ }, /* 601 */
+ {
+ 0x14112125,
+ 0x11316113,
+ 0x13251131,
+ }, /* 602 */
+ {
+ 0x24112133,
+ 0x12225212,
+ 0x12342131,
+ }, /* 603 */
+ {
+ 0x34112141,
+ 0x13134311,
+ 0x11433131,
+ }, /* 604 */
+ {
+ 0x14112224,
+ 0x11316212,
+ 0x11441114,
+ }, /* 605 */
+ {
+ 0x24112232,
+ 0x12225311,
+ 0x21441122,
+ }, /* 606 */
+ {
+ 0x14112323,
+ 0x11316311,
+ 0x11441213,
+ }, /* 607 */
+ {
+ 0x24112331,
+ 0x13135121,
+ 0x21441221,
+ }, /* 608 */
+ {
+ 0x14112422,
+ 0x12226121,
+ 0x11441312,
+ }, /* 609 */
+ {
+ 0x14112521,
+ 0x61321112,
+ 0x11441411,
+ }, /* 610 */
+ {
+ 0x14113133,
+ 0x11321153,
+ 0x12351122,
+ }, /* 611 */
+ {
+ 0x24113141,
+ 0x21321161,
+ 0x11442122,
+ }, /* 612 */
+ {
+ 0x14113232,
+ 0x61321211,
+ 0x12351221,
+ }, /* 613 */
+ {
+ 0x14113331,
+ 0x11321252,
+ 0x11442221,
+ }, /* 614 */
+ {
+ 0x14114141,
+ 0x11321351,
+ 0x11451113,
+ }, /* 615 */
+ {
+ 0x23211116,
+ 0x52231112,
+ 0x21451121,
+ }, /* 616 */
+ {
+ 0x33211124,
+ 0x12231161,
+ 0x11451212,
+ }, /* 617 */
+ {
+ 0x43211132,
+ 0x51322112,
+ 0x11451311,
+ }, /* 618 */
+ {
+ 0x23211215,
+ 0x52231211,
+ 0x12361121,
+ }, /* 619 */
+ {
+ 0x33211223,
+ 0x11322161,
+ 0x11452121,
+ }, /* 620 */
+ {
+ 0x23211314,
+ 0x51322211,
+ 0x15111143,
+ }, /* 621 */
+ {
+ 0x33211322,
+ 0x43141112,
+ 0x25111151,
+ }, /* 622 */
+ {
+ 0x23211413,
+ 0x42232112,
+ 0x15111242,
+ }, /* 623 */
+ {
+ 0x33211421,
+ 0x43141211,
+ 0x15111341,
+ }, /* 624 */
+ {
+ 0x23211512,
+ 0x41323112,
+ 0x15112151,
+ }, /* 625 */
+ {
+ 0x14121116,
+ 0x42232211,
+ 0x14211134,
+ }, /* 626 */
+ {
+ 0x24121124,
+ 0x41323211,
+ 0x24211142,
+ }, /* 627 */
+ {
+ 0x34121132,
+ 0x33142112,
+ 0x14211233,
+ }, /* 628 */
+ {
+ 0x13212116,
+ 0x32233112,
+ 0x24211241,
+ }, /* 629 */
+ {
+ 0x14121215,
+ 0x33142211,
+ 0x14211332,
+ }, /* 630 */
+ {
+ 0x33212132,
+ 0x31324112,
+ 0x14211431,
+ }, /* 631 */
+ {
+ 0x34121231,
+ 0x32233211,
+ 0x15121142,
+ }, /* 632 */
+ {
+ 0x13212215,
+ 0x31324211,
+ 0x14212142,
+ }, /* 633 */
+ {
+ 0x23212223,
+ 0x23143112,
+ 0x15121241,
+ }, /* 634 */
+ {
+ 0x33212231,
+ 0x22234112,
+ 0x14212241,
+ }, /* 635 */
+ {
+ 0x13212314,
+ 0x23143211,
+ 0x13311125,
+ }, /* 636 */
+ {
+ 0x14121413,
+ 0x21325112,
+ 0x23311133,
+ }, /* 637 */
+ {
+ 0x24121421,
+ 0x22234211,
+ 0x33311141,
+ }, /* 638 */
+ {
+ 0x13212413,
+ 0x21325211,
+ 0x13311224,
+ }, /* 639 */
+ {
+ 0x23212421,
+ 0x13144112,
+ 0x23311232,
+ }, /* 640 */
+ {
+ 0x14121611,
+ 0x12235112,
+ 0x13311323,
+ }, /* 641 */
+ {
+ 0x14122124,
+ 0x13144211,
+ 0x23311331,
+ }, /* 642 */
+ {
+ 0x24122132,
+ 0x11326112,
+ 0x13311422,
+ }, /* 643 */
+ {
+ 0x13213124,
+ 0x12235211,
+ 0x13311521,
+ }, /* 644 */
+ {
+ 0x14122223,
+ 0x11326211,
+ 0x14221133,
+ }, /* 645 */
+ {
+ 0x24122231,
+ 0x61331111,
+ 0x24221141,
+ }, /* 646 */
+ {
+ 0x13213223,
+ 0x11331152,
+ 0x13312133,
+ }, /* 647 */
+ {
+ 0x23213231,
+ 0x11331251,
+ 0x14221232,
+ }, /* 648 */
+ {
+ 0x13213322,
+ 0x52241111,
+ 0x13312232,
+ }, /* 649 */
+ {
+ 0x14122421,
+ 0x51332111,
+ 0x14221331,
+ }, /* 650 */
+ {
+ 0x14123132,
+ 0x43151111,
+ 0x13312331,
+ }, /* 651 */
+ {
+ 0x13214132,
+ 0x42242111,
+ 0x15131141,
+ }, /* 652 */
+ {
+ 0x14123231,
+ 0x41333111,
+ 0x14222141,
+ }, /* 653 */
+ {
+ 0x13214231,
+ 0x33152111,
+ 0x13313141,
+ }, /* 654 */
+ {
+ 0x32311115,
+ 0x32243111,
+ 0x12411116,
+ }, /* 655 */
+ {
+ 0x42311123,
+ 0x31334111,
+ 0x22411124,
+ }, /* 656 */
+ {
+ 0x52311131,
+ 0x23153111,
+ 0x32411132,
+ }, /* 657 */
+ {
+ 0x32311214,
+ 0x22244111,
+ 0x12411215,
+ }, /* 658 */
+ {
+ 0x42311222,
+ 0x21335111,
+ 0x22411223,
+ }, /* 659 */
+ {
+ 0x32311313,
+ 0x13154111,
+ 0x32411231,
+ }, /* 660 */
+ {
+ 0x42311321,
+ 0x12245111,
+ 0x12411314,
+ }, /* 661 */
+ {
+ 0x32311412,
+ 0x11336111,
+ 0x22411322,
+ }, /* 662 */
+ {
+ 0x32311511,
+ 0x11341151,
+ 0x12411413,
+ }, /* 663 */
+ {
+ 0x23221115,
+ 0x44111114,
+ 0x22411421,
+ }, /* 664 */
+ {
+ 0x33221123,
+ 0x54111122,
+ 0x12411512,
+ }, /* 665 */
+ {
+ 0x22312115,
+ 0x44111213,
+ 0x12411611,
+ }, /* 666 */
+ {
+ 0x23221214,
+ 0x54111221,
+ 0x13321124,
+ }, /* 667 */
+ {
+ 0x33221222,
+ 0x44111312,
+ 0x23321132,
+ }, /* 668 */
+ {
+ 0x22312214,
+ 0x44111411,
+ 0x12412124,
+ }, /* 669 */
+ {
+ 0x32312222,
+ 0x34112114,
+ 0x13321223,
+ }, /* 670 */
+ {
+ 0x33221321,
+ 0x44112122,
+ 0x23321231,
+ }, /* 671 */
+ {
+ 0x22312313,
+ 0x34112213,
+ 0x12412223,
+ }, /* 672 */
+ {
+ 0x23221412,
+ 0x44112221,
+ 0x22412231,
+ }, /* 673 */
+ {
+ 0x22312412,
+ 0x34112312,
+ 0x12412322,
+ }, /* 674 */
+ {
+ 0x23221511,
+ 0x34112411,
+ 0x13321421,
+ }, /* 675 */
+ {
+ 0x22312511,
+ 0x24113114,
+ 0x12412421,
+ }, /* 676 */
+ {
+ 0x14131115,
+ 0x34113122,
+ 0x14231132,
+ }, /* 677 */
+ {
+ 0x24131123,
+ 0x24113213,
+ 0x13322132,
+ }, /* 678 */
+ {
+ 0x13222115,
+ 0x34113221,
+ 0x14231231,
+ }, /* 679 */
+ {
+ 0x14131214,
+ 0x24113312,
+ 0x12413132,
+ }, /* 680 */
+ {
+ 0x33222131,
+ 0x24113411,
+ 0x13322231,
+ }, /* 681 */
+ {
+ 0x12313115,
+ 0x14114114,
+ 0x12413231,
+ }, /* 682 */
+ {
+ 0x13222214,
+ 0x24114122,
+ 0x21511115,
+ }, /* 683 */
+ {
+ 0x23222222,
+ 0x14114213,
+ 0x31511123,
+ }, /* 684 */
+ {
+ 0x24131321,
+ 0x24114221,
+ 0x41511131,
+ }, /* 685 */
+ {
+ 0x12313214,
+ 0x14114312,
+ 0x21511214,
+ }, /* 686 */
+ {
+ 0x22313222,
+ 0x14114411,
+ 0x31511222,
+ }, /* 687 */
+ {
+ 0x14131412,
+ 0x14115122,
+ 0x21511313,
+ }, /* 688 */
+ {
+ 0x12313313,
+ 0x14115221,
+ 0x31511321,
+ }, /* 689 */
+ {
+ 0x13222412,
+ 0x53211113,
+ 0x21511412,
+ }, /* 690 */
+ {
+ 0x14131511,
+ 0x63211121,
+ 0x21511511,
+ }, /* 691 */
+ {
+ 0x13222511,
+ 0x13211162,
+ 0x12421115,
+ }, /* 692 */
+ {
+ 0x14132123,
+ 0x53211212,
+ 0x22421123,
+ }, /* 693 */
+ {
+ 0x24132131,
+ 0x13211261,
+ 0x32421131,
+ }, /* 694 */
+ {
+ 0x13223123,
+ 0x53211311,
+ 0x11512115,
+ }, /* 695 */
+ {
+ 0x14132222,
+ 0x44121113,
+ 0x12421214,
+ }, /* 696 */
+ {
+ 0x12314123,
+ 0x54121121,
+ 0x22421222,
+ }, /* 697 */
+ {
+ 0x13223222,
+ 0x43212113,
+ 0x11512214,
+ }, /* 698 */
+ {
+ 0x14132321,
+ 0x44121212,
+ 0x21512222,
+ }, /* 699 */
+ {
+ 0x12314222,
+ 0x43212212,
+ 0x22421321,
+ }, /* 700 */
+ {
+ 0x13223321,
+ 0x44121311,
+ 0x11512313,
+ }, /* 701 */
+ {
+ 0x14133131,
+ 0x43212311,
+ 0x12421412,
+ }, /* 702 */
+ {
+ 0x13224131,
+ 0x34122113,
+ 0x11512412,
+ }, /* 703 */
+ {
+ 0x12315131,
+ 0x44122121,
+ 0x12421511,
+ }, /* 704 */
+ {
+ 0x41411114,
+ 0x33213113,
+ 0x11512511,
+ }, /* 705 */
+ {
+ 0x51411122,
+ 0x34122212,
+ 0x13331123,
+ }, /* 706 */
+ {
+ 0x41411213,
+ 0x33213212,
+ 0x23331131,
+ }, /* 707 */
+ {
+ 0x51411221,
+ 0x34122311,
+ 0x12422123,
+ }, /* 708 */
+ {
+ 0x41411312,
+ 0x33213311,
+ 0x13331222,
+ }, /* 709 */
+ {
+ 0x41411411,
+ 0x24123113,
+ 0x11513123,
+ }, /* 710 */
+ {
+ 0x32321114,
+ 0x34123121,
+ 0x12422222,
+ }, /* 711 */
+ {
+ 0x42321122,
+ 0x23214113,
+ 0x13331321,
+ }, /* 712 */
+ {
+ 0x31412114,
+ 0x24123212,
+ 0x11513222,
+ }, /* 713 */
+ {
+ 0x41412122,
+ 0x23214212,
+ 0x12422321,
+ }, /* 714 */
+ {
+ 0x42321221,
+ 0x24123311,
+ 0x11513321,
+ }, /* 715 */
+ {
+ 0x31412213,
+ 0x23214311,
+ 0x14241131,
+ }, /* 716 */
+ {
+ 0x41412221,
+ 0x14124113,
+ 0x13332131,
+ }, /* 717 */
+ {
+ 0x31412312,
+ 0x24124121,
+ 0x12423131,
+ }, /* 718 */
+ {
+ 0x32321411,
+ 0x13215113,
+ 0x11514131,
+ }, /* 719 */
+ {
+ 0x31412411,
+ 0x14124212,
+ 0x21521114,
+ }, /* 720 */
+ {
+ 0x23231114,
+ 0x13215212,
+ 0x31521122,
+ }, /* 721 */
+ {
+ 0x33231122,
+ 0x14124311,
+ 0x21521213,
+ }, /* 722 */
+ {
+ 0x22322114,
+ 0x13215311,
+ 0x31521221,
+ }, /* 723 */
+ {
+ 0x23231213,
+ 0x14125121,
+ 0x21521312,
+ }, /* 724 */
+ {
+ 0x33231221,
+ 0x13216121,
+ 0x21521411,
+ }, /* 725 */
+ {
+ 0x21413114,
+ 0x62311112,
+ 0x12431114,
+ }, /* 726 */
+ {
+ 0x22322213,
+ 0x12311153,
+ 0x22431122,
+ }, /* 727 */
+ {
+ 0x32322221,
+ 0x22311161,
+ 0x11522114,
+ }, /* 728 */
+ {
+ 0x21413213,
+ 0x62311211,
+ 0x12431213,
+ }, /* 729 */
+ {
+ 0x31413221,
+ 0x12311252,
+ 0x22431221,
+ }, /* 730 */
+ {
+ 0x23231411,
+ 0x12311351,
+ 0x11522213,
+ }, /* 731 */
+ {
+ 0x21413312,
+ 0x53221112,
+ 0x21522221,
+ }, /* 732 */
+ {
+ 0x22322411,
+ 0x13221161,
+ 0x11522312,
+ }, /* 733 */
+ {
+ 0x21413411,
+ 0x52312112,
+ 0x12431411,
+ }, /* 734 */
+ {
+ 0x14141114,
+ 0x53221211,
+ 0x11522411,
+ }, /* 735 */
+ {
+ 0x24141122,
+ 0x12312161,
+ 0x13341122,
+ }, /* 736 */
+ {
+ 0x13232114,
+ 0x52312211,
+ 0x12432122,
+ }, /* 737 */
+ {
+ 0x14141213,
+ 0x44131112,
+ 0x13341221,
+ }, /* 738 */
+ {
+ 0x24141221,
+ 0x43222112,
+ 0x11523122,
+ }, /* 739 */
+ {
+ 0x12323114,
+ 0x44131211,
+ 0x12432221,
+ }, /* 740 */
+ {
+ 0x13232213,
+ 0x42313112,
+ 0x11523221,
+ }, /* 741 */
+ {
+ 0x23232221,
+ 0x43222211,
+ 0x21531113,
+ }, /* 742 */
+ {
+ 0x11414114,
+ 0x42313211,
+ 0x31531121,
+ }, /* 743 */
+ {
+ 0x12323213,
+ 0x34132112,
+ 0x21531212,
+ }, /* 744 */
+ {
+ 0x22323221,
+ 0x33223112,
+ 0x21531311,
+ }, /* 745 */
+ {
+ 0x14141411,
+ 0x34132211,
+ 0x12441113,
+ }, /* 746 */
+ {
+ 0x11414213,
+ 0x32314112,
+ 0x22441121,
+ }, /* 747 */
+ {
+ 0x21414221,
+ 0x33223211,
+ 0x11532113,
+ }, /* 748 */
+ {
+ 0x13232411,
+ 0x32314211,
+ 0x12441212,
+ }, /* 749 */
+ {
+ 0x11414312,
+ 0x24133112,
+ 0x11532212,
+ }, /* 750 */
+ {
+ 0x14142122,
+ 0x23224112,
+ 0x12441311,
+ }, /* 751 */
+ {
+ 0x13233122,
+ 0x24133211,
+ 0x11532311,
+ }, /* 752 */
+ {
+ 0x14142221,
+ 0x22315112,
+ 0x13351121,
+ }, /* 753 */
+ {
+ 0x12324122,
+ 0x23224211,
+ 0x12442121,
+ }, /* 754 */
+ {
+ 0x13233221,
+ 0x22315211,
+ 0x11533121,
+ }, /* 755 */
+ {
+ 0x11415122,
+ 0x14134112,
+ 0x21541112,
+ }, /* 756 */
+ {
+ 0x12324221,
+ 0x13225112,
+ 0x21541211,
+ }, /* 757 */
+ {
+ 0x11415221,
+ 0x14134211,
+ 0x12451112,
+ }, /* 758 */
+ {
+ 0x41421113,
+ 0x12316112,
+ 0x11542112,
+ }, /* 759 */
+ {
+ 0x51421121,
+ 0x13225211,
+ 0x12451211,
+ }, /* 760 */
+ {
+ 0x41421212,
+ 0x12316211,
+ 0x11542211,
+ }, /* 761 */
+ {
+ 0x41421311,
+ 0x11411144,
+ 0x16111142,
+ }, /* 762 */
+ {
+ 0x32331113,
+ 0x21411152,
+ 0x16111241,
+ }, /* 763 */
+ {
+ 0x42331121,
+ 0x11411243,
+ 0x15211133,
+ }, /* 764 */
+ {
+ 0x31422113,
+ 0x21411251,
+ 0x25211141,
+ }, /* 765 */
+ {
+ 0x41422121,
+ 0x11411342,
+ 0x15211232,
+ }, /* 766 */
+ {
+ 0x31422212,
+ 0x11411441,
+ 0x15211331,
+ }, /* 767 */
+ {
+ 0x32331311,
+ 0x62321111,
+ 0x16121141,
+ }, /* 768 */
+ {
+ 0x31422311,
+ 0x12321152,
+ 0x15212141,
+ }, /* 769 */
+ {
+ 0x23241113,
+ 0x61412111,
+ 0x14311124,
+ }, /* 770 */
+ {
+ 0x33241121,
+ 0x11412152,
+ 0x24311132,
+ }, /* 771 */
+ {
+ 0x22332113,
+ 0x12321251,
+ 0x14311223,
+ }, /* 772 */
+ {
+ 0x23241212,
+ 0x11412251,
+ 0x24311231,
+ }, /* 773 */
+ {
+ 0x21423113,
+ 0x53231111,
+ 0x14311322,
+ }, /* 774 */
+ {
+ 0x22332212,
+ 0x52322111,
+ 0x14311421,
+ }, /* 775 */
+ {
+ 0x23241311,
+ 0x51413111,
+ 0x15221132,
+ }, /* 776 */
+ {
+ 0x21423212,
+ 0x44141111,
+ 0x14312132,
+ }, /* 777 */
+ {
+ 0x22332311,
+ 0x43232111,
+ 0x15221231,
+ }, /* 778 */
+ {
+ 0x21423311,
+ 0x42323111,
+ 0x14312231,
+ }, /* 779 */
+ {
+ 0x14151113,
+ 0x41414111,
+ 0x13411115,
+ }, /* 780 */
+ {
+ 0x24151121,
+ 0x34142111,
+ 0x23411123,
+ }, /* 781 */
+ {
+ 0x13242113,
+ 0x33233111,
+ 0x33411131,
+ }, /* 782 */
+ {
+ 0x23242121,
+ 0x32324111,
+ 0x13411214,
+ }, /* 783 */
+ {
+ 0x12333113,
+ 0x31415111,
+ 0x23411222,
+ }, /* 784 */
+ {
+ 0x13242212,
+ 0x24143111,
+ 0x13411313,
+ }, /* 785 */
+ {
+ 0x14151311,
+ 0x23234111,
+ 0x23411321,
+ }, /* 786 */
+ {
+ 0x11424113,
+ 0x22325111,
+ 0x13411412,
+ }, /* 787 */
+ {
+ 0x12333212,
+ 0x21416111,
+ 0x13411511,
+ }, /* 788 */
+ {
+ 0x13242311,
+ 0x14144111,
+ 0x14321123,
+ }, /* 789 */
+ {
+ 0x11424212,
+ 0x13235111,
+ 0x24321131,
+ }, /* 790 */
+ {
+ 0x12333311,
+ 0x12326111,
+ 0x13412123,
+ }, /* 791 */
+ {
+ 0x11424311,
+ 0x11421143,
+ 0x23412131,
+ }, /* 792 */
+ {
+ 0x13243121,
+ 0x21421151,
+ 0x13412222,
+ }, /* 793 */
+ {
+ 0x11425121,
+ 0x11421242,
+ 0x14321321,
+ }, /* 794 */
+ {
+ 0x41431211,
+ 0x11421341,
+ 0x13412321,
+ }, /* 795 */
+ {
+ 0x31432112,
+ 0x12331151,
+ 0x15231131,
+ }, /* 796 */
+ {
+ 0x31432211,
+ 0x11422151,
+ 0x14322131,
+ }, /* 797 */
+ {
+ 0x22342112,
+ 0x11431142,
+ 0x13413131,
+ }, /* 798 */
+ {
+ 0x21433112,
+ 0x11431241,
+ 0x22511114,
+ }, /* 799 */
+ {
+ 0x21433211,
+ 0x11441141,
+ 0x32511122,
+ }, /* 800 */
+ {
+ 0x13252112,
+ 0x45111113,
+ 0x22511213,
+ }, /* 801 */
+ {
+ 0x12343112,
+ 0x45111212,
+ 0x32511221,
+ }, /* 802 */
+ {
+ 0x11434112,
+ 0x45111311,
+ 0x22511312,
+ }, /* 803 */
+ {
+ 0x11434211,
+ 0x35112113,
+ 0x22511411,
+ }, /* 804 */
+ {
+ 0x15111116,
+ 0x45112121,
+ 0x13421114,
+ }, /* 805 */
+ {
+ 0x15111215,
+ 0x35112212,
+ 0x23421122,
+ }, /* 806 */
+ {
+ 0x25111223,
+ 0x35112311,
+ 0x12512114,
+ }, /* 807 */
+ {
+ 0x15111314,
+ 0x25113113,
+ 0x22512122,
+ }, /* 808 */
+ {
+ 0x15111413,
+ 0x35113121,
+ 0x23421221,
+ }, /* 809 */
+ {
+ 0x15111512,
+ 0x25113212,
+ 0x12512213,
+ }, /* 810 */
+ {
+ 0x15112124,
+ 0x25113311,
+ 0x13421312,
+ }, /* 811 */
+ {
+ 0x15112223,
+ 0x15114113,
+ 0x12512312,
+ }, /* 812 */
+ {
+ 0x15112322,
+ 0x25114121,
+ 0x13421411,
+ }, /* 813 */
+ {
+ 0x15112421,
+ 0x15114212,
+ 0x12512411,
+ }, /* 814 */
+ {
+ 0x15113132,
+ 0x15114311,
+ 0x14331122,
+ }, /* 815 */
+ {
+ 0x15113231,
+ 0x15115121,
+ 0x13422122,
+ }, /* 816 */
+ {
+ 0x24211115,
+ 0x54211112,
+ 0x14331221,
+ }, /* 817 */
+ {
+ 0x24211214,
+ 0x14211161,
+ 0x12513122,
+ }, /* 818 */
+ {
+ 0x34211222,
+ 0x54211211,
+ 0x13422221,
+ }, /* 819 */
+ {
+ 0x24211313,
+ 0x45121112,
+ 0x12513221,
+ }, /* 820 */
+ {
+ 0x34211321,
+ 0x44212112,
+ 0x31611113,
+ }, /* 821 */
+ {
+ 0x24211412,
+ 0x45121211,
+ 0x41611121,
+ }, /* 822 */
+ {
+ 0x24211511,
+ 0x44212211,
+ 0x31611212,
+ }, /* 823 */
+ {
+ 0x15121115,
+ 0x35122112,
+ 0x31611311,
+ }, /* 824 */
+ {
+ 0x25121123,
+ 0x34213112,
+ 0x22521113,
+ }, /* 825 */
+ {
+ 0x14212115,
+ 0x35122211,
+ 0x32521121,
+ }, /* 826 */
+ {
+ 0x24212123,
+ 0x34213211,
+ 0x21612113,
+ }, /* 827 */
+ {
+ 0x25121222,
+ 0x25123112,
+ 0x22521212,
+ }, /* 828 */
+ {
+ 0x14212214,
+ 0x24214112,
+ 0x21612212,
+ }, /* 829 */
+ {
+ 0x24212222,
+ 0x25123211,
+ 0x22521311,
+ }, /* 830 */
+ {
+ 0x14212313,
+ 0x24214211,
+ 0x21612311,
+ }, /* 831 */
+ {
+ 0x24212321,
+ 0x15124112,
+ 0x13431113,
+ }, /* 832 */
+ {
+ 0x14212412,
+ 0x14215112,
+ 0x23431121,
+ }, /* 833 */
+ {
+ 0x15121511,
+ 0x15124211,
+ 0x12522113,
+ }, /* 834 */
+ {
+ 0x14212511,
+ 0x14215211,
+ 0x13431212,
+ }, /* 835 */
+ {
+ 0x15122123,
+ 0x63311111,
+ 0x11613113,
+ }, /* 836 */
+ {
+ 0x25122131,
+ 0x13311152,
+ 0x12522212,
+ }, /* 837 */
+ {
+ 0x14213123,
+ 0x13311251,
+ 0x13431311,
+ }, /* 838 */
+ {
+ 0x24213131,
+ 0x54221111,
+ 0x11613212,
+ }, /* 839 */
+ {
+ 0x14213222,
+ 0x53312111,
+ 0x12522311,
+ }, /* 840 */
+ {
+ 0x15122321,
+ 0x45131111,
+ 0x11613311,
+ }, /* 841 */
+ {
+ 0x14213321,
+ 0x44222111,
+ 0x14341121,
+ }, /* 842 */
+ {
+ 0x15123131,
+ 0x43313111,
+ 0x13432121,
+ }, /* 843 */
+ {
+ 0x14214131,
+ 0x35132111,
+ 0x12523121,
+ }, /* 844 */
+ {
+ 0x33311114,
+ 0x34223111,
+ 0x11614121,
+ }, /* 845 */
+ {
+ 0x33311213,
+ 0x33314111,
+ 0x31621112,
+ }, /* 846 */
+ {
+ 0x33311312,
+ 0x25133111,
+ 0x31621211,
+ }, /* 847 */
+ {
+ 0x33311411,
+ 0x24224111,
+ 0x22531112,
+ }, /* 848 */
+ {
+ 0x24221114,
+ 0x23315111,
+ 0x21622112,
+ }, /* 849 */
+ {
+ 0x23312114,
+ 0x15134111,
+ 0x22531211,
+ }, /* 850 */
+ {
+ 0x33312122,
+ 0x14225111,
+ 0x21622211,
+ }, /* 851 */
+ {
+ 0x34221221,
+ 0x13316111,
+ 0x13441112,
+ }, /* 852 */
+ {
+ 0x23312213,
+ 0x12411143,
+ 0x12532112,
+ }, /* 853 */
+ {
+ 0x33312221,
+ 0x22411151,
+ 0x13441211,
+ }, /* 854 */
+ {
+ 0x23312312,
+ 0x12411242,
+ 0x11623112,
+ }, /* 855 */
+ {
+ 0x24221411,
+ 0x12411341,
+ 0x12532211,
+ }, /* 856 */
+ {
+ 0x23312411,
+ 0x13321151,
+ 0x11623211,
+ }, /* 857 */
+ {
+ 0x15131114,
+ 0x12412151,
+ 0x31631111,
+ }, /* 858 */
+ {
+ 0x14222114,
+ 0x11511134,
+ 0x22541111,
+ }, /* 859 */
+ {
+ 0x15131213,
+ 0x21511142,
+ 0x21632111,
+ }, /* 860 */
+ {
+ 0x25131221,
+ 0x11511233,
+ 0x13451111,
+ }, /* 861 */
+ {
+ 0x13313114,
+ 0x21511241,
+ 0x12542111,
+ }, /* 862 */
+ {
+ 0x14222213,
+ 0x11511332,
+ 0x11633111,
+ }, /* 863 */
+ {
+ 0x15131312,
+ 0x11511431,
+ 0x16211132,
+ }, /* 864 */
+ {
+ 0x13313213,
+ 0x12421142,
+ 0x16211231,
+ }, /* 865 */
+ {
+ 0x14222312,
+ 0x11512142,
+ 0x15311123,
+ }, /* 866 */
+ {
+ 0x15131411,
+ 0x12421241,
+ 0x25311131,
+ }, /* 867 */
+ {
+ 0x13313312,
+ 0x11512241,
+ 0x15311222,
+ }, /* 868 */
+ {
+ 0x14222411,
+ 0x11521133,
+ 0x15311321,
+ }, /* 869 */
+ {
+ 0x15132122,
+ 0x21521141,
+ 0x16221131,
+ }, /* 870 */
+ {
+ 0x14223122,
+ 0x11521232,
+ 0x15312131,
+ }, /* 871 */
+ {
+ 0x15132221,
+ 0x11521331,
+ 0x14411114,
+ }, /* 872 */
+ {
+ 0x13314122,
+ 0x12431141,
+ 0x24411122,
+ }, /* 873 */
+ {
+ 0x14223221,
+ 0x11522141,
+ 0x14411213,
+ }, /* 874 */
+ {
+ 0x13314221,
+ 0x11531132,
+ 0x24411221,
+ }, /* 875 */
+ {
+ 0x42411113,
+ 0x11531231,
+ 0x14411312,
+ }, /* 876 */
+ {
+ 0x42411212,
+ 0x11541131,
+ 0x14411411,
+ }, /* 877 */
+ {
+ 0x42411311,
+ 0x36112112,
+ 0x15321122,
+ }, /* 878 */
+ {
+ 0x33321113,
+ 0x36112211,
+ 0x14412122,
+ }, /* 879 */
+ {
+ 0x32412113,
+ 0x26113112,
+ 0x15321221,
+ }, /* 880 */
+ {
+ 0x42412121,
+ 0x26113211,
+ 0x14412221,
+ }, /* 881 */
+ {
+ 0x32412212,
+ 0x16114112,
+ 0x23511113,
+ }, /* 882 */
+ {
+ 0x33321311,
+ 0x16114211,
+ 0x33511121,
+ }, /* 883 */
+ {
+ 0x32412311,
+ 0x45212111,
+ 0x23511212,
+ }, /* 884 */
+ {
+ 0x24231113,
+ 0x36122111,
+ 0x23511311,
+ }, /* 885 */
+ {
+ 0x34231121,
+ 0x35213111,
+ 0x14421113,
+ }, /* 886 */
+ {
+ 0x23322113,
+ 0x26123111,
+ 0x24421121,
+ }, /* 887 */
+ {
+ 0x33322121,
+ 0x25214111,
+ 0x13512113,
+ }, /* 888 */
+ {
+ 0x22413113,
+ 0x16124111,
+ 0x23512121,
+ }, /* 889 */
+ {
+ 0x23322212,
+ 0x15215111,
+ 0x13512212,
+ }, /* 890 */
+ {
+ 0x24231311,
+ 0x14311151,
+ 0x14421311,
+ }, /* 891 */
+ {
+ 0x22413212,
+ 0x13411142,
+ 0x13512311,
+ }, /* 892 */
+ {
+ 0x23322311,
+ 0x13411241,
+ 0x15331121,
+ }, /* 893 */
+ {
+ 0x22413311,
+ 0x12511133,
+ 0x14422121,
+ }, /* 894 */
+ {
+ 0x15141113,
+ 0x22511141,
+ 0x13513121,
+ }, /* 895 */
+ {
+ 0x25141121,
+ 0x12511232,
+ 0x32611112,
+ }, /* 896 */
+ {
+ 0x14232113,
+ 0x12511331,
+ 0x32611211,
+ }, /* 897 */
+ {
+ 0x24232121,
+ 0x13421141,
+ 0x23521112,
+ }, /* 898 */
+ {
+ 0x13323113,
+ 0x12512141,
+ 0x22612112,
+ }, /* 899 */
+ {
+ 0x14232212,
+ 0x11611124,
+ 0x23521211,
+ }, /* 900 */
+ {
+ 0x15141311,
+ 0x21611132,
+ 0x22612211,
+ }, /* 901 */
+ {
+ 0x12414113,
+ 0x11611223,
+ 0x14431112,
+ }, /* 902 */
+ {
+ 0x13323212,
+ 0x21611231,
+ 0x13522112,
+ }, /* 903 */
+ {
+ 0x14232311,
+ 0x11611322,
+ 0x14431211,
+ }, /* 904 */
+ {
+ 0x12414212,
+ 0x11611421,
+ 0x12613112,
+ }, /* 905 */
+ {
+ 0x13323311,
+ 0x12521132,
+ 0x13522211,
+ }, /* 906 */
+ {
+ 0x15142121,
+ 0x11612132,
+ 0x12613211,
+ }, /* 907 */
+ {
+ 0x14233121,
+ 0x12521231,
+ 0x32621111,
+ }, /* 908 */
+ {
+ 0x13324121,
+ 0x11612231,
+ 0x23531111,
+ }, /* 909 */
+ {
+ 0x12415121,
+ 0x11621123,
+ 0x22622111,
+ }, /* 910 */
+ {
+ 0x51511112,
+ 0x21621131,
+ 0x14441111,
+ }, /* 911 */
+ {
+ 0x51511211,
+ 0x11621222,
+ 0x13532111,
+ }, /* 912 */
+ {
+ 0x42421112,
+ 0x11621321,
+ 0x12623111,
+ }, /* 913 */
+ {
+ 0x41512112,
+ 0x12531131,
+ 0x16311122,
+ }, /* 914 */
+ {
+ 0x42421211,
+ 0x11622131,
+ 0x16311221,
+ }, /* 915 */
+ {
+ 0x41512211,
+ 0x11631122,
+ 0x15411113,
+ }, /* 916 */
+ {
+ 0x33331112,
+ 0x11631221,
+ 0x25411121,
+ }, /* 917 */
+ {
+ 0x32422112,
+ 0x14411141,
+ 0x15411212,
+ }, /* 918 */
+ {
+ 0x33331211,
+ 0x13511132,
+ 0x15411311,
+ }, /* 919 */
+ {
+ 0x31513112,
+ 0x13511231,
+ 0x16321121,
+ }, /* 920 */
+ {
+ 0x32422211,
+ 0x12611123,
+ 0x15412121,
+ }, /* 921 */
+ {
+ 0x31513211,
+ 0x22611131,
+ 0x24511112,
+ }, /* 922 */
+ {
+ 0x24241112,
+ 0x12611222,
+ 0x24511211,
+ }, /* 923 */
+ {
+ 0x23332112,
+ 0x12611321,
+ 0x15421112,
+ }, /* 924 */
+ {
+ 0x24241211,
+ 0x13521131,
+ 0x14512112,
+ }, /* 925 */
+ {
+ 0x22423112,
+ 0x12612131,
+ 0x15421211,
+ }, /* 926 */
+ {
+ 0x23332211,
+ 0x12621122,
+ 0x14512211,
+ }, /* 927 */
+ {
+ 0x21514112,
+ 0x12621221,
+ 0x33611111,
+ }, /* 928 */
+};
+
+#endif
diff --git a/test/test_convert.c b/test/test_convert.c
new file mode 100644
index 0000000..426ac81
--- /dev/null
+++ b/test/test_convert.c
@@ -0,0 +1,60 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <zbar.h>
+#include "test_images.h"
+
+#if 0
+static uint32_t formats[] = {
+
+};
+#endif
+
+int main(int argc, char *argv[])
+{
+ zbar_set_verbosity(10);
+
+ uint32_t srcfmt = fourcc('I', '4', '2', '0');
+ if (argc > 1)
+ srcfmt = *(uint32_t *)argv[1];
+
+ zbar_image_t *img = zbar_image_create();
+ zbar_image_set_size(img, 640, 480);
+ zbar_image_set_format(img, srcfmt);
+ if (test_image_bars(img))
+ return (2);
+
+ if (zbar_image_write(img, "/tmp/base"))
+ return (1);
+ return (0);
+}
diff --git a/test/test_cpp.cpp b/test/test_cpp.cpp
new file mode 100644
index 0000000..1c60ece
--- /dev/null
+++ b/test/test_cpp.cpp
@@ -0,0 +1,43 @@
+//------------------------------------------------------------------------
+// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+//
+// This file is part of the ZBar Bar Code Reader.
+//
+// The ZBar Bar Code Reader is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser Public License as
+// published by the Free Software Foundation; either version 2.1 of
+// the License, or (at your option) any later version.
+//
+// The ZBar Bar Code Reader is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser Public License for more details.
+//
+// You should have received a copy of the GNU Lesser Public License
+// along with the ZBar Bar Code Reader; if not, write to the Free
+// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301 USA
+//
+// http://sourceforge.net/projects/zbar
+//------------------------------------------------------------------------
+
+// NB do not put anything before this header
+// it's here to check that we didn't omit any dependencies
+#include <zbar.h>
+
+int main(int argc, char **argv)
+{
+ const char *video_dev = "/dev/video0";
+ if (argc > 1)
+ video_dev = argv[1];
+
+ zbar::Processor proc = zbar::Processor(true, video_dev);
+ proc.set_visible();
+ proc.set_active();
+ try {
+ proc.user_wait();
+ } catch (zbar::ClosedError &) {
+ }
+
+ return (0);
+}
diff --git a/test/test_cpp_img.cpp b/test/test_cpp_img.cpp
new file mode 100644
index 0000000..3b57fcb
--- /dev/null
+++ b/test/test_cpp_img.cpp
@@ -0,0 +1,214 @@
+//------------------------------------------------------------------------
+// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+//
+// This file is part of the ZBar Bar Code Reader.
+//
+// The ZBar Bar Code Reader is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser Public License as
+// published by the Free Software Foundation; either version 2.1 of
+// the License, or (at your option) any later version.
+//
+// The ZBar Bar Code Reader is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser Public License for more details.
+//
+// You should have received a copy of the GNU Lesser Public License
+// along with the ZBar Bar Code Reader; if not, write to the Free
+// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301 USA
+//
+// http://sourceforge.net/projects/zbar
+//------------------------------------------------------------------------
+
+// NB do not put anything before this header
+// it's here to check that we didn't omit any dependencies
+#include <zbar.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include "test_images.h"
+
+bool debug = false;
+bool verbose = false;
+int errors = 0;
+zbar::zbar_symbol_type_t expect_type = zbar::ZBAR_NONE;
+std::string expect_data;
+
+template <class T> inline std::string to_string(const T &t)
+{
+ std::stringstream ss;
+ ss << t;
+ return ss.str();
+}
+
+static inline int error(const std::string &msg)
+{
+ errors++;
+ std::cerr << "ERROR: " << msg << std::endl;
+ if (debug)
+ abort();
+ return (-1);
+}
+
+static inline int check_loc(const zbar::Image &img, const zbar::Symbol &sym)
+{
+ int n = 0;
+ int w = img.get_width();
+ int h = img.get_height();
+ for (zbar::Symbol::PointIterator p(sym.point_begin()); p != sym.point_end();
+ ++p, n++) {
+ zbar::Symbol::Point q(*p);
+ if (q.x < 0 || q.x >= w || q.y < 0 || q.y >= h)
+ error("location point out of range");
+ }
+ return (!n);
+}
+
+static inline int check_symbol(const zbar::Image &img, const zbar::Symbol &sym)
+{
+ zbar::zbar_symbol_type_t type(sym.get_type());
+ std::string data(sym.get_data());
+
+ bool pass = expect_type && type == expect_type && data == expect_data &&
+ sym.get_data_length() == expect_data.length() &&
+ sym.get_quality() > 4;
+ if (pass)
+ pass = !check_loc(img, sym);
+
+ if (verbose || !pass)
+ std::cerr << "decode Symbol: " << sym << std::endl;
+
+ if (!expect_type)
+ error("unexpected");
+ else if (!pass)
+ error(std::string("expected: ") +
+ zbar::zbar_get_symbol_name(expect_type) + " " + expect_data);
+
+ expect_type = zbar::ZBAR_NONE;
+ expect_data = "";
+ return (!pass);
+}
+
+static inline int check_image(const zbar::Image &img)
+{
+ zbar::SymbolSet syms(img.get_symbols());
+ int setn = syms.get_size(), countn = 0;
+
+ int rc = 0;
+ for (zbar::SymbolIterator sym(syms.symbol_begin());
+ sym != syms.symbol_end(); ++sym, ++countn)
+ rc |= check_symbol(img, *sym);
+
+ if (countn != setn)
+ rc |= error("SymbolSet size mismatch: exp=" + to_string(setn) +
+ " act=" + to_string(countn));
+ return (rc);
+}
+
+static inline void expect(zbar::zbar_symbol_type_t type, std::string data)
+{
+ if (expect_type)
+ error(std::string("missing: ") + zbar_get_symbol_name(expect_type) +
+ " " + expect_data);
+ expect_type = type;
+ expect_data = data;
+}
+
+class Handler : public zbar::Image::Handler
+{
+ void image_callback(zbar::Image &img);
+};
+
+void Handler::image_callback(zbar::Image &img)
+{
+ bool unexpected = !expect_type;
+ if (unexpected)
+ error("unexpected image callback");
+ check_image(img);
+}
+
+static inline int test_processor()
+{
+ // create processor w/no video and no window
+ zbar::Processor proc(debug, NULL);
+ Handler handler;
+ proc.set_handler(handler);
+ if (debug) {
+ proc.set_visible();
+ proc.user_wait();
+ }
+
+ // generate barcode test image
+ zbar::Image rgb3(0, 0, "RGB3");
+
+ // test cast to C image
+ if (test_image_ean13(rgb3))
+ error("failed to generate image");
+
+ // test decode
+ expect(zbar::ZBAR_EAN13, test_image_ean13_data);
+ proc.process_image(rgb3);
+ if (debug)
+ proc.user_wait();
+
+ expect(zbar::ZBAR_EAN13, test_image_ean13_data);
+ check_image(rgb3);
+
+ if (rgb3.get_format() != zbar_fourcc('R', 'G', 'B', '3'))
+ error("image format mismatch");
+
+ expect(zbar::ZBAR_NONE, "");
+ proc.set_config(zbar::ZBAR_EAN13, zbar::ZBAR_CFG_ENABLE, false);
+ proc.process_image(rgb3);
+ check_image(rgb3);
+ if (debug)
+ proc.user_wait();
+
+ proc.set_config("ean13.en");
+ expect(zbar::ZBAR_EAN13, test_image_ean13_data);
+ proc << rgb3;
+ expect(zbar::ZBAR_EAN13, test_image_ean13_data);
+ check_image(rgb3);
+ if (debug)
+ proc.user_wait();
+
+ {
+ zbar::Image grey(rgb3.convert(zbar_fourcc('G', 'R', 'E', 'Y')));
+ expect(zbar::ZBAR_EAN13, test_image_ean13_data);
+ proc << grey;
+
+ zbar::Image y800 = grey.convert("Y800");
+ expect(zbar::ZBAR_EAN13, test_image_ean13_data);
+ proc << y800;
+ }
+ if (debug)
+ // check image data retention
+ proc.user_wait();
+
+ expect(zbar::ZBAR_NONE, "");
+ return (0);
+}
+
+int main(int argc, char **argv)
+{
+ debug = (argc > 1 && std::string(argv[1]) == "-d");
+ verbose = (debug || (argc > 1 && std::string(argv[1]) == "-v"));
+
+ if (test_processor()) {
+ error("ERROR: Processor test FAILED");
+ return (2);
+ }
+
+ if (test_image_check_cleanup())
+ error("cleanup failed");
+
+ if (errors) {
+ std::cout << "processor FAILED" << std::endl;
+ return (2);
+ } else {
+ std::cout << "processor PASSED." << std::endl;
+ return (0);
+ }
+}
diff --git a/test/test_dbus.c b/test/test_dbus.c
new file mode 100644
index 0000000..60a415e
--- /dev/null
+++ b/test/test_dbus.c
@@ -0,0 +1,254 @@
+/*------------------------------------------------------------------------
+ * Copyright 2019 (c) Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *------------------------------------------------------------------------*/
+
+#include <argp.h>
+#include <dbus/dbus.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ZBAR_INTERFACE "org.linuxtv.Zbar1.Code"
+#define ZBAR_SIGNAL_CODE "Code"
+#define ZBAR_SIGNAL_TYPE "Type"
+#define ZBAR_SIGNAL_DATA "Data"
+#define ZBAR_SIGNAL_BINARY_DATA "BinaryData"
+
+#define PROGRAM_NAME "test_dbus"
+
+static const char doc[] = "\nTest if ZBar is sending codes via D-Bus\n";
+
+static const struct argp_option options[] = {
+ { "count", 'c', "#codes", 0, "Stop after received #codes", 0 },
+ { "time", 't', "#seconds", 0, "Stop after #seconds", 0 },
+ { "log", 'l', "#file", 0, "Write log to #file", 0 },
+ { "bin-log", 'b', "#file", 0, "Write binary log to #file", 0 },
+ { "help", '?', 0, 0, "Give this help list", -1 },
+ { "usage", -3, 0, 0, "Give a short usage message", 0 },
+ { 0 }
+};
+
+static int max_msg = 0;
+static int timeout = 0;
+static FILE *log = NULL;
+static FILE *bin_log = NULL;
+
+static error_t parse_opt(int k, char *optarg, struct argp_state *state)
+{
+ switch (k) {
+ case 'c':
+ max_msg = strtoul(optarg, NULL, 0);
+ break;
+ case 't':
+ timeout = strtoul(optarg, NULL, 0);
+ break;
+ case 'l':
+ log = fopen(optarg, "wb");
+ break;
+ case 'b':
+ bin_log = fopen(optarg, "wb");
+ break;
+ case '?':
+ argp_state_help(state, state->out_stream,
+ ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC);
+ exit(0);
+ case -3:
+ argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
+ exit(0);
+ default:
+ return ARGP_ERR_UNKNOWN;
+ };
+ return 0;
+}
+
+static const struct argp argp = {
+ .options = options,
+ .parser = parse_opt,
+ .doc = doc,
+};
+
+int main(int argc, char *argv[])
+{
+ DBusMessage *msg;
+ DBusMessageIter args, entry, dict, val;
+ DBusConnection *conn;
+ DBusError err;
+ char *str, *property;
+ int count = 0, length = 0;
+
+ if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0)) {
+ argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
+ return -1;
+ }
+
+ if (!log)
+ log = fdopen(dup(fileno(stderr)), "w+");
+
+ if (!bin_log)
+ bin_log = fdopen(dup(fileno(stderr)), "w+");
+
+ // initialise the error value
+ dbus_error_init(&err);
+
+ // connect to the DBUS system bus, and check for errors
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+ if (dbus_error_is_set(&err)) {
+ fprintf(stderr, "Connection Error (%s)\n", err.message);
+ dbus_error_free(&err);
+ }
+ if (!conn) {
+ fprintf(stderr, "Connection Null\n");
+ return -1;
+ }
+
+ dbus_bus_add_match(conn, "type='signal',interface='" ZBAR_INTERFACE "'",
+ &err);
+ dbus_connection_flush(conn);
+ if (dbus_error_is_set(&err)) {
+ fprintf(stderr, "Match Error (%s)\n", err.message);
+ exit(1);
+ }
+
+ if (timeout)
+ alarm(timeout);
+
+ /* loop listening for signals being emitted */
+ fprintf(stderr, "Waiting for Zbar events\n");
+ while (true) {
+ // non blocking read of the next available message
+ dbus_connection_read_write(conn, 0);
+ msg = dbus_connection_pop_message(conn);
+
+ // loop again if we haven't read a message
+ if (NULL == msg) {
+ sleep(1);
+ continue;
+ }
+
+ // check if the message is a signal from the correct interface and with the
+ // correct name
+ if (dbus_message_is_signal(msg, ZBAR_INTERFACE, ZBAR_SIGNAL_CODE)) {
+ // read the parameters
+ if (!dbus_message_iter_init(msg, &args))
+ fprintf(stderr, "Message has no arguments!\n");
+ else if (DBUS_TYPE_ARRAY != dbus_message_iter_get_arg_type(&args))
+ fprintf(stderr, "Argument is not array!\n");
+ else {
+ while (dbus_message_iter_get_arg_type(&args) !=
+ DBUS_TYPE_INVALID) {
+ dbus_message_iter_recurse(&args, &entry);
+ if (DBUS_TYPE_DICT_ENTRY !=
+ dbus_message_iter_get_arg_type(&entry)) {
+ fprintf(stderr, "Element is not dict entry!\n");
+ } else {
+ while (dbus_message_iter_get_arg_type(&entry) !=
+ DBUS_TYPE_INVALID) {
+ dbus_message_iter_recurse(&entry, &dict);
+ if (DBUS_TYPE_STRING !=
+ dbus_message_iter_get_arg_type(&dict)) {
+ fprintf(stderr,
+ "Dict Entry key is not string!\n");
+ } else {
+ dbus_message_iter_get_basic(&dict, &property);
+ dbus_message_iter_next(&dict);
+ if (DBUS_TYPE_VARIANT !=
+ dbus_message_iter_get_arg_type(&dict)) {
+ fprintf(
+ stderr,
+ "Dict Entry value is not variant!\n");
+ } else {
+ dbus_message_iter_recurse(&dict, &val);
+ if (strcmp(property, ZBAR_SIGNAL_TYPE) ==
+ 0) {
+ if (DBUS_TYPE_STRING !=
+ dbus_message_iter_get_arg_type(
+ &val)) {
+ fprintf(
+ stderr,
+ "Dict Entry value for barcode type is not string!\n");
+ } else {
+ dbus_message_iter_get_basic(&val,
+ &str);
+ fprintf(stderr, "Type = %s\n", str);
+ }
+ } else if (strcmp(property,
+ ZBAR_SIGNAL_DATA) == 0) {
+ if (DBUS_TYPE_STRING !=
+ dbus_message_iter_get_arg_type(
+ &val)) {
+ fprintf(
+ stderr,
+ "Dict Entry value for barcode text data is not string!\n");
+ } else {
+ dbus_message_iter_get_basic(&val,
+ &str);
+ fprintf(stderr, "Value = %s\n",
+ str);
+ fprintf(log, "%s\n", str);
+ }
+ } else if (strcmp(property,
+ ZBAR_SIGNAL_BINARY_DATA) ==
+ 0) {
+ if (DBUS_TYPE_ARRAY !=
+ dbus_message_iter_get_arg_type(
+ &val)) {
+ fprintf(
+ stderr,
+ "Dict Entry value for barcode binary data is not array!\n");
+ } else {
+ dbus_message_iter_recurse(&val,
+ &val);
+ if (DBUS_TYPE_BYTE !=
+ dbus_message_iter_get_arg_type(
+ &val)) {
+ fprintf(
+ stderr,
+ "Dict Entry value for barcode binary data is not array of bytes!\n");
+ } else {
+ dbus_message_iter_get_fixed_array(
+ &val, &str, &length);
+ fprintf(stderr,
+ "BinaryData[%d]\n",
+ length);
+ fwrite(str, sizeof(*str),
+ length, bin_log);
+ }
+ }
+ }
+ }
+ }
+ dbus_message_iter_next(&entry);
+ }
+ /* If max_msg > 0, stops after receiving 'count' messages */
+ if (++count == max_msg) {
+ dbus_message_unref(msg);
+ return 0;
+ }
+ }
+ dbus_message_iter_next(&args);
+ }
+ }
+ }
+ // free the message
+ dbus_message_unref(msg);
+ }
+
+ fclose(log);
+ fclose(bin_log);
+
+ return 0;
+}
diff --git a/test/test_decode.c b/test/test_decode.c
new file mode 100644
index 0000000..aa526f6
--- /dev/null
+++ b/test/test_decode.c
@@ -0,0 +1,1356 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include <argp.h>
+#include <assert.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <zbar.h>
+
+zbar_decoder_t *decoder;
+
+zbar_symbol_type_t expect_sym;
+char *expect_data = NULL;
+
+int rnd_size = 9; /* NB should be odd */
+int wrong = 0, spurious = 0, missing = 0;
+
+#define zprintf(level, format, ...) \
+ do { \
+ if (verbosity >= (level)) { \
+ fprintf(stderr, format, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PROGRAM_NAME "test_video"
+
+static const char doc[] =
+ "\nGenerate barcodes and decode them with ZBar decoding logic\n";
+
+static const struct argp_option options[] = {
+ { "quiet", 'q', 0, 0, "Don't be verbose", 0 },
+ { "verbose", 'v', 0, 0, "Increases verbosity level", 0 },
+ { "random", 'r', 0, 0, "use a random seed", 0 },
+ { "seed", 's', "seed", 0, "sets the random seed", 0 },
+ { "number", 'n', "count", 0, "sets the number of interactions", 0 },
+ { "help", '?', 0, 0, "Give this help list", -1 },
+ { "usage", -3, 0, 0, "Give a short usage message", 0 },
+ { 0 }
+};
+
+unsigned seed = 0, rand_seed = 0;
+int verbosity = 1;
+int iter = 0, num_iter = 0; /* test iteration */
+
+static error_t parse_opt(int k, char *optarg, struct argp_state *state)
+{
+ switch (k) {
+ case 'q':
+ verbosity = 0;
+ break;
+ case 'v':
+ verbosity++;
+ break;
+ case 'r':
+ rand_seed = 1;
+ break;
+ case 's':
+ seed = strtol(optarg, NULL, 0);
+ break;
+ case 'n':
+ num_iter = strtol(optarg, NULL, 0);
+ break;
+ case '?':
+ argp_state_help(state, state->out_stream,
+ ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC);
+ exit(0);
+ case -3:
+ argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
+ exit(0);
+ default:
+ return ARGP_ERR_UNKNOWN;
+ };
+ return 0;
+}
+
+static const struct argp argp = {
+ .options = options,
+ .parser = parse_opt,
+ .doc = doc,
+};
+
+static inline void print_sep(int level)
+{
+ zprintf(level,
+ "----------------------------------------------------------\n");
+}
+
+static void symbol_handler(zbar_decoder_t *decoder)
+{
+ zbar_symbol_type_t sym = zbar_decoder_get_type(decoder);
+ if (sym <= ZBAR_PARTIAL || sym == ZBAR_QRCODE)
+ return;
+ const char *data = zbar_decoder_get_data(decoder);
+
+ if (sym != expect_sym) {
+ zprintf(0, "[%d] SEED=%d: warning: expecting %s, got spurious %s\n",
+ iter, seed, zbar_get_symbol_name(expect_sym),
+ zbar_get_symbol_name(sym));
+ spurious++;
+ return;
+ }
+
+ int pass = (sym == expect_sym) && !strcmp(data, expect_data) &&
+ zbar_decoder_get_data_length(decoder) == strlen(data);
+ pass *= 3;
+
+ zprintf(pass, "decode %s:%s\n", zbar_get_symbol_name(sym), data);
+
+ if (!expect_sym)
+ zprintf(0, "UNEXPECTED!\n");
+ else
+ zprintf(pass, "expect %s:%s\n", zbar_get_symbol_name(expect_sym),
+ expect_data);
+ if (!pass) {
+ zprintf(0, "[%d] SEED=%d: ERROR: expecting %s (%s), got %s (%s)\n",
+ iter, seed, expect_data, zbar_get_symbol_name(expect_sym), data,
+ zbar_get_symbol_name(sym));
+ wrong++;
+ }
+
+ expect_sym = ZBAR_NONE;
+ free(expect_data);
+ expect_data = NULL;
+}
+
+static void expect(zbar_symbol_type_t sym, const char *data)
+{
+ if (expect_sym) {
+ zprintf(0, "[%d] SEED=%d: missing decode: %s (%s)\n", iter, seed,
+ zbar_get_symbol_name(expect_sym), expect_data);
+ missing++;
+ }
+ expect_sym = sym;
+ expect_data = (data) ? strdup(data) : NULL;
+}
+
+static void encode_junk(int n)
+{
+ if (n > 1)
+ zprintf(3, "encode random junk...\n");
+ int i;
+ for (i = 0; i < n; i++)
+ zbar_decode_width(decoder, 20. * (rand() / (RAND_MAX + 1.)) + 1);
+}
+
+#define FWD 1
+#define REV 0
+
+static void encode(uint64_t units, int fwd)
+{
+ zprintf(3, " raw=%x%x%c\n", (unsigned)(units >> 32),
+ (unsigned)(units & 0xffffffff), (fwd) ? '<' : '>');
+ if (!fwd)
+ while (units && !(units >> 0x3c))
+ units <<= 4;
+
+ while (units) {
+ unsigned char w = (fwd) ? units & 0xf : units >> 0x3c;
+ zbar_decode_width(decoder, w);
+ if (fwd)
+ units >>= 4;
+ else
+ units <<= 4;
+ }
+}
+
+/*------------------------------------------------------------*/
+/* Code 128 encoding */
+
+typedef enum code128_char_e
+{
+ FNC3 = 0x60,
+ FNC2 = 0x61,
+ SHIFT = 0x62,
+ CODE_C = 0x63,
+ CODE_B = 0x64,
+ CODE_A = 0x65,
+ FNC1 = 0x66,
+ START_A = 0x67,
+ START_B = 0x68,
+ START_C = 0x69,
+ STOP = 0x6a,
+} code128_char_t;
+
+static const unsigned int
+ code128[107] = {
+ 0x212222, 0x222122, 0x222221, 0x121223, /* 00 */
+ 0x121322, 0x131222, 0x122213, 0x122312,
+ 0x132212, 0x221213, 0x221312, 0x231212, /* 08 */
+ 0x112232, 0x122132, 0x122231, 0x113222,
+ 0x123122, 0x123221, 0x223211, 0x221132, /* 10 */
+ 0x221231, 0x213212, 0x223112, 0x312131,
+ 0x311222, 0x321122, 0x321221, 0x312212, /* 18 */
+ 0x322112, 0x322211, 0x212123, 0x212321,
+ 0x232121, 0x111323, 0x131123, 0x131321, /* 20 */
+ 0x112313, 0x132113, 0x132311, 0x211313,
+ 0x231113, 0x231311, 0x112133, 0x112331, /* 28 */
+ 0x132131, 0x113123, 0x113321, 0x133121,
+ 0x313121, 0x211331, 0x231131, 0x213113, /* 30 */
+ 0x213311, 0x213131, 0x311123, 0x311321,
+ 0x331121, 0x312113, 0x312311, 0x332111, /* 38 */
+ 0x314111, 0x221411, 0x431111, 0x111224,
+ 0x111422, 0x121124, 0x121421, 0x141122, /* 40 */
+ 0x141221, 0x112214, 0x112412, 0x122114,
+ 0x122411, 0x142112, 0x142211, 0x241211, /* 48 */
+ 0x221114, 0x413111, 0x241112, 0x134111,
+ 0x111242, 0x121142, 0x121241, 0x114212, /* 50 */
+ 0x124112, 0x124211, 0x411212, 0x421112,
+ 0x421211, 0x212141, 0x214121, 0x412121, /* 58 */
+ 0x111143, 0x111341, 0x131141, 0x114113,
+ 0x114311, 0x411113, 0x411311, 0x113141, /* 60 */
+ 0x114131, 0x311141, 0x411131, 0xa211412,
+ 0xa211214, 0xa211232, /* START_A-START_C (67-69) */
+ 0x2331112a, /* STOP (6a) */
+ };
+
+static void encode_code128b(char *data)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+ zprintf(2, "CODE-128(B): %s\n", data);
+ zprintf(3, " encode START_B: %02x", START_B);
+ encode(code128[START_B], 0);
+ int i, chk = START_B;
+ for (i = 0; data[i]; i++) {
+ zprintf(3, " encode '%c': %02x", data[i], data[i] - 0x20);
+ encode(code128[data[i] - 0x20], 0);
+ chk += (i + 1) * (data[i] - 0x20);
+ }
+ chk %= 103;
+ zprintf(3, " encode checksum: %02x", chk);
+ encode(code128[chk], 0);
+ zprintf(3, " encode STOP: %02x", STOP);
+ encode(code128[STOP], 0);
+ print_sep(3);
+}
+
+static void encode_code128c(char *data)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+ zprintf(2, "CODE-128(C): %s\n", data);
+ zprintf(3, " encode START_C: %02x", START_C);
+ encode(code128[START_C], 0);
+ int i, chk = START_C;
+ for (i = 0; data[i]; i += 2) {
+ assert(data[i] >= '0');
+ assert(data[i + 1] >= '0');
+ unsigned char c = (data[i] - '0') * 10 + (data[i + 1] - '0');
+ zprintf(3, " encode '%c%c': %02d", data[i], data[i + 1], c);
+ encode(code128[c], 0);
+ chk += (i / 2 + 1) * c;
+ }
+ chk %= 103;
+ zprintf(3, " encode checksum: %02x", chk);
+ encode(code128[chk], 0);
+ zprintf(3, " encode STOP: %02x", STOP);
+ encode(code128[STOP], 0);
+ print_sep(3);
+}
+
+/*------------------------------------------------------------*/
+/* Code 93 encoding */
+
+#define CODE93_START_STOP 0x2f
+
+static const unsigned int code93[47 + 1] = {
+ 0x131112, 0x111213, 0x111312, 0x111411, /* 00 */
+ 0x121113, 0x121212, 0x121311, 0x111114,
+ 0x131211, 0x141111, 0x211113, 0x211212, /* 08 */
+ 0x211311, 0x221112, 0x221211, 0x231111,
+ 0x112113, 0x112212, 0x112311, 0x122112, /* 10 */
+ 0x132111, 0x111123, 0x111222, 0x111321,
+ 0x121122, 0x131121, 0x212112, 0x212211, /* 18 */
+ 0x211122, 0x211221, 0x221121, 0x222111,
+ 0x112122, 0x112221, 0x122121, 0x123111, /* 20 */
+ 0x121131, 0x311112, 0x311211, 0x321111,
+ 0x112131, 0x113121, 0x211131, 0x121221, /* 28 */
+ 0x312111, 0x311121, 0x122211, 0x111141, /* START/STOP (2f) */
+};
+
+#define S1 0x2b00 |
+#define S2 0x2c00 |
+#define S3 0x2d00 |
+#define S4 0x2e00 |
+
+static const unsigned short code93_ext[0x80] = {
+ S2 'U', S1 'A', S1 'B', S1 'C', S1 'D', S1 'E', S1 'F', S1 'G', S1 'H',
+ S1 'I', S1 'J', S1 'K', S1 'L', S1 'M', S1 'N', S1 'O', S1 'P', S1 'Q',
+ S1 'R', S1 'S', S1 'T', S1 'U', S1 'V', S1 'W', S1 'X', S1 'Y', S1 'Z',
+ S2 'A', S2 'B', S2 'C', S2 'D', S2 'E', 0x26, S3 'A', S3 'B', S3 'C',
+ 0x27, 0x2a, S3 'F', S3 'G', S3 'H', S3 'I', S3 'J', 0x29, S3 'L',
+ 0x24, 0x25, 0x28, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, S3 'Z', S2 'F', S2 'G', S2 'H', S2 'I',
+ S2 'J', S2 'V', 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+ 0x23, S2 'K', S2 'L', S2 'M', S2 'N', S2 'O', S2 'W', S4 'A', S4 'B',
+ S4 'C', S4 'D', S4 'E', S4 'F', S4 'G', S4 'H', S4 'I', S4 'J', S4 'K',
+ S4 'L', S4 'M', S4 'N', S4 'O', S4 'P', S4 'Q', S4 'R', S4 'S', S4 'T',
+ S4 'U', S4 'V', S4 'W', S4 'X', S4 'Y', S4 'Z', S2 'P', S2 'Q', S2 'R',
+ S2 'S', S2 'T',
+};
+
+#undef S1
+#undef S2
+#undef S3
+#undef S4
+
+static void encode_char93(unsigned char c, int dir)
+{
+ unsigned ext = code93_ext[c];
+ unsigned shift = ext >> 8;
+ assert(shift < 0x30);
+ c = ext & 0xff;
+ if (shift) {
+ assert(c < 0x80);
+ c = code93_ext[c];
+ }
+ assert(c < 0x30);
+
+ if (shift) {
+ encode(code93[(dir) ? shift : c], dir ^ 1);
+ encode(code93[(dir) ? c : shift], dir ^ 1);
+ } else
+ encode(code93[c], dir ^ 1);
+}
+
+static void encode_code93(char *data, int dir)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+
+ /* calculate checksums */
+ int i, j, chk_c = 0, chk_k = 0, n = 0;
+ for (i = 0; data[i]; i++, n++) {
+ unsigned c = data[i], ext;
+ assert(c < 0x80);
+ ext = code93_ext[c];
+ n += ext >> 13;
+ }
+
+ for (i = 0, j = 0; data[i]; i++, j++) {
+ unsigned ext = code93_ext[(unsigned)data[i]];
+ unsigned shift = ext >> 8;
+ unsigned c = ext & 0xff;
+ if (shift) {
+ chk_c += shift * (((n - 1 - j) % 20) + 1);
+ chk_k += shift * (((n - j) % 15) + 1);
+ j++;
+ c = code93_ext[c];
+ }
+ chk_c += c * (((n - 1 - j) % 20) + 1);
+ chk_k += c * (((n - j) % 15) + 1);
+ }
+ chk_c %= 47;
+ chk_k += chk_c;
+ chk_k %= 47;
+
+ zprintf(2, "CODE-93: %s (n=%x C=%02x K=%02x)\n", data, n, chk_c, chk_k);
+ encode(0xa, 0); /* leading quiet */
+
+ zprintf(3, " encode %s:", (dir) ? "START" : "STOP");
+ if (!dir)
+ encode(0x1, REV);
+ encode(code93[CODE93_START_STOP], dir ^ 1);
+ if (!dir) {
+ zprintf(3, " encode checksum (K): %02x", chk_k);
+ encode(code93[chk_k], REV ^ 1);
+ zprintf(3, " encode checksum (C): %02x", chk_c);
+ encode(code93[chk_c], REV ^ 1);
+ }
+
+ n = strlen(data);
+ for (i = 0; i < n; i++) {
+ unsigned char c = data[(dir) ? i : (n - i - 1)];
+ zprintf(3, " encode '%c':", c);
+ encode_char93(c, dir);
+ }
+
+ if (dir) {
+ zprintf(3, " encode checksum (C): %02x", chk_c);
+ encode(code93[chk_c], FWD ^ 1);
+ zprintf(3, " encode checksum (K): %02x", chk_k);
+ encode(code93[chk_k], FWD ^ 1);
+ }
+ zprintf(3, " encode %s:", (dir) ? "STOP" : "START");
+ encode(code93[CODE93_START_STOP], dir ^ 1);
+ if (dir)
+ encode(0x1, FWD);
+
+ encode(0xa, 0); /* trailing quiet */
+ print_sep(3);
+}
+
+/*------------------------------------------------------------*/
+/* Code 39 encoding */
+
+static const unsigned int code39[91 - 32] = {
+ 0x0c4, 0x000, 0x000, 0x000, 0x0a8, 0x02a, 0x000, 0x000, /* 20 */
+ 0x000, 0x000, 0x094, 0x08a, 0x000, 0x085, 0x184, 0x0a2, /* 28 */
+ 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, /* 30 */
+ 0x124, 0x064, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 38 */
+ 0x000, 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00d, /* 40 */
+ 0x10c, 0x04c, 0x01c, 0x103, 0x043, 0x142, 0x013, 0x112, /* 48 */
+ 0x052, 0x007, 0x106, 0x046, 0x016, 0x181, 0x0c1, 0x1c0, /* 50 */
+ 0x091, 0x190, 0x0d0, /* 58 */
+};
+
+/* FIXME configurable/randomized ratio, ics */
+/* FIXME check digit option, ASCII escapes */
+
+static void convert_code39(char *data)
+{
+ char *src, *dst;
+ for (src = data, dst = data; *src; src++) {
+ char c = *src;
+ if (c >= 'a' && c <= 'z')
+ *(dst++) = c - ('a' - 'A');
+ else if (c == ' ' || c == '$' || c == '%' || c == '+' || c == '-' ||
+ (c >= '.' && c <= '9') || (c >= 'A' && c <= 'Z'))
+ *(dst++) = c;
+ else
+ /* skip (FIXME) */;
+ }
+ *dst = 0;
+}
+
+static void encode_char39(unsigned char c, unsigned ics)
+{
+ assert(0x20 <= c && c <= 0x5a);
+ unsigned int raw = code39[c - 0x20];
+ if (!raw)
+ return; /* skip (FIXME) */
+
+ uint64_t enc = 0;
+ int j;
+ for (j = 0; j < 9; j++) {
+ enc = (enc << 4) | ((raw & 0x100) ? 2 : 1);
+ raw <<= 1;
+ }
+ enc = (enc << 4) | ics;
+ zprintf(3, " encode '%c': %02x%08x: ", c, (unsigned)(enc >> 32),
+ (unsigned)(enc & 0xffffffff));
+ encode(enc, REV);
+}
+
+static void encode_code39(char *data)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+ zprintf(2, "CODE-39: %s\n", data);
+ encode(0xa, 0); /* leading quiet */
+ encode_char39('*', 1);
+ int i;
+ for (i = 0; data[i]; i++)
+ if (data[i] != '*') /* skip (FIXME) */
+ encode_char39(data[i], 1);
+ encode_char39('*', 0xa); /* w/trailing quiet */
+ print_sep(3);
+}
+
+#if 0
+/*------------------------------------------------------------*/
+/* PDF417 encoding */
+
+/* hardcoded test message: "hello world" */
+#define PDF417_ROWS 3
+#define PDF417_COLS 3
+static const unsigned pdf417_msg[PDF417_ROWS][PDF417_COLS] = {
+ { 007, 817, 131 },
+ { 344, 802, 437 },
+ { 333, 739, 194 },
+};
+
+#define PDF417_START UINT64_C(0x81111113)
+#define PDF417_STOP UINT64_C(0x711311121)
+#include "pdf417_encode.h"
+
+static int calc_ind417 (int mod,
+ int r,
+ int cols)
+{
+ mod = (mod + 3) % 3;
+ int cw = 30 * (r / 3);
+ if(!mod)
+ return(cw + cols - 1);
+ else if(mod == 1)
+ return(cw + (PDF417_ROWS - 1) % 3);
+ assert(mod == 2);
+ return(cw + (PDF417_ROWS - 1) / 3);
+}
+
+static void encode_row417 (int r,
+ const unsigned *cws,
+ int cols,
+ int dir)
+{
+ int k = r % 3;
+
+ zprintf(3, " [%d] encode %s:", r, (dir) ? "stop" : "start");
+ encode((dir) ? PDF417_STOP : PDF417_START, dir);
+
+ int cw = calc_ind417(k + !dir, r, cols);
+ zprintf(3, " [%d,%c] encode %03d(%d): ", r, (dir) ? 'R' : 'L', cw, k);
+ encode(pdf417_encode[cw][k], dir);
+
+ int c;
+ for(c = 0; c < cols; c++) {
+ cw = cws[c];
+ zprintf(3, " [%d,%d] encode %03d(%d): ", r, c, cw, k);
+ encode(pdf417_encode[cw][k], dir);
+ }
+
+ cw = calc_ind417(k + dir, r, cols);
+ zprintf(3, " [%d,%c] encode %03d(%d): ", r, (dir) ? 'L' : 'R', cw, k);
+ encode(pdf417_encode[cw][k], dir);
+
+ zprintf(3, " [%d] encode %s:", r, (dir) ? "start" : "stop");
+ encode((dir) ? PDF417_START : PDF417_STOP, dir);
+}
+
+static void encode_pdf417 (char *data)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+ zprintf(2, "PDF417: hello world\n");
+ encode(0xa, 0);
+
+ int r;
+ for(r = 0; r < PDF417_ROWS; r++) {
+ encode_row417(r, pdf417_msg[r], PDF417_COLS, r & 1);
+ encode(0xa, 0);
+ }
+
+ print_sep(3);
+}
+#endif
+
+/*------------------------------------------------------------*/
+/* Codabar encoding */
+
+static const unsigned int codabar[20] = {
+ 0x03, 0x06, 0x09, 0x60, 0x12, 0x42, 0x21, 0x24, 0x30, 0x48,
+ 0x0c, 0x18, 0x45, 0x51, 0x54, 0x15, 0x1a, 0x29, 0x0b, 0x0e,
+};
+
+static const char codabar_char[0x14] = "0123456789-$:/.+ABCD";
+
+/* FIXME configurable/randomized ratio, ics */
+/* FIXME check digit option */
+
+static char *convert_codabar(char *src)
+{
+ unsigned len = strlen(src);
+ char tmp[4] = {
+ 0,
+ };
+ if (len < 2) {
+ unsigned delim = rand() >> 8;
+ tmp[0] = delim & 3;
+ if (len)
+ tmp[1] = src[0];
+ tmp[len + 1] = (delim >> 2) & 3;
+ len += 2;
+ src = tmp;
+ }
+
+ char *result = malloc(len + 1);
+ char *dst = result;
+ *(dst++) = ((*(src++) - 1) & 0x3) + 'A';
+ for (len--; len > 1; len--) {
+ char c = *(src++);
+ if (c >= '0' && c <= '9')
+ *(dst++) = c;
+ else if (c == '-' || c == '$' || c == ':' || c == '/' || c == '.' ||
+ c == '+')
+ *(dst++) = c;
+ else
+ *(dst++) = codabar_char[c % 0x10];
+ }
+ *(dst++) = ((*(src++) - 1) & 0x3) + 'A';
+ *dst = 0;
+ return (result);
+}
+
+static void encode_codachar(unsigned char c, unsigned ics, int dir)
+{
+ unsigned int idx;
+ if (c >= '0' && c <= '9')
+ idx = c - '0';
+ else if (c >= 'A' && c <= 'D')
+ idx = c - 'A' + 0x10;
+ else
+ switch (c) {
+ case '-':
+ idx = 0xa;
+ break;
+ case '$':
+ idx = 0xb;
+ break;
+ case ':':
+ idx = 0xc;
+ break;
+ case '/':
+ idx = 0xd;
+ break;
+ case '.':
+ idx = 0xe;
+ break;
+ case '+':
+ idx = 0xf;
+ break;
+ default:
+ assert(0);
+ }
+
+ assert(idx < 0x14);
+ unsigned int raw = codabar[idx];
+
+ uint32_t enc = 0;
+ int j;
+ for (j = 0; j < 7; j++, raw <<= 1)
+ enc = (enc << 4) | ((raw & 0x40) ? 3 : 1);
+ zprintf(3, " encode '%c': %07x: ", c, enc);
+ if (dir)
+ enc = (enc << 4) | ics;
+ else
+ enc |= ics << 28;
+ encode(enc, 1 - dir);
+}
+
+static void encode_codabar(char *data, int dir)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+ zprintf(2, "CODABAR: %s\n", data);
+ encode(0xa, 0); /* leading quiet */
+ int i, n = strlen(data);
+ for (i = 0; i < n; i++) {
+ int j = (dir) ? i : n - i - 1;
+ encode_codachar(data[j], (i < n - 1) ? 1 : 0xa, dir);
+ }
+ print_sep(3);
+}
+
+/*------------------------------------------------------------*/
+/* Interleaved 2 of 5 encoding */
+
+static const unsigned char i25[10] = {
+ 0x06, 0x11, 0x09, 0x18, 0x05, 0x14, 0x0c, 0x03, 0x12, 0x0a,
+};
+
+static void encode_i25(char *data, int dir)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+ zprintf(2, "Interleaved 2 of 5: %s\n", data);
+ zprintf(3, " encode start:");
+ encode((dir) ? 0xa1111 : 0xa112, 0);
+
+ /* FIXME rev case data reversal */
+ int i;
+ for (i = (strlen(data) & 1) ? -1 : 0; i < 0 || data[i]; i += 2) {
+ /* encode 2 digits */
+ unsigned char c0 = (i < 0) ? 0 : data[i] - '0';
+ unsigned char c1 = data[i + 1] - '0';
+ zprintf(3, " encode '%d%d':", c0, c1);
+ assert(c0 < 10);
+ assert(c1 < 10);
+
+ c0 = i25[c0];
+ c1 = i25[c1];
+
+ /* interleave */
+ uint64_t enc = 0;
+ int j;
+ for (j = 0; j < 5; j++) {
+ enc <<= 8;
+ enc |= (c0 & 1) ? 0x02 : 0x01;
+ enc |= (c1 & 1) ? 0x20 : 0x10;
+ c0 >>= 1;
+ c1 >>= 1;
+ }
+ encode(enc, dir);
+ }
+
+ zprintf(3, " encode end:");
+ encode((dir) ? 0x211a : 0x1111a, 0);
+ print_sep(3);
+}
+
+/*------------------------------------------------------------*/
+/* DataBar encoding */
+
+/* character encoder reference algorithm from ISO/IEC 24724:2009 */
+
+struct rss_group {
+ int T_odd, T_even, n_odd, w_max;
+};
+
+static const struct rss_group databar_groups_outside[] = { { 161, 1, 12, 8 },
+ { 80, 10, 10, 6 },
+ { 31, 34, 8, 4 },
+ { 10, 70, 6, 3 },
+ { 1, 126, 4, 1 },
+ {
+ 0,
+ } };
+
+static const struct rss_group databar_groups_inside[] = { { 4, 84, 5, 2 },
+ { 20, 35, 7, 4 },
+ { 48, 10, 9, 6 },
+ { 81, 1, 11, 8 },
+ {
+ 0,
+ } };
+
+static const uint32_t databar_finders[9] = {
+ 0x38211, 0x35511, 0x33711, 0x31911, 0x27411,
+ 0x25611, 0x23811, 0x15711, 0x13911,
+};
+
+int combins(int n, int r)
+{
+ int i, j;
+ int maxDenom, minDenom;
+ int val;
+ if (n - r > r) {
+ minDenom = r;
+ maxDenom = n - r;
+ } else {
+ minDenom = n - r;
+ maxDenom = r;
+ }
+ val = 1;
+ j = 1;
+ for (i = n; i > maxDenom; i--) {
+ val *= i;
+ if (j <= minDenom) {
+ val /= j;
+ j++;
+ }
+ }
+ for (; j <= minDenom; j++)
+ val /= j;
+ return (val);
+}
+
+void getRSSWidths(int val, int n, int elements, int maxWidth, int noNarrow,
+ int *widths)
+{
+ int narrowMask = 0;
+ int bar;
+ for (bar = 0; bar < elements - 1; bar++) {
+ int elmWidth, subVal;
+ for (elmWidth = 1, narrowMask |= (1 << bar);;
+ elmWidth++, narrowMask &= ~(1 << bar)) {
+ subVal = combins(n - elmWidth - 1, elements - bar - 2);
+ if ((!noNarrow) && !narrowMask &&
+ (n - elmWidth - (elements - bar - 1) >= elements - bar - 1))
+ subVal -= combins(n - elmWidth - (elements - bar),
+ elements - bar - 2);
+ if (elements - bar - 1 > 1) {
+ int mxwElement, lessVal = 0;
+ for (mxwElement = n - elmWidth - (elements - bar - 2);
+ mxwElement > maxWidth; mxwElement--)
+ lessVal += combins(n - elmWidth - mxwElement - 1,
+ elements - bar - 3);
+ subVal -= lessVal * (elements - 1 - bar);
+ } else if (n - elmWidth > maxWidth)
+ subVal--;
+ val -= subVal;
+ if (val < 0)
+ break;
+ }
+ val += subVal;
+ n -= elmWidth;
+ widths[bar] = elmWidth;
+ }
+ widths[bar] = n;
+}
+
+static uint64_t encode_databar_char(unsigned val, const struct rss_group *grp,
+ int nmodules, int nelems, int dir)
+{
+ int G_sum = 0;
+ while (1) {
+ assert(grp->T_odd);
+ int sum = G_sum + grp->T_odd * grp->T_even;
+ if (val >= sum)
+ G_sum = sum;
+ else
+ break;
+ grp++;
+ }
+
+ zprintf(3, "char=%d", val);
+
+ int V_grp = val - G_sum;
+ int V_odd, V_even;
+ if (!dir) {
+ V_odd = V_grp / grp->T_even;
+ V_even = V_grp % grp->T_even;
+ } else {
+ V_even = V_grp / grp->T_odd;
+ V_odd = V_grp % grp->T_odd;
+ }
+
+ zprintf(3, " G_sum=%d T_odd=%d T_even=%d n_odd=%d w_max=%d V_grp=%d\n",
+ G_sum, grp->T_odd, grp->T_even, grp->n_odd, grp->w_max, V_grp);
+
+ int odd[16];
+ getRSSWidths(V_odd, grp->n_odd, nelems, grp->w_max, !dir, odd);
+ zprintf(3, " V_odd=%d odd=%d%d%d%d", V_odd, odd[0], odd[1], odd[2],
+ odd[3]);
+
+ int even[16];
+ getRSSWidths(V_even, nmodules - grp->n_odd, nelems, 9 - grp->w_max, dir,
+ even);
+ zprintf(3, " V_even=%d even=%d%d%d%d", V_even, even[0], even[1], even[2],
+ even[3]);
+
+ uint64_t units = 0;
+ int i;
+ for (i = 0; i < nelems; i++)
+ units = (units << 8) | (odd[i] << 4) | even[i];
+
+ zprintf(3, " raw=%" PRIx64 "\n", units);
+ return (units);
+}
+
+#define SWAP(a, b) \
+ do { \
+ uint32_t tmp = (a); \
+ (a) = (b); \
+ (b) = tmp; \
+ } while (0);
+
+static void encode_databar(char *data, int dir)
+{
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+
+ print_sep(3);
+ zprintf(2, "DataBar: %s\n", data);
+
+ uint32_t v[4] = {
+ 0,
+ };
+ int i, j;
+ for (i = 0; i < 14; i++) {
+ for (j = 0; j < 4; j++)
+ v[j] *= 10;
+ assert(data[i]);
+ v[0] += data[i] - '0';
+ v[1] += v[0] / 1597;
+ v[0] %= 1597;
+ v[2] += v[1] / 2841;
+ v[1] %= 2841;
+ v[3] += v[2] / 1597;
+ v[2] %= 1597;
+ /*printf(" [%d] %c (%d,%d,%d,%d)\n",
+ i, data[i], v[0], v[1], v[2], v[3]);*/
+ }
+ zprintf(3, "chars=(%d,%d,%d,%d)\n", v[3], v[2], v[1], v[0]);
+
+ uint32_t c[4] = {
+ encode_databar_char(v[3], databar_groups_outside, 16, 4, 0),
+ encode_databar_char(v[2], databar_groups_inside, 15, 4, 1),
+ encode_databar_char(v[1], databar_groups_outside, 16, 4, 0),
+ encode_databar_char(v[0], databar_groups_inside, 15, 4, 1),
+ };
+
+ int chk = 0, w = 1;
+ for (i = 0; i < 4; i++, chk %= 79, w %= 79)
+ for (j = 0; j < 8; j++, w *= 3)
+ chk += ((c[i] >> (28 - j * 4)) & 0xf) * w;
+ zprintf(3, "chk=%d\n", chk);
+
+ if (chk >= 8)
+ chk++;
+ if (chk >= 72)
+ chk++;
+ int C_left = chk / 9;
+ int C_right = chk % 9;
+
+ if (dir == REV) {
+ SWAP(C_left, C_right);
+ SWAP(c[0], c[2]);
+ SWAP(c[1], c[3]);
+ SWAP(v[0], v[2]);
+ SWAP(v[1], v[3]);
+ }
+
+ zprintf(3, " encode start guard:");
+ encode_junk(dir);
+ encode(0x1, FWD);
+
+ zprintf(3, "encode char[0]=%d", v[3]);
+ encode(c[0], REV);
+
+ zprintf(3, "encode left finder=%d", C_left);
+ encode(databar_finders[C_left], REV);
+
+ zprintf(3, "encode char[1]=%d", v[2]);
+ encode(c[1], FWD);
+
+ zprintf(3, "encode char[3]=%d", v[0]);
+ encode(c[3], REV);
+
+ zprintf(3, "encode right finder=%d", C_right);
+ encode(databar_finders[C_right], FWD);
+
+ zprintf(3, "encode char[2]=%d", v[1]);
+ encode(c[2], FWD);
+
+ zprintf(3, " encode end guard:");
+ encode(0x1, FWD);
+ encode_junk(!dir);
+ print_sep(3);
+}
+
+/*------------------------------------------------------------*/
+/* EAN/UPC encoding */
+
+static const unsigned int ean_digits[10] = {
+ 0x1123, 0x1222, 0x2212, 0x1141, 0x2311,
+ 0x1321, 0x4111, 0x2131, 0x3121, 0x2113,
+};
+
+static const unsigned int ean_guard[] = {
+ 0, 0, 0x11, /* [2] add-on delineator */
+ 0x1117, /* [3] normal guard bars */
+ 0x2117, /* [4] add-on guard bars */
+ 0x11111, /* [5] center guard bars */
+ 0x111111 /* [6] "special" guard bars */
+};
+
+static const unsigned char ean_parity_encode[] = {
+ 0x3f, /* AAAAAA = 0 */
+ 0x34, /* AABABB = 1 */
+ 0x32, /* AABBAB = 2 */
+ 0x31, /* AABBBA = 3 */
+ 0x2c, /* ABAABB = 4 */
+ 0x26, /* ABBAAB = 5 */
+ 0x23, /* ABBBAA = 6 */
+ 0x2a, /* ABABAB = 7 */
+ 0x29, /* ABABBA = 8 */
+ 0x25, /* ABBABA = 9 */
+};
+
+static const unsigned char addon_parity_encode[] = {
+ 0x07, /* BBAAA = 0 */
+ 0x0b, /* BABAA = 1 */
+ 0x0d, /* BAABA = 2 */
+ 0x0e, /* BAAAB = 3 */
+ 0x13, /* ABBAA = 4 */
+ 0x19, /* AABBA = 5 */
+ 0x1c, /* AAABB = 6 */
+ 0x15, /* ABABA = 7 */
+ 0x16, /* ABAAB = 8 */
+ 0x1a, /* AABAB = 9 */
+};
+
+static void calc_ean_parity(char *data, int n)
+{
+ int i, chk = 0;
+ for (i = 0; i < n; i++) {
+ unsigned char c = data[i] - '0';
+ chk += ((i ^ n) & 1) ? c * 3 : c;
+ }
+ chk %= 10;
+ if (chk)
+ chk = 10 - chk;
+ data[i++] = '0' + chk;
+ data[i] = 0;
+}
+
+static void encode_ean13(char *data)
+{
+ int i;
+ unsigned char par = ean_parity_encode[data[0] - '0'];
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+
+ print_sep(3);
+ zprintf(2, "EAN-13: %s (%02x)\n", data, par);
+ zprintf(3, " encode start guard:");
+ encode(ean_guard[3], FWD);
+ for (i = 1; i < 7; i++, par <<= 1) {
+ zprintf(3, " encode %x%c:", (par >> 5) & 1, data[i]);
+ encode(ean_digits[data[i] - '0'], (par >> 5) & 1);
+ }
+ zprintf(3, " encode center guard:");
+ encode(ean_guard[5], FWD);
+ for (; i < 13; i++) {
+ zprintf(3, " encode %x%c:", 0, data[i]);
+ encode(ean_digits[data[i] - '0'], FWD);
+ }
+ zprintf(3, " encode end guard:");
+ encode(ean_guard[3], REV);
+ print_sep(3);
+}
+
+static void encode_ean8(char *data)
+{
+ int i;
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ print_sep(3);
+ zprintf(2, "EAN-8: %s\n", data);
+ zprintf(3, " encode start guard:");
+ encode(ean_guard[3], FWD);
+ for (i = 0; i < 4; i++) {
+ zprintf(3, " encode %c:", data[i]);
+ encode(ean_digits[data[i] - '0'], FWD);
+ }
+ zprintf(3, " encode center guard:");
+ encode(ean_guard[5], FWD);
+ for (; i < 8; i++) {
+ zprintf(3, " encode %c:", data[i]);
+ encode(ean_digits[data[i] - '0'], FWD);
+ }
+ zprintf(3, " encode end guard:");
+ encode(ean_guard[3], REV);
+ print_sep(3);
+}
+
+static void encode_addon(char *data, unsigned par, int n)
+{
+ int i;
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+
+ print_sep(3);
+ zprintf(2, "EAN-%d: %s (par=%02x)\n", n, data, par);
+ zprintf(3, " encode start guard:");
+ encode(ean_guard[4], FWD);
+ for (i = 0; i < n; i++, par <<= 1) {
+ zprintf(3, " encode %x%c:", (par >> (n - 1)) & 1, data[i]);
+ encode(ean_digits[data[i] - '0'], (par >> (n - 1)) & 1);
+ if (i < n - 1) {
+ zprintf(3, " encode delineator:");
+ encode(ean_guard[2], FWD);
+ }
+ }
+ zprintf(3, " encode trailing qz:");
+ encode(0x7, FWD);
+ print_sep(3);
+}
+
+static void encode_ean5(char *data)
+{
+ unsigned chk = ((data[0] - '0' + data[2] - '0' + data[4] - '0') * 3 +
+ (data[1] - '0' + data[3] - '0') * 9) %
+ 10;
+ encode_addon(data, addon_parity_encode[chk], 5);
+}
+
+static void encode_ean2(char *data)
+{
+ unsigned par = (~(10 * (data[0] - '0') + data[1] - '0')) & 3;
+ encode_addon(data, par, 2);
+}
+
+/*------------------------------------------------------------*/
+/* main test flow */
+
+int test_databar_F_1()
+{
+ expect(ZBAR_DATABAR, "0124012345678905");
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ encode(0x11, 0);
+ encode(0x31111333, 0);
+ encode(0x13911, 0);
+ encode(0x31131231, 0);
+ encode(0x11214222, 0);
+ encode(0x11553, 0);
+ encode(0x21231313, 0);
+ encode(0x1, 0);
+ encode_junk(rnd_size);
+ return (0);
+}
+
+int test_databar_F_3()
+{
+ expect(ZBAR_DATABAR_EXP, "1012A");
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ encode(0x11, 0);
+ encode(0x11521151, 0);
+ encode(0x18411, 0);
+ encode(0x13171121, 0);
+ encode(0x11521232, 0);
+ encode(0x11481, 0);
+ encode(0x23171111, 0);
+ encode(0x1, 0);
+ encode_junk(rnd_size);
+ return (0);
+}
+
+int test_orange()
+{
+ char data[32] = "0100845963000052";
+ expect(ZBAR_DATABAR, data);
+ assert(zbar_decoder_get_color(decoder) == ZBAR_SPACE);
+ encode(0x1, 0);
+ encode(0x23212321, 0); // data[0]
+ encode(0x31911, 0); // finder[?] = 3
+ encode(0x21121215, 1); // data[1]
+ encode(0x41111133, 0); // data[3]
+ encode(0x23811, 1); // finder[?] = 6
+ encode(0x11215141, 1); // data[2]
+ encode(0x11, 0);
+ encode_junk(rnd_size);
+
+ expect(ZBAR_DATABAR, data);
+ data[1] = '0';
+ encode_databar(data + 1, FWD);
+ encode_junk(rnd_size);
+ return (0);
+}
+
+int test_numeric(char *data)
+{
+ char tmp[32] = "01";
+ strncpy(tmp + 2, data + 1, 13);
+ tmp[15] = '\0';
+ calc_ean_parity(tmp + 2, 13);
+ expect(ZBAR_DATABAR, tmp);
+
+ tmp[1] = data[0] & '1';
+ encode_databar(tmp + 1, (rand() >> 8) & 1);
+
+ encode_junk(rnd_size);
+
+ data[strlen(data) & ~1] = 0;
+ expect(ZBAR_CODE128, data);
+ encode_code128c(data);
+
+ encode_junk(rnd_size);
+
+ expect(ZBAR_I25, data);
+ encode_i25(data, FWD);
+
+ encode_junk(rnd_size);
+#if 0 /* FIXME encoding broken */
+ encode_i25(data, REV);
+
+ encode_junk(rnd_size);
+#endif
+
+ char *cdb = convert_codabar(data);
+ expect(ZBAR_CODABAR, cdb);
+ encode_codabar(cdb, FWD);
+ encode_junk(rnd_size);
+
+ expect(ZBAR_CODABAR, cdb);
+ encode_codabar(cdb, REV);
+ encode_junk(rnd_size);
+ free(cdb);
+
+ calc_ean_parity(data + 2, 12);
+ expect(ZBAR_EAN13, data + 2);
+ encode_ean13(data + 2);
+ encode_junk(rnd_size);
+
+ calc_ean_parity(data + 7, 7);
+ expect(ZBAR_EAN8, data + 7);
+ encode_ean8(data + 7);
+
+ encode_junk(rnd_size);
+
+ data[5] = 0;
+ expect(ZBAR_EAN5, data);
+ encode_ean5(data);
+
+ encode_junk(rnd_size);
+
+ data[2] = 0;
+ expect(ZBAR_EAN2, data);
+ encode_ean2(data);
+ encode_junk(rnd_size);
+
+ expect(ZBAR_NONE, NULL);
+ return (0);
+}
+
+int test_alpha(char *data)
+{
+ expect(ZBAR_CODE128, data);
+ encode_code128b(data);
+
+ encode_junk(rnd_size);
+
+ expect(ZBAR_CODE93, data);
+ encode_code93(data, FWD);
+
+ encode_junk(rnd_size);
+
+ expect(ZBAR_CODE93, data);
+ encode_code93(data, REV);
+
+ encode_junk(rnd_size);
+
+ char *cdb = convert_codabar(data);
+ expect(ZBAR_CODABAR, cdb);
+ encode_codabar(cdb, FWD);
+ encode_junk(rnd_size);
+
+ expect(ZBAR_CODABAR, cdb);
+ encode_codabar(cdb, REV);
+ encode_junk(rnd_size);
+ free(cdb);
+
+ convert_code39(data);
+ expect(ZBAR_CODE39, data);
+ encode_code39(data);
+
+ encode_junk(rnd_size);
+
+#if 0 /* FIXME decoder unfinished */
+ encode_pdf417(data);
+
+ encode_junk(rnd_size);
+#endif
+
+ expect(ZBAR_NONE, NULL);
+ return (0);
+}
+
+int test1()
+{
+ print_sep(2);
+ if (!seed)
+ seed = 0xbabeface;
+ zprintf(1, "[%d] SEED=%d\n", iter, seed);
+ srand(seed);
+
+ int i;
+ char data[32];
+ for (i = 0; i < 14; i++) {
+ data[i] = (rand() % 10) + '0';
+ }
+ data[i] = 0;
+
+ zprintf(1, "testing data: %s\n", data);
+
+ test_numeric(data);
+
+ for (i = 0; i < 10; i++)
+ data[i] = (rand() % 0x5f) + 0x20;
+ data[i] = 0;
+
+ zprintf(1, "testing alpha: %s\n", data);
+
+ test_alpha(data);
+ return (0);
+}
+
+/* FIXME TBD:
+ * - random module width (!= 1.0)
+ * - simulate scan speed variance
+ * - simulate dark "swelling" and light "blooming"
+ * - inject parity errors
+ */
+
+float percent(int count, int iter)
+{
+ if (iter <= 1) {
+ if (count)
+ return 100.0;
+ else
+ return 0.0;
+ }
+ return (count * 100.0) / iter;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0)) {
+ argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
+ return -1;
+ }
+
+ if (rand_seed) {
+ seed = time(NULL);
+ srand(seed);
+ seed = (rand() << 8) ^ rand();
+ zprintf(0, "Random SEED=%d\n", seed);
+ }
+
+ decoder = zbar_decoder_create();
+ /* allow empty CODE39 symbologies */
+ zbar_decoder_set_config(decoder, ZBAR_CODE39, ZBAR_CFG_MIN_LEN, 0);
+ /* enable addons */
+ zbar_decoder_set_config(decoder, ZBAR_EAN2, ZBAR_CFG_ENABLE, 1);
+ zbar_decoder_set_config(decoder, ZBAR_EAN5, ZBAR_CFG_ENABLE, 1);
+ zbar_decoder_set_handler(decoder, symbol_handler);
+
+ encode_junk(rnd_size + 1);
+
+ if (num_iter) {
+ for (iter = 0; iter < num_iter; iter++) {
+ test1();
+ seed = (rand() << 8) ^ rand();
+ }
+ } else {
+ test_databar_F_1();
+ test_databar_F_3();
+ test_orange();
+ test1();
+ }
+
+ zbar_decoder_destroy(decoder);
+
+ if (!wrong && percent(spurious, num_iter) <= 0.01 &&
+ percent(missing, num_iter) <= 0.01) {
+ if (spurious || missing)
+ printf(
+ "decoder PASSED with %d spurious (%02.4f%%) and %d missing(%02.4f%%).\n",
+ spurious, percent(spurious, num_iter), missing,
+ percent(missing, num_iter));
+ else
+ printf("decoder PASSED.\n");
+ } else {
+ printf(
+ "decoder FAILED with %d wrong decoding(%02.4f%%), %d spurious (%02.4f%%) and %d missing(%02.4f%%).\n",
+ wrong, percent(wrong, num_iter), spurious,
+ percent(spurious, num_iter), missing, percent(missing, num_iter));
+ return 1;
+ }
+ return (0);
+}
diff --git a/test/test_examples.sh.in b/test/test_examples.sh.in
new file mode 100644
index 0000000..f4c18e8
--- /dev/null
+++ b/test/test_examples.sh.in
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+unset ERR
+
+DIR="@abs_top_srcdir@"
+ZBARIMG="@abs_top_builddir@/zbarimg/zbarimg --nodbus"
+
+test()
+{
+ if [ "$2" != "" ]; then
+ i="$DIR/examples/$2"
+ j="$1 $2"
+ else
+ i="$DIR/examples/$1"
+ j="$1"
+ fi;
+ if [ "$2" != "" ]; then
+ CMD="$ZBARIMG $1"
+ else
+ CMD="$ZBARIMG"
+ fi
+ CK=`$CMD "$i" 2>/dev/null|sha1sum|cut -d" " -f1`
+ ORG=`grep "zbarimg $j" "$DIR/examples/sha1sum"|cut -d " " -f1`
+
+ if [ "$CK" != "$ORG" ]; then
+ echo "FAILED: $i ($CK instead of $ORG)"
+ echo -e "\tcmd: $CMD '$i'"
+ echo -en "\tresults: "
+ $CMD "$i" 2>/dev/null
+ ERR=1
+ fi
+}
+
+if [ "@ENABLE_CODE128@" == "1" ]; then
+ test code-128.png
+fi
+
+if [ "@ENABLE_CODE93@" == "1" ]; then
+ test code-93.png
+fi
+
+if [ "@ENABLE_CODE39@" == "1" ]; then
+ test code-39.png
+fi
+
+if [ "@ENABLE_CODABAR@" == "1" ]; then
+ test codabar.png
+fi
+
+if [ "@ENABLE_DATABAR@" == "1" ]; then
+ test databar.png
+ test databar-exp.png
+fi
+
+if [ "@ENABLE_EAN@" == "1" ]; then
+ test -Sean2.enable ean-2.png
+ test -Sean5.enable ean-5.png
+ test ean-8.png
+ test ean-13.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
+ test i2-5.png
+fi
+
+if [ "@ENABLE_QRCODE@" == "1" ]; then
+ test qr-code.png
+ test -Stest-inverted qr-code-inverted.png
+ test '--raw --oneshot -Sbinary' qr-code-binary.png
+fi
+
+if [ "@ENABLE_SQCODE@" == "1" ]; then
+ test sqcode1-generated.png
+ test sqcode1-scanned.png
+fi
+
+# The pdf417 code is incomplete: it doesn't output any results
+#
+#if [ "@ENABLE_PDF417@" == "1" ]; then
+# test code-pdf417.png
+#fi
+
+if [ "$ERR" == "" ]; then
+ echo "zbarimg PASSED."
+else
+ exit 1
+fi
+
diff --git a/test/test_gi.py b/test/test_gi.py
new file mode 100755
index 0000000..c64f574
--- /dev/null
+++ b/test/test_gi.py
@@ -0,0 +1,216 @@
+#!/usr/bin/env python3
+#------------------------------------------------------------------------
+# Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+#
+# This file is part of the ZBar Bar Code Reader.
+#
+# The ZBar Bar Code Reader is free software; you can redistribute it
+# and/or modify it under the terms of the GNU Lesser Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# The ZBar Bar Code Reader is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser Public License for more details.
+#
+# You should have received a copy of the GNU Lesser Public License
+# along with the ZBar Bar Code Reader; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# http://sourceforge.net/projects/zbar
+#------------------------------------------------------------------------
+import sys, os, stat
+
+import gi
+gi.require_version('ZBar', '1.0')
+
+try:
+ from gi.repository import ZBar, Gtk, GdkPixbuf
+except ImportError:
+ print("No ZBar integration")
+ sys.exit()
+
+# To debug vars on a interactive python3:
+# >>> import gi
+# >>> gi.require_version('ZBar', '1.0')
+# >>> from gi.repository import ZBar
+# >>> zbar = ZBar.Gtk.new()
+#
+# >>> zbar.<tab>
+
+def decoded(zbar, data):
+ """callback invoked when a barcode is decoded by the zbar widget.
+ displays the decoded data in the text box
+ """
+ buf = results.props.buffer
+ end = buf.get_end_iter()
+ buf.insert(end, data + "\n")
+ results.scroll_to_iter(end, 0, 0, 0, 0)
+
+def video_enabled(zbar, param):
+ """callback invoked when the zbar widget enables or disables
+ video streaming. updates the status button state to reflect the
+ current video state
+ """
+ enabled = zbar.get_video_enabled()
+ if status_button.get_active() != enabled:
+ status_button.set_active(enabled)
+
+def video_opened(zbar, param):
+ """callback invoked when the zbar widget opens or closes a video
+ device. also called when a device is closed due to error.
+ updates the status button state to reflect the current video state
+ """
+ opened = zbar.get_video_opened()
+ status_button.set_sensitive(opened)
+ set_status_label(opened, zbar.get_video_enabled())
+
+def video_changed(widget):
+ """callback invoked when a new video device is selected from the
+ drop-down list. sets the new device for the zbar widget,
+ which will eventually cause it to be opened and enabled
+ """
+ dev = video_list.get_active_text()
+ if dev[0] == '<':
+ dev = ''
+ zbar.set_video_device(dev)
+
+def status_button_toggled(button):
+ """callback invoked when the status button changes state
+ (interactively or programmatically). ensures the zbar widget
+ video streaming state is consistent and updates the display of the
+ button to represent the current state
+ """
+ opened = zbar.get_video_opened()
+ active = status_button.get_active()
+ if opened and (active != zbar.get_video_enabled()):
+ zbar.set_video_enabled(active)
+ set_status_label(opened, active)
+ if active:
+ status_image.set_from_icon_name("gtk-yes", Gtk.IconSize.BUTTON)
+ else:
+ status_image.set_from_icon_name("Gtk-no", Gtk.IconSize.BUTTON)
+
+def open_button_clicked(button):
+ """callback invoked when the 'Open' button is clicked. pops up an
+ 'Open File' dialog which the user may use to select an image file.
+ if the image is successfully opened, it is passed to the zbar
+ widget which displays it and scans it for barcodes. results are
+ returned using the same hook used to report video results
+ """
+ dialog = Gtk.FileChooserDialog(title = "Open Image File", parent = window,
+ action = Gtk.FileChooserAction.OPEN)
+
+ dialog.add_buttons("gtk-cancel", Gtk.ResponseType.CANCEL)
+ dialog.add_buttons("gtk-open", Gtk.ResponseType.ACCEPT)
+
+ global open_file
+ if open_file:
+ dialog.set_filename(open_file)
+ try:
+ if dialog.run() == Gtk.ResponseType.ACCEPT:
+ open_file = dialog.get_filename()
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file(open_file)
+ if pixbuf:
+ zbar.scan_image(pixbuf)
+ finally:
+ dialog.destroy()
+
+def set_status_label(opened, enabled):
+ """update status button label to reflect indicated state."""
+ if not opened:
+ label = "closed"
+ elif enabled:
+ label = "enabled"
+ else:
+ label = "disabled"
+ status_button.set_label(label)
+
+open_file = None
+video_device = None
+if len(sys.argv) > 1:
+ video_device = sys.argv[1]
+
+window = Gtk.Window()
+window.set_title("test_pygtk")
+window.set_border_width(8)
+window.connect("destroy", Gtk.main_quit)
+
+zbar = ZBar.Gtk.new()
+
+print(zbar.get_video_device())
+
+try:
+ print(zbar.get_video_device())
+except:
+ print(ZBar.get_video_device(zbar))
+
+zbar.connect("decoded-text", decoded)
+
+# video device list combo box
+video_list = Gtk.ComboBoxText()
+video_list.connect("changed", video_changed)
+
+# enable/disable status button
+status_button = Gtk.ToggleButton(name="closed")
+status_image = Gtk.Image.new_from_icon_name("gtk-no", Gtk.IconSize.BUTTON)
+status_button.set_image(status_image)
+status_button.set_sensitive(False)
+
+# bind status button state and video state
+status_button.connect("toggled", status_button_toggled)
+zbar.connect("notify::video-enabled", video_enabled)
+zbar.connect("notify::video-opened", video_opened)
+
+# open image file button
+open_button = Gtk.Button.new_with_mnemonic(label="Open")
+open_button.connect("clicked", open_button_clicked)
+
+# populate video devices in combo box
+video_list.append_text("<none>")
+video_list.set_active(0)
+for (root, dirs, files) in os.walk("/dev"):
+ for dev in files:
+ path = os.path.join(root, dev)
+ if not os.access(path, os.F_OK):
+ continue
+ info = os.stat(path)
+ if stat.S_ISCHR(info.st_mode) and os.major(info.st_rdev) == 81:
+ video_list.append_text(path)
+ if path == video_device:
+ video_list.set_active(len(video_list.get_model()) - 1)
+ video_device = None
+
+if video_device is not None:
+ video_list.append_text(video_device)
+ video_list.set_active(len(video_list.get_model()) - 1)
+ video_device = None
+
+# combine combo box and buttons horizontally
+hbox = Gtk.HBox(spacing=8)
+hbox.pack_start(video_list, True, True, 0)
+hbox.pack_start(status_button, False, True, 0)
+hbox.pack_start(open_button, False, True, 0)
+
+# text box for holding results
+results = Gtk.TextView()
+results.set_size_request(320, 64)
+results.props.editable = results.props.cursor_visible = False
+results.set_left_margin(4)
+
+# combine inputs, scanner, and results vertically
+vbox = Gtk.VBox(spacing=8)
+vbox.pack_start(hbox, False, True, 0)
+vbox.pack_start(zbar, True, True, 0)
+vbox.pack_start(results, False, True, 0)
+
+window.add(vbox)
+
+# FIXME: how to fill the geometry parameter?
+#geo = {"min_width": 320, "min_height": 240}
+#window.set_geometry_hints(geometry_widget=zbar, geometry=geo )
+window.show_all()
+
+Gtk.main()
diff --git a/test/test_images.c b/test/test_images.c
new file mode 100644
index 0000000..68a3251
--- /dev/null
+++ b/test/test_images.c
@@ -0,0 +1,533 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zbar.h>
+#include "test_images.h"
+
+typedef enum format_type_e
+{
+ GRAY,
+ YUVP,
+ YVUP,
+ YUYV,
+ YVYU,
+ UYVY,
+ RGB888,
+ BGR888,
+ RGB565B = 0x0565,
+ RGB565L = 0x1565,
+ RGB555B = 0x0555,
+ RGB555L = 0x1555,
+} format_type_t;
+
+typedef struct format_def_s {
+ uint32_t format;
+ format_type_t type;
+ uint8_t bpp;
+ uint8_t xdiv, ydiv;
+} format_def_t;
+
+typedef union packed_u {
+ uint32_t u32[3];
+ uint16_t u16[6];
+ uint8_t u8[12];
+} packed_t;
+
+/* bar colors */
+static const uint8_t Cr[] = { 0x22, 0x92, 0x80, 0xf0, 0x10, 0x80, 0x6e, 0xde };
+static const uint8_t Cb[] = { 0x36, 0x10, 0x80, 0x5a, 0xa6, 0x80, 0xf0, 0xca };
+
+static const format_def_t formats[] = {
+ { fourcc('G', 'R', 'E', 'Y'), GRAY, 8, 0, 0 },
+ { fourcc('Y', '8', '0', '0'), GRAY, 8, 0, 0 },
+ { fourcc('Y', '8', ' ', ' '), GRAY, 8, 0, 0 },
+ { fourcc('Y', '8', 0, 0), GRAY, 8, 0, 0 },
+
+ { fourcc('Y', 'U', 'V', '9'), YUVP, 9, 4, 4 },
+ { fourcc('Y', 'V', 'U', '9'), YVUP, 9, 4, 4 },
+
+ { fourcc('I', '4', '2', '0'), YUVP, 12, 2, 2 },
+ { fourcc('Y', 'U', '1', '2'), YUVP, 12, 2, 2 },
+ { fourcc('Y', 'V', '1', '2'), YVUP, 12, 2, 2 },
+ { fourcc('4', '1', '1', 'P'), YUVP, 12, 4, 1 },
+
+ { fourcc('N', 'V', '1', '2'), YUVP, 12, 2, 2 },
+ { fourcc('N', 'V', '2', '1'), YVUP, 12, 2, 2 },
+
+ { fourcc('4', '2', '2', 'P'), YUVP, 16, 2, 1 },
+
+ { fourcc('Y', 'U', 'Y', 'V'), YUYV, 16, 2, 1 },
+ { fourcc('Y', 'U', 'Y', '2'), YUYV, 16, 2, 1 },
+ { fourcc('Y', 'V', 'Y', 'U'), YVYU, 16, 2, 1 },
+ { fourcc('U', 'Y', 'V', 'Y'), UYVY, 16, 2, 1 },
+
+ {
+ fourcc('R', 'G', 'B', '3'),
+ RGB888,
+ 24,
+ },
+ {
+ fourcc('B', 'G', 'R', '3'),
+ BGR888,
+ 24,
+ },
+ {
+ fourcc(3, 0, 0, 0),
+ RGB888,
+ 32,
+ },
+ {
+ fourcc('R', 'G', 'B', '4'),
+ RGB888,
+ 32,
+ },
+ {
+ fourcc('B', 'G', 'R', '4'),
+ BGR888,
+ 32,
+ },
+ {
+ fourcc('R', 'G', 'B', 'P'),
+ RGB565L,
+ 16,
+ },
+ {
+ fourcc('R', 'G', 'B', 'O'),
+ RGB555L,
+ 16,
+ },
+ {
+ fourcc('R', 'G', 'B', 'R'),
+ RGB565B,
+ 16,
+ },
+ {
+ fourcc('R', 'G', 'B', 'Q'),
+ RGB555B,
+ 16,
+ },
+ { 0 }
+};
+
+static const char *encoded_widths =
+ "9 111 212241113121211311141132 11111 311213121312121332111132 111 9";
+const char *test_image_ean13_data = "6268964977804";
+
+static int allocated_images = 0;
+
+int test_image_check_cleanup()
+{
+ if (allocated_images)
+ fprintf(stderr, "ERROR: %d image data buffers still allocated\n",
+ allocated_images);
+ /*else
+ fprintf(stderr, "all image data buffers freed\n");*/
+ return (allocated_images);
+}
+
+static void test_cleanup_handler(zbar_image_t *img)
+{
+ void *data = (void *)zbar_image_get_data(img);
+ /*fprintf(stderr, "cleanup image data @%p\n", data);*/
+ free(data);
+ allocated_images--;
+}
+
+static inline const format_def_t *lookup_format(zbar_image_t *img)
+{
+ uint32_t ifmt = zbar_image_get_format(img);
+ const format_def_t *fmt;
+ for (fmt = formats; fmt->format; fmt++)
+ if (fmt->format == ifmt)
+ break;
+ if (!fmt->format) {
+ fprintf(stderr, "ERROR: no %.4s (%08" PRIx32 ") format\n",
+ (char *)&ifmt, ifmt);
+ return (NULL);
+ }
+ return (fmt);
+}
+
+static inline const format_def_t *alloc_data(zbar_image_t *img)
+{
+ allocated_images++;
+ const format_def_t *fmt = lookup_format(img);
+ if (!fmt)
+ return (NULL);
+
+ unsigned w = zbar_image_get_width(img);
+ unsigned h = zbar_image_get_height(img);
+ unsigned long planelen = w * h;
+ unsigned long datalen = planelen * fmt->bpp / 8;
+ uint8_t *data = malloc(datalen);
+
+ zbar_image_set_data(img, data, datalen, test_cleanup_handler);
+
+ /*fprintf(stderr, "create %.4s(%08"PRIx32") image data %lx bytes @%p\n",
+ (char*)&fmt->format, fmt->format, datalen, data);*/
+ return (fmt);
+}
+
+/* write intensity plane */
+static inline uint8_t *fill_bars_y(uint8_t *p, unsigned w, unsigned h)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0xff;
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ unsigned v = ((((i & 1) ? y : h - y) * 256) + h - 1) / h;
+ for (; x < x0; x++)
+ *(p++) = v;
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0xff;
+
+ return (p);
+}
+
+/* write Cb (U) or Cr (V) plane */
+static inline uint8_t *fill_bars_uv(uint8_t *p, unsigned w, unsigned h,
+ const uint8_t *C)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0x80;
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ for (; x < x0; x++)
+ *(p++) = C[i];
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++)
+ *(p++) = 0x80;
+
+ return (p);
+}
+
+/* write packed CbCr plane */
+static inline uint8_t *fill_bars_nv(uint8_t *p, unsigned w, unsigned h,
+ format_type_t order)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++) {
+ *(p++) = 0x80;
+ *(p++) = 0x80;
+ }
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ uint8_t u = (order == YUVP) ? Cb[i] : Cr[i];
+ uint8_t v = (order == YUVP) ? Cr[i] : Cb[i];
+ for (; x < x0; x++) {
+ *(p++) = u;
+ *(p++) = v;
+ }
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++) {
+ *(p++) = 0x80;
+ *(p++) = 0x80;
+ }
+
+ return (p);
+}
+
+/* write packed YCbCr plane */
+static inline uint8_t *fill_bars_yuv(uint8_t *p, unsigned w, unsigned h,
+ format_type_t order)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+ packed_t yuv;
+ uint32_t *q = (uint32_t *)p;
+ w /= 2;
+
+ yuv.u8[0] = yuv.u8[2] = (order == UYVY) ? 0x80 : 0xff;
+ yuv.u8[1] = yuv.u8[3] = (order == UYVY) ? 0xff : 0x80;
+ for (y = 0; y < y0; y++)
+ for (x = 0; x < w; x++)
+ *(q++) = yuv.u32[0];
+
+ for (; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ unsigned v = ((((i & 1) ? y : h - y) * 256) + h - 1) / h;
+ if (order == UYVY) {
+ yuv.u8[0] = Cb[i];
+ yuv.u8[2] = Cr[i];
+ yuv.u8[1] = yuv.u8[3] = v;
+ } else {
+ yuv.u8[0] = yuv.u8[2] = v;
+ yuv.u8[1] = (order == YUYV) ? Cb[i] : Cr[i];
+ yuv.u8[3] = (order == YVYU) ? Cr[i] : Cb[i];
+ }
+ for (; x < x0; x++)
+ *(q++) = yuv.u32[0];
+ }
+
+ yuv.u8[0] = yuv.u8[2] = (order == UYVY) ? 0x80 : 0xff;
+ yuv.u8[1] = yuv.u8[3] = (order == UYVY) ? 0xff : 0x80;
+ for (; y < h; y++)
+ for (x = 0; x < w; x++)
+ *(q++) = yuv.u32[0];
+
+ return ((uint8_t *)q);
+}
+
+static inline uint8_t *fill_bars_rgb(uint8_t *p, unsigned w, unsigned h,
+ format_type_t order, int bpp)
+{
+ unsigned x, y, i;
+ unsigned y0 = (h + 31) / 30;
+ packed_t rgb;
+
+ unsigned headlen = y0 * w * bpp / 8;
+ memset(p, 0xff, headlen);
+ uint32_t *q = (uint32_t *)(p + headlen);
+
+ for (y = y0; y < h - y0; y++)
+ for (x = 0, i = 0; x < w; i++) {
+ assert(i < 8);
+ /* FIXME clean this up... */
+ unsigned x0 = (((i + 1) * w) + 7) >> 3;
+ assert(x0 <= w);
+ unsigned yi = (i & 1) ? y : h - y;
+ unsigned v1, v0;
+ if (yi < h / 2 - 1) {
+ v1 = ((yi * 0x180) + h - 1) / h + 0x40;
+ v0 = 0x00;
+ } else {
+ v1 = 0xff;
+ v0 = (((yi - (h / 2)) * 0x180) + h - 1) / h + 0x40;
+ }
+
+ uint8_t r = (i & 4) ? v1 : v0;
+ uint8_t g = (i & 2) ? v1 : v0;
+ uint8_t b = (i & 1) ? v1 : v0;
+ if (bpp == 32) {
+ if (order == RGB888) {
+ rgb.u8[0] = 0xff;
+ rgb.u8[1] = r;
+ rgb.u8[2] = g;
+ rgb.u8[3] = b;
+ } else {
+ rgb.u8[0] = b;
+ rgb.u8[1] = g;
+ rgb.u8[2] = r;
+ rgb.u8[3] = 0xff;
+ }
+ for (; x < x0; x++)
+ *(q++) = rgb.u32[0];
+ } else if (bpp == 24) {
+ rgb.u8[0] = rgb.u8[3] = rgb.u8[6] = rgb.u8[9] =
+ (order == RGB888) ? r : b;
+ rgb.u8[1] = rgb.u8[4] = rgb.u8[7] = rgb.u8[10] = g;
+ rgb.u8[2] = rgb.u8[5] = rgb.u8[8] = rgb.u8[11] =
+ (order == RGB888) ? b : r;
+ for (; x < x0; x += 4) {
+ *(q++) = rgb.u32[0];
+ *(q++) = rgb.u32[1];
+ *(q++) = rgb.u32[2];
+ }
+ } else {
+ assert(bpp == 16);
+ r = ((r + 7) / 8) & 0x1f;
+ b = ((b + 7) / 8) & 0x1f;
+ if ((order & 0x0fff) == 0x0555) {
+ g = ((g + 7) / 8) & 0x1f;
+ rgb.u16[0] = b | (g << 5) | (r << 10);
+ } else {
+ g = ((g + 3) / 4) & 0x3f;
+ rgb.u16[0] = b | (g << 5) | (r << 11);
+ }
+ if (order & 0x1000)
+ rgb.u16[0] = (rgb.u16[0] >> 8) | (rgb.u16[0] << 8);
+ rgb.u16[1] = rgb.u16[0];
+ for (; x < x0; x += 2)
+ *(q++) = rgb.u32[0];
+ }
+ }
+
+ memset(q, 0xff, headlen);
+ return (((uint8_t *)q) + headlen);
+}
+
+int test_image_bars(zbar_image_t *img)
+{
+ const format_def_t *fmt = alloc_data(img);
+ if (!fmt)
+ return (-1);
+
+ unsigned w = zbar_image_get_width(img);
+ unsigned h = zbar_image_get_height(img);
+ uint8_t *data = (void *)zbar_image_get_data(img);
+ assert(data);
+ uint8_t *p = data;
+ switch (fmt->type) {
+ case GRAY:
+ case YUVP: /* planar YUV */
+ case YVUP:
+ p = fill_bars_y(p, w, h);
+ if (fmt->type != GRAY) {
+ w = (w + fmt->xdiv - 1) / fmt->xdiv;
+ h = (h + fmt->ydiv - 1) / fmt->ydiv;
+ } else
+ break;
+
+ if (fmt->format == fourcc('N', 'V', '1', '2') ||
+ fmt->format == fourcc('N', 'V', '2', '1'))
+ p = fill_bars_nv(p, w, h, fmt->type);
+ else if (fmt->type == YUVP || fmt->type == YVUP) {
+ p = fill_bars_uv(p, w, h, (fmt->type == YUVP) ? Cb : Cr);
+ p = fill_bars_uv(p, w, h, (fmt->type == YUVP) ? Cr : Cb);
+ }
+ break;
+
+ case YUYV: /* packed YUV */
+ case YVYU:
+ case UYVY:
+ p = fill_bars_yuv(p, w, h, fmt->type);
+ break;
+
+ default: /* RGB */
+ p = fill_bars_rgb(p, w, h, fmt->type, fmt->bpp);
+ break;
+ }
+
+ assert(p == data + zbar_image_get_data_length(img));
+ return (0);
+}
+
+int test_image_ean13(zbar_image_t *img)
+{
+ unsigned w = 114, h = 85;
+ zbar_image_set_size(img, w, h);
+
+ const format_def_t *fmt = alloc_data(img);
+ if (!fmt)
+ return (-1);
+
+ uint8_t *data = (void *)zbar_image_get_data(img);
+ unsigned int datalen = zbar_image_get_data_length(img);
+ assert(data && datalen);
+
+ uint8_t *p = data;
+ /* FIXME randomize? */
+ memset(data, 0x80, datalen);
+
+ int nrep = 1, nskip = 0;
+ switch (fmt->type) {
+ case YUVP: /* planar YUV */
+ case YVUP:
+ case GRAY:
+ break;
+
+ case UYVY: /* packed YUV */
+ p++;
+ case YUYV:
+ case YVYU:
+ nskip = 1;
+ break;
+
+ default: /* RGB */
+ nrep = fmt->bpp / 8;
+ }
+
+ int y = 0, x, i;
+ for (; y < 10 && y < h; y++)
+ for (x = 0; x < w; x++) {
+ for (i = 0; i < nrep; i++)
+ *p++ = 0xff;
+ p += nskip;
+ }
+
+ for (; y < h - 10; y++) {
+ uint8_t color = 0xff;
+ const char *c;
+ for (x = 0, c = encoded_widths; *c; c++) {
+ int dx;
+ if (*c == ' ')
+ continue;
+ for (dx = *c - '0'; dx > 0; dx--) {
+ for (i = 0; i < nrep; i++)
+ *p++ = color;
+ p += nskip;
+ x++;
+ }
+ color = ~color;
+ }
+ assert(!color);
+ for (; x < w; x++) {
+ for (i = 0; i < nrep; i++)
+ *p++ = 0xff;
+ p += nskip;
+ }
+ assert(x == w);
+ }
+
+ for (; y < h; y++)
+ for (x = 0; x < w; x++) {
+ for (i = 0; i < nrep; i++)
+ *p++ = 0xff;
+ p += nskip;
+ }
+
+ if (fmt->type == UYVY)
+ p--;
+ assert(p == data + datalen);
+ return (0);
+}
diff --git a/test/test_images.h b/test/test_images.h
new file mode 100644
index 0000000..47ead45
--- /dev/null
+++ b/test/test_images.h
@@ -0,0 +1,46 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+#ifndef _TEST_IMAGES_H_
+#define _TEST_IMAGES_H_
+
+#define fourcc zbar_fourcc
+
+#ifdef __cplusplus
+
+extern "C" {
+int test_image_check_cleanup(void);
+int test_image_bars(zbar::zbar_image_t *);
+int test_image_ean13(zbar::zbar_image_t *);
+}
+
+#else
+
+int test_image_check_cleanup(void);
+int test_image_bars(zbar_image_t *);
+int test_image_ean13(zbar_image_t *);
+
+#endif
+
+extern const char *test_image_ean13_data;
+
+#endif
diff --git a/test/test_jpeg.c b/test/test_jpeg.c
new file mode 100644
index 0000000..9e1bba6
--- /dev/null
+++ b/test/test_jpeg.c
@@ -0,0 +1,158 @@
+/*------------------------------------------------------------------------
+ * Copyright 2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#include <argp.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <zbar.h>
+
+#include "test_images.h"
+
+unsigned char jpeg[405] = {
+ 255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0,
+ 72, 0, 72, 0, 0, 255, 219, 0, 67, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255,
+ 219, 0, 67, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 255, 192, 0, 17, 8, 0, 8,
+ 0, 8, 3, 1, 17, 0, 2, 17, 1, 3, 17, 1, 255, 196, 0,
+ 20, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 7, 255, 196, 0, 32, 16, 0, 1, 2, 5, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 20, 22, 0, 8,
+ 18, 19, 24, 6, 23, 36, 37, 39, 255, 196, 0, 20, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
+ 255, 196, 0, 35, 17, 0, 2, 1, 1, 7, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 20, 21, 19, 22, 0, 1, 7, 18, 23,
+ 36, 38, 3, 4, 35, 37, 52, 255, 218, 0, 12, 3, 1, 0, 2,
+ 17, 3, 17, 0, 63, 0, 118, 93, 56, 89, 200, 157, 68, 199, 111,
+ 134, 71, 23, 12, 215, 215, 130, 197, 136, 103, 143, 117, 170, 97, 48,
+ 42, 244, 202, 12, 216, 179, 211, 183, 29, 252, 24, 42, 160, 197, 45,
+ 65, 146, 62, 181, 91, 48, 134, 52, 246, 76, 170, 151, 4, 42, 137,
+ 198, 104, 56, 214, 96, 193, 7, 120, 197, 15, 154, 194, 128, 216, 207,
+ 170, 114, 197, 220, 215, 36, 130, 123, 155, 219, 184, 172, 222, 150, 146,
+ 23, 191, 47, 17, 204, 2, 197, 155, 246, 180, 206, 226, 223, 255, 217,
+};
+
+unsigned char rgb[8 * 8 * 3] = {
+ 255, 255, 255, 176, 238, 176, 94, 220, 94, 60, 213, 60, 60, 213, 60,
+ 94, 220, 94, 176, 238, 176, 255, 255, 255, 176, 238, 176, 46, 210, 46,
+ 10, 102, 10, 17, 204, 17, 17, 204, 17, 10, 102, 10, 46, 210, 46,
+ 176, 238, 176, 94, 220, 94, 19, 204, 19, 9, 102, 9, 17, 204, 17,
+ 17, 204, 17, 9, 102, 9, 19, 204, 19, 94, 220, 94, 60, 213, 60,
+ 17, 204, 17, 9, 102, 9, 17, 204, 17, 17, 204, 17, 9, 102, 9,
+ 17, 204, 17, 60, 213, 60, 60, 213, 60, 17, 204, 17, 17, 204, 17,
+ 17, 204, 17, 17, 204, 17, 17, 204, 17, 17, 204, 17, 60, 213, 60,
+ 94, 220, 94, 10, 102, 10, 17, 204, 17, 17, 204, 17, 17, 204, 17,
+ 17, 204, 17, 10, 102, 10, 94, 220, 94, 176, 238, 176, 46, 210, 46,
+ 10, 102, 10, 9, 102, 9, 9, 102, 9, 10, 102, 10, 46, 210, 46,
+ 176, 238, 176, 255, 255, 255, 176, 238, 176, 94, 220, 94, 60, 213, 60,
+ 60, 213, 60, 94, 220, 94, 176, 238, 176, 255, 255, 255,
+};
+
+#define PROGRAM_NAME "test_video"
+
+static const char doc[] =
+ "\nTest if ZBar is able to handle a video input (camera)\n";
+
+static const struct argp_option options[] = {
+ { "quiet", 'q', 0, 0, "Don't be verbose", 0 },
+ { "help", '?', 0, 0, "Give this help list", -1 },
+ { "usage", -3, 0, 0, "Give a short usage message", 0 },
+ { 0 }
+};
+
+static int quiet = 0;
+
+static error_t parse_opt(int k, char *optarg, struct argp_state *state)
+{
+ switch (k) {
+ case 'q':
+ quiet = 1;
+ break;
+ case '?':
+ argp_state_help(state, state->out_stream,
+ ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC);
+ exit(0);
+ case -3:
+ argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
+ exit(0);
+ default:
+ return ARGP_ERR_UNKNOWN;
+ };
+ return 0;
+}
+
+static const struct argp argp = {
+ .options = options,
+ .parser = parse_opt,
+ .doc = doc,
+};
+
+int main(int argc, char **argv)
+{
+ if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0)) {
+ argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
+ return -1;
+ }
+ if (!quiet)
+ zbar_set_verbosity(32);
+ else
+ zbar_set_verbosity(0);
+
+ zbar_processor_t *proc = zbar_processor_create(0);
+ assert(proc);
+ if (zbar_processor_init(proc, NULL, 1))
+ return (2);
+
+ zbar_image_t *img = zbar_image_create();
+ zbar_image_set_size(img, 8, 8);
+ zbar_image_set_format(img, fourcc('J', 'P', 'E', 'G'));
+ zbar_image_set_data(img, jpeg, sizeof(jpeg), NULL);
+
+ zbar_image_t *test = zbar_image_convert(img, fourcc('Y', '8', '0', '0'));
+ if (!test)
+ return (2);
+ if (!quiet)
+ printf("converted: %d x %d (%lx) %08lx\n", zbar_image_get_width(test),
+ zbar_image_get_height(test), zbar_image_get_data_length(test),
+ zbar_image_get_format(test));
+
+ if (zbar_process_image(proc, test) < 0)
+ return (3);
+ if (zbar_processor_set_visible(proc, 1))
+ return (4);
+
+ printf("jpeg PASSED.\n");
+ return (0);
+}
diff --git a/test/test_perl.pl b/test/test_perl.pl
new file mode 100755
index 0000000..cc28ffb
--- /dev/null
+++ b/test/test_perl.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/env perl
+#------------------------------------------------------------------------
+# Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+#
+# This file is part of the ZBar Bar Code Reader.
+#
+# The ZBar Bar Code Reader is free software; you can redistribute it
+# and/or modify it under the terms of the GNU Lesser Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# The ZBar Bar Code Reader is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser Public License for more details.
+#
+# You should have received a copy of the GNU Lesser Public License
+# along with the ZBar Bar Code Reader; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# http://sourceforge.net/projects/zbar
+#------------------------------------------------------------------------
+
+use 5.006;
+use warnings;
+use strict;
+
+use Barcode::ZBar;
+
+Barcode::ZBar::set_verbosity(15);
+
+my $proc = Barcode::ZBar::Processor->new(1);
+
+$proc->init($ARGV[0] || '/dev/video0');
+
+$proc->set_visible();
+$proc->user_wait(2);
+
+$proc->set_active();
+$proc->user_wait(5);
+
+$proc->set_active(0);
+$proc->user_wait(2);
+
+$proc->process_one();
+$proc->user_wait(1);
diff --git a/test/test_proc.c b/test/test_proc.c
new file mode 100644
index 0000000..46eb992
--- /dev/null
+++ b/test/test_proc.c
@@ -0,0 +1,170 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <zbar.h>
+#include "test_images.h"
+
+zbar_processor_t *proc = NULL;
+int use_threads = 1, use_window = 1;
+
+int input_wait(int timeout)
+{
+ if (timeout >= 0)
+ fprintf(stderr, "waiting %d.%03ds for input...", timeout / 1000,
+ timeout % 1000);
+ else
+ fprintf(stderr, "waiting indefinitely for input...");
+ fflush(stderr);
+ int rc = zbar_processor_user_wait(proc, timeout);
+ if (rc > 0)
+ fprintf(stderr, "got input (%02x)\n", rc);
+ else if (!rc)
+ fprintf(stderr, "timed out\n");
+ else if (zbar_processor_get_error_code(proc) == ZBAR_ERR_CLOSED)
+ use_window = rc = 0;
+ fflush(stderr);
+ return (rc);
+}
+
+int main(int argc, char **argv)
+{
+ zbar_set_verbosity(127);
+ char *video_dev = NULL;
+ uint32_t fmt = 0;
+ int i, j = 0;
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (!strncmp(argv[i], "-thr", 4))
+ use_threads = 0;
+ else if (!strncmp(argv[i], "-win", 4))
+ use_window = 0;
+ else
+ return (1);
+ } else if (!j++)
+ video_dev = argv[i];
+ else if (j++ == 1) {
+ int n = strlen(argv[i]);
+ if (n > 4)
+ n = 4;
+ memcpy((char *)&fmt, argv[i], n);
+ }
+ }
+ if (!fmt)
+ fmt = fourcc('B', 'G', 'R', '3');
+
+ proc = zbar_processor_create(use_threads);
+ assert(proc);
+ fprintf(stderr, "created processor (%sthreaded)\n",
+ (!use_threads) ? "un" : "");
+ fflush(stderr);
+
+ if (zbar_processor_init(proc, NULL, 0))
+ return (2);
+ fprintf(stderr, "initialized (video=disabled, window=disabled)\n");
+ fflush(stderr);
+
+ zbar_image_t *img = zbar_image_create();
+ zbar_image_set_size(img, 640, 480);
+ zbar_image_set_format(img, fmt);
+ test_image_bars(img);
+
+ if (zbar_process_image(proc, img) < 0)
+ return (3);
+ fprintf(stderr, "processed test image\n");
+ fflush(stderr);
+
+ if (zbar_processor_init(proc, video_dev, use_window))
+ return (2);
+ fprintf(stderr, "reinitialized (video=%s, window=%s)\n",
+ (video_dev) ? video_dev : "disabled",
+ (use_window) ? "enabled" : "disabled");
+ fflush(stderr);
+
+ if (use_window) {
+ if (zbar_processor_set_visible(proc, 1))
+ return (4);
+ fprintf(stderr, "window visible\n");
+ fflush(stderr);
+ }
+
+ if (input_wait((use_window && !video_dev) ? -1 : 2000) < 0)
+ return (5);
+
+ if (zbar_process_image(proc, img) < 0)
+ return (3);
+ fprintf(stderr, "processed test image\n");
+ fflush(stderr);
+ zbar_image_destroy(img);
+
+ if (input_wait((use_window && !video_dev) ? -1 : 3333) < 0)
+ return (5);
+
+ if (video_dev) {
+ if (zbar_processor_set_active(proc, 1))
+ return (3);
+ fprintf(stderr, "video activated\n");
+ fflush(stderr);
+
+ if (input_wait((use_window) ? -1 : 4000) < 0)
+ return (5);
+
+ if (zbar_processor_set_active(proc, 0))
+ return (3);
+ fprintf(stderr, "video deactivated\n");
+ fflush(stderr);
+
+ if (input_wait((use_window) ? -1 : 4000) < 0)
+ return (5);
+
+ /* FIXME test process_one() */
+ }
+
+ if (zbar_process_image(proc, NULL))
+ return (3);
+ fprintf(stderr, "flushed image\n");
+ fflush(stderr);
+
+ if (input_wait((use_window && !video_dev) ? -1 : 2500) < 0)
+ return (5);
+
+ fprintf(stderr, "cleaning up...\n");
+ fflush(stderr);
+
+ zbar_processor_destroy(proc);
+ proc = NULL;
+ if (test_image_check_cleanup())
+ return (32);
+ return (0);
+}
diff --git a/test/test_pygtk.py b/test/test_pygtk.py
new file mode 100755
index 0000000..fc19fa9
--- /dev/null
+++ b/test/test_pygtk.py
@@ -0,0 +1,193 @@
+#!/usr/bin/env python2
+#------------------------------------------------------------------------
+# Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+#
+# This file is part of the ZBar Bar Code Reader.
+#
+# The ZBar Bar Code Reader is free software; you can redistribute it
+# and/or modify it under the terms of the GNU Lesser Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# The ZBar Bar Code Reader is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser Public License for more details.
+#
+# You should have received a copy of the GNU Lesser Public License
+# along with the ZBar Bar Code Reader; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# http://sourceforge.net/projects/zbar
+#------------------------------------------------------------------------
+import sys, os, stat
+import pygtk, gtk
+import zbarpygtk
+
+def decoded(zbar, data):
+ """callback invoked when a barcode is decoded by the zbar widget.
+ displays the decoded data in the text box
+ """
+ buf = results.props.buffer
+ end = buf.get_end_iter()
+ buf.insert(end, data + "\n")
+ results.scroll_to_iter(end, 0)
+
+def video_enabled(zbar, param):
+ """callback invoked when the zbar widget enables or disables
+ video streaming. updates the status button state to reflect the
+ current video state
+ """
+ enabled = zbar.get_video_enabled()
+ if status_button.get_active() != enabled:
+ status_button.set_active(enabled)
+
+def video_opened(zbar, param):
+ """callback invoked when the zbar widget opens or closes a video
+ device. also called when a device is closed due to error.
+ updates the status button state to reflect the current video state
+ """
+ opened = zbar.get_video_opened()
+ status_button.set_sensitive(opened)
+ set_status_label(opened, zbar.get_video_enabled())
+
+def video_changed(widget):
+ """callback invoked when a new video device is selected from the
+ drop-down list. sets the new device for the zbar widget,
+ which will eventually cause it to be opened and enabled
+ """
+ dev = video_list.get_active_text()
+ if dev[0] == '<':
+ dev = ''
+ zbar.set_video_device(dev)
+
+def status_button_toggled(button):
+ """callback invoked when the status button changes state
+ (interactively or programmatically). ensures the zbar widget
+ video streaming state is consistent and updates the display of the
+ button to represent the current state
+ """
+ opened = zbar.get_video_opened()
+ active = status_button.get_active()
+ if opened and (active != zbar.get_video_enabled()):
+ zbar.set_video_enabled(active)
+ set_status_label(opened, active)
+ if active:
+ status_image.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON)
+ else:
+ status_image.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_BUTTON)
+
+def open_button_clicked(button):
+ """callback invoked when the 'Open' button is clicked. pops up an
+ 'Open File' dialog which the user may use to select an image file.
+ if the image is successfully opened, it is passed to the zbar
+ widget which displays it and scans it for barcodes. results are
+ returned using the same hook used to report video results
+ """
+ dialog = gtk.FileChooserDialog("Open Image File", window,
+ gtk.FILE_CHOOSER_ACTION_OPEN,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT))
+ global open_file
+ if open_file:
+ dialog.set_filename(open_file)
+ try:
+ if dialog.run() == gtk.RESPONSE_ACCEPT:
+ open_file = dialog.get_filename()
+ pixbuf = gtk.gdk.pixbuf_new_from_file(open_file)
+ if pixbuf:
+ zbar.scan_image(pixbuf)
+ finally:
+ dialog.destroy()
+
+def set_status_label(opened, enabled):
+ """update status button label to reflect indicated state."""
+ if not opened:
+ label = "closed"
+ elif enabled:
+ label = "enabled"
+ else:
+ label = "disabled"
+ status_button.set_label(label)
+
+open_file = None
+video_device = None
+if len(sys.argv) > 1:
+ video_device = sys.argv[1]
+
+# threads *must* be properly initialized to use zbarpygtk
+gtk.gdk.threads_init()
+gtk.gdk.threads_enter()
+
+window = gtk.Window()
+window.set_title("test_pygtk")
+window.set_border_width(8)
+window.connect("destroy", gtk.main_quit)
+
+zbar = zbarpygtk.Gtk()
+zbar.connect("decoded-text", decoded)
+
+# video device list combo box
+video_list = gtk.combo_box_new_text()
+video_list.connect("changed", video_changed)
+
+# enable/disable status button
+status_button = gtk.ToggleButton("closed")
+status_image = gtk.image_new_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_BUTTON)
+status_button.set_image(status_image)
+status_button.set_sensitive(False)
+
+# bind status button state and video state
+status_button.connect("toggled", status_button_toggled)
+zbar.connect("notify::video-enabled", video_enabled)
+zbar.connect("notify::video-opened", video_opened)
+
+# open image file button
+open_button = gtk.Button(stock=gtk.STOCK_OPEN)
+open_button.connect("clicked", open_button_clicked)
+
+# populate video devices in combo box
+video_list.append_text("<none>")
+video_list.set_active(0)
+for (root, dirs, files) in os.walk("/dev"):
+ for dev in files:
+ path = os.path.join(root, dev)
+ if not os.access(path, os.F_OK):
+ continue
+ info = os.stat(path)
+ if stat.S_ISCHR(info.st_mode) and os.major(info.st_rdev) == 81:
+ video_list.append_text(path)
+ if path == video_device:
+ video_list.set_active(len(video_list.get_model()) - 1)
+ video_device = None
+
+if video_device is not None:
+ video_list.append_text(video_device)
+ video_list.set_active(len(video_list.get_model()) - 1)
+ video_device = None
+
+# combine combo box and buttons horizontally
+hbox = gtk.HBox(spacing=8)
+hbox.pack_start(video_list)
+hbox.pack_start(status_button, expand=False)
+hbox.pack_start(open_button, expand=False)
+
+# text box for holding results
+results = gtk.TextView()
+results.set_size_request(320, 64)
+results.props.editable = results.props.cursor_visible = False
+results.set_left_margin(4)
+
+# combine inputs, scanner, and results vertically
+vbox = gtk.VBox(spacing=8)
+vbox.pack_start(hbox, expand=False)
+vbox.pack_start(zbar)
+vbox.pack_start(results, expand=False)
+
+window.add(vbox)
+window.set_geometry_hints(zbar, min_width=320, min_height=240)
+window.show_all()
+
+gtk.main()
+gtk.gdk.threads_leave()
diff --git a/test/test_python.py b/test/test_python.py
new file mode 100755
index 0000000..7ffdf9f
--- /dev/null
+++ b/test/test_python.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+#------------------------------------------------------------------------
+# Copyright 2019 (c) Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+#
+# This file is part of the ZBar Bar Code Reader.
+#
+# The ZBar Bar Code Reader is free software; you can redistribute it
+# and/or modify it under the terms of the GNU Lesser Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# The ZBar Bar Code Reader is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser Public License for more details.
+#
+#------------------------------------------------------------------------
+
+from __future__ import print_function
+import zbar, sys
+
+try:
+ from PIL import Image
+except:
+ try:
+ import Image
+ except:
+ print("No image library on python. Aborting test")
+ sys.exit()
+
+if len(sys.argv) < 1 or len(sys.argv) > 3:
+ print("Usage: %s <file name> [<expected text to check>]")
+ sys.exit(-1)
+
+filename = sys.argv[1]
+
+org_image = Image.open(filename)
+
+image = org_image.convert(mode='L')
+
+width = image.size[0]
+height = image.size[1]
+raw_data = image.tobytes()
+
+scanner = zbar.ImageScanner()
+image = zbar.Image(width=width, height=height, format='Y800', data=raw_data)
+scanner.scan(image)
+
+if len(sys.argv) == 3:
+ text = sys.argv[2]
+
+ found = False
+ for symbol in image:
+ found = True
+ if symbol.data == text:
+ print("OK")
+ else:
+ print("Expecting %s, received %s" % (text, symbol.data))
+
+ if not found:
+ print("Can't process file")
+else:
+ for symbol in image:
+ print("Decoded as %s" % symbol.data)
diff --git a/test/test_video.c b/test/test_video.c
new file mode 100644
index 0000000..b8618d6
--- /dev/null
+++ b/test/test_video.c
@@ -0,0 +1,237 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#include <argp.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <assert.h>
+
+#include <zbar.h>
+#include "test_images.h"
+
+#ifdef _WIN32
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+
+zbar_video_t *video;
+
+#define PROGRAM_NAME "test_video"
+
+static const char doc[] =
+ "\nTest if ZBar is able to handle a video input (camera)\n";
+
+static const struct argp_option options[] = {
+ { "quiet", 'q', 0, 0, "Don't be verbose", 0 },
+ { "dev", 'd', "devnode", 0, "open devnode for video in", 0 },
+ { "format", 'f', "fourcc", 0, "Stop after #seconds", 0 },
+ { "help", '?', 0, 0, "Give this help list", -1 },
+ { "usage", -3, 0, 0, "Give a short usage message", 0 },
+ { 0 }
+};
+
+static int quiet = 0;
+uint32_t vidfmt = fourcc('B', 'G', 'R', '3');
+char *dev = "";
+
+static error_t parse_opt(int k, char *optarg, struct argp_state *state)
+{
+ switch (k) {
+ case 'q':
+ quiet = 1;
+ break;
+ case 'f': {
+ int len = strlen(optarg);
+ if (len > 4)
+ len = 4;
+ memcpy((char *)&vidfmt, optarg, len);
+ if (len < 4)
+ memset(len + (char *)&vidfmt, 0, 4 - len);
+ break;
+ }
+ case 'd':
+ dev = optarg;
+ break;
+ case '?':
+ argp_state_help(state, state->out_stream,
+ ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_DOC);
+ exit(0);
+ case -3:
+ argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
+ exit(0);
+ default:
+ return ARGP_ERR_UNKNOWN;
+ };
+ return 0;
+}
+
+static const struct argp argp = {
+ .options = options,
+ .parser = parse_opt,
+ .doc = doc,
+};
+
+int main(int argc, char *argv[])
+{
+ if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0)) {
+ argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
+ return -1;
+ }
+ if (!quiet)
+ zbar_set_verbosity(31);
+ else
+ zbar_set_verbosity(0);
+
+ video = zbar_video_create();
+ if (!video) {
+ fprintf(stderr, "unable to allocate memory?!\n");
+ return (1);
+ }
+
+ zbar_video_request_size(video, 640, 480);
+
+ if (zbar_video_open(video, dev)) {
+ zbar_video_error_spew(video, 0);
+ fprintf(stderr,
+ "ERROR: unable to access your video device\n"
+ "this program requires video capture support using"
+ " v4l version 1 or 2 or VfW\n"
+ " - is your video device located at \"%s\"?\n"
+ " - is your video driver installed? (check dmesg)\n"
+ " - make sure you have the latest drivers\n"
+ " - do you have read/write permission to access it?\n"
+ " - is another application is using it?\n"
+ " - does the device support video capture?\n"
+ " - does the device work with other programs?\n",
+ dev);
+ return (1);
+ }
+ if (!quiet) {
+ fprintf(stderr, "opened video device: %s (fd=%d)\n", dev,
+ zbar_video_get_fd(video));
+ fflush(stderr);
+ }
+
+ if (zbar_video_init(video, vidfmt)) {
+ fprintf(stderr, "ERROR: failed to set format: %.4s(%08x)\n",
+ (char *)&vidfmt, vidfmt);
+ return (zbar_video_error_spew(video, 0));
+ }
+
+ if (zbar_video_enable(video, 1)) {
+ fprintf(stderr, "ERROR: starting video stream\n");
+ return (zbar_video_error_spew(video, 0));
+ }
+ if (!quiet) {
+ fprintf(stderr, "started video stream...\n");
+ fflush(stderr);
+ }
+
+ zbar_image_t *image = zbar_video_next_image(video);
+ if (!image) {
+ fprintf(stderr, "ERROR: unable to capture image\n");
+ return (zbar_video_error_spew(video, 0));
+ }
+ uint32_t format = zbar_image_get_format(image);
+ unsigned width = zbar_image_get_width(image);
+ unsigned height = zbar_image_get_height(image);
+ const uint8_t *data = zbar_image_get_data(image);
+ if (!quiet) {
+ fprintf(stderr, "captured image: %d x %d %.4s @%p\n", width, height,
+ (char *)&format, data);
+ fflush(stderr);
+ }
+
+ zbar_image_destroy(image);
+
+ if (!quiet) {
+ fprintf(stderr, "\nstreaming 100 frames...\n");
+ fflush(stderr);
+ }
+
+ struct timespec start, end;
+#if _POSIX_TIMERS > 0
+ clock_gettime(CLOCK_REALTIME, &start);
+#else
+ struct timeval ustime;
+ gettimeofday(&ustime, NULL);
+ start.tv_nsec = ustime.tv_usec * 1000;
+ start.tv_sec = ustime.tv_sec;
+#endif
+
+ int i;
+ for (i = 0; i < 100; i++) {
+ zbar_image_t *image = zbar_video_next_image(video);
+ if (!image) {
+ fprintf(stderr, "ERROR: unable to capture image\n");
+ return (zbar_video_error_spew(video, 0));
+ }
+ zbar_image_destroy(image);
+ }
+
+#if _POSIX_TIMERS > 0
+ clock_gettime(CLOCK_REALTIME, &end);
+#else
+ gettimeofday(&ustime, NULL);
+ end.tv_nsec = ustime.tv_usec * 1000;
+ end.tv_sec = ustime.tv_sec;
+#endif
+ double ms = (end.tv_sec - start.tv_sec +
+ (end.tv_nsec - start.tv_nsec) / 1000000000.);
+ double fps = i / ms;
+ if (!quiet) {
+ fprintf(stderr, "\nprocessed %d images in %gs @%gfps\n", i, ms, fps);
+ fflush(stderr);
+ }
+
+ if (zbar_video_enable(video, 0)) {
+ fprintf(stderr, "ERROR: while stopping video stream\n");
+ return (zbar_video_error_spew(video, 0));
+ }
+
+ if (!quiet) {
+ fprintf(stderr, "\ncleaning up...\n");
+ fflush(stderr);
+ }
+
+ zbar_video_destroy(video);
+
+ if (test_image_check_cleanup())
+ return (32);
+
+ fprintf(stderr, "video PASSED.\n");
+ return (0);
+}
diff --git a/test/test_window.c b/test/test_window.c
new file mode 100644
index 0000000..894c8af
--- /dev/null
+++ b/test/test_window.c
@@ -0,0 +1,98 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include <zbar.h>
+#include "processor.h"
+#include "test_images.h"
+
+zbar_processor_t proc;
+
+static void input_wait()
+{
+ fprintf(stderr, "waiting for input...\n");
+ if (_zbar_window_handle_events(&proc, 1) < 0)
+ zbar_processor_error_spew(&proc, 1);
+}
+
+int main(int argc, char *argv[])
+{
+ zbar_set_verbosity(32);
+
+ err_init(&proc.err, ZBAR_MOD_PROCESSOR);
+ proc.window = zbar_window_create();
+ if (!proc.window) {
+ fprintf(stderr, "unable to allocate memory?!\n");
+ return (1);
+ }
+
+ int width = 640;
+ int height = 480;
+
+ if (_zbar_window_open(&proc, "zbar window test", width, height) ||
+ zbar_window_attach(proc.window, proc.display, proc.xwin) ||
+ _zbar_window_set_visible(&proc, 1)) {
+ fprintf(stderr, "failed to open test window\n");
+ return (1);
+ }
+ input_wait();
+
+ zbar_image_t *img = zbar_image_create();
+ zbar_image_set_size(img, width, height);
+ zbar_image_set_format(img, fourcc('B', 'G', 'R', '4'));
+ /*fourcc('I','4','2','0')*/
+ /*fourcc('Y','V','1','2')*/
+ /*fourcc('U','Y','V','Y')*/
+ /*fourcc('Y','U','Y','V')*/
+ /*fourcc('R','G','B','3')*/
+ /*fourcc('Y','8','0','0')*/
+ test_image_bars(img);
+
+ if (zbar_window_draw(proc.window, img) || zbar_window_redraw(proc.window)) {
+ fprintf(stderr, "error drawing image\n");
+ return (1);
+ }
+ zbar_image_destroy(img);
+ img = NULL;
+
+ input_wait();
+
+ /* FIXME display cmd arg images? or formats? */
+
+ fprintf(stderr, "cleaning up\n");
+ zbar_window_destroy(proc.window);
+
+ /* FIXME destructor check? */
+ if (test_image_check_cleanup())
+ return (32);
+ return (0);
+}