summaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 00:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 00:06:44 +0000
commit44cf8ec67278bd1ab6c7f83a9993f7a5686a9541 (patch)
tree5eec4b0d1a3f163d279c3c27c03324ba49fa235a /python
parentInitial commit. (diff)
downloadzbar-44cf8ec67278bd1ab6c7f83a9993f7a5686a9541.tar.xz
zbar-44cf8ec67278bd1ab6c7f83a9993f7a5686a9541.zip
Adding upstream version 0.23.93.upstream/0.23.93upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'python')
-rw-r--r--python/MANIFEST.in2
-rw-r--r--python/Makefile.am.inc13
-rw-r--r--python/README60
-rw-r--r--python/decoder.c360
-rw-r--r--python/enum.c259
-rw-r--r--python/examples/processor.py35
-rw-r--r--python/examples/read_one.py29
-rw-r--r--python/examples/scan_image.py31
-rw-r--r--python/exception.c123
-rw-r--r--python/image.c482
-rw-r--r--python/imagescanner.c195
-rw-r--r--python/processor.c456
-rw-r--r--python/scanner.c193
-rw-r--r--python/setup.py45
-rw-r--r--python/symbol.c230
-rw-r--r--python/symboliter.c103
-rw-r--r--python/symbolset.c85
-rw-r--r--python/test/barcode.pngbin0 -> 1182 bytes
-rwxr-xr-xpython/test/test_zbar.py506
-rw-r--r--python/zbarmodule.c340
-rw-r--r--python/zbarmodule.h164
21 files changed, 3711 insertions, 0 deletions
diff --git a/python/MANIFEST.in b/python/MANIFEST.in
new file mode 100644
index 0000000..93acc53
--- /dev/null
+++ b/python/MANIFEST.in
@@ -0,0 +1,2 @@
+include MANIFEST MANIFEST.in zbarmodule.h test/barcode.png
+recursive-include examples *.py
diff --git a/python/Makefile.am.inc b/python/Makefile.am.inc
new file mode 100644
index 0000000..f1f30a4
--- /dev/null
+++ b/python/Makefile.am.inc
@@ -0,0 +1,13 @@
+pyexec_LTLIBRARIES += python/zbar.la
+python_zbar_la_CPPFLAGS = $(PYTHON_CFLAGS) $(AM_CPPFLAGS)
+python_zbar_la_LDFLAGS = -shared -module -avoid-version -export-dynamic \
+ -export-symbols-regex '(initzbar|PyInit_zbar)' $(PYTHON_LDFLAGS)
+python_zbar_la_LIBADD = zbar/libzbar.la $(AM_LIBADD)
+
+python_zbar_la_SOURCES = python/zbarmodule.c python/zbarmodule.h \
+ python/enum.c python/exception.c python/symbol.c python/symbolset.c \
+ python/symboliter.c python/image.c \
+ python/processor.c python/imagescanner.c python/decoder.c python/scanner.c
+
+EXTRA_DIST += python/test/barcode.png python/test/test_zbar.py \
+ python/examples/processor.py python/examples/read_one.py
diff --git a/python/README b/python/README
new file mode 100644
index 0000000..876b0c3
--- /dev/null
+++ b/python/README
@@ -0,0 +1,60 @@
+==========================================
+zbar -- read barcodes from images or video
+==========================================
+
+ZBar Bar Code Reader is an open source software suite for reading bar
+codes from various sources, such as video streams, image files and raw
+intensity sensors. It supports EAN-13/UPC-A, UPC-E, EAN-8, Code 128,
+Code 93, Code 39, Codabar, Interleaved 2 of 5 and QR Code. These are
+the Python bindings for the library.
+
+Check the ZBar project home page for the latest release, mailing
+lists, etc.
+
+* https://github.com/mchehab/zbar
+
+Installation
+------------
+
+To install this module type the following::
+
+ python setup.py install
+
+Dependencies
+------------
+
+This module requires the ZBar Bar Code Reader, which may be obtained
+from:
+
+* https://github.com/mchehab/zbar
+
+Windows users please note: the module *will NOT load* unless the ZBar
+library DLL (currently libzbar-0.dll) is available in your Windows system
+PATH!
+
+Examples
+--------
+
+To scan an image, wrap the raw image data in a ``zbar.Image`` and feed
+it to a ``zbar.ImageScanner``::
+
+ import zbar
+ scanner = zbar.ImageScanner()
+ image = zbar.Image(width, height, 'Y800', raw_data)
+ scanner.scan(image)
+ for symbol in image:
+ print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data
+
+Complete, runnable examples may be found in the source distribution,
+under the ``examples/`` directory. A couple of HOWTOs_ that cover
+programming with the library may be found on the project wiki.
+
+.. _HOWTOs: http://sourceforge.net/apps/mediawiki/zbar/index.php?title=Category:HOWTOs
+
+Copyright and License
+---------------------
+
+Licensed under the GNU Lesser General Public License, version 2.1.
+http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
+
+Copyright 2008-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
diff --git a/python/decoder.c b/python/decoder.c
new file mode 100644
index 0000000..e75ee9f
--- /dev/null
+++ b/python/decoder.c
@@ -0,0 +1,360 @@
+/*------------------------------------------------------------------------
+ * Copyright 2009-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
+ *------------------------------------------------------------------------*/
+
+#include "zbarmodule.h"
+
+static char decoder_doc[] =
+ PyDoc_STR("low level decode of measured bar/space widths.\n"
+ "\n"
+ "FIXME.");
+
+static zbarDecoder *decoder_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ static char *kwlist[] = { NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
+ return (NULL);
+
+ zbarDecoder *self = (zbarDecoder *)type->tp_alloc(type, 0);
+ if (!self)
+ return (NULL);
+
+ self->zdcode = zbar_decoder_create();
+ zbar_decoder_set_userdata(self->zdcode, self);
+ if (!self->zdcode) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+
+ return (self);
+}
+
+static int decoder_traverse(zbarDecoder *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->handler);
+ Py_VISIT(self->args);
+ return (0);
+}
+
+static int decoder_clear(zbarDecoder *self)
+{
+ zbar_decoder_set_handler(self->zdcode, NULL);
+ zbar_decoder_set_userdata(self->zdcode, NULL);
+ Py_CLEAR(self->handler);
+ Py_CLEAR(self->args);
+ return (0);
+}
+
+static void decoder_dealloc(zbarDecoder *self)
+{
+ decoder_clear(self);
+ zbar_decoder_destroy(self->zdcode);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static zbarEnumItem *decoder_get_color(zbarDecoder *self, void *closure)
+{
+ zbar_color_t zcol = zbar_decoder_get_color(self->zdcode);
+ assert(zcol == ZBAR_BAR || zcol == ZBAR_SPACE);
+
+ struct module_state *st = GETMODSTATE();
+ zbarEnumItem *color = st->color_enum[zcol];
+ Py_INCREF((PyObject *)color);
+ return (color);
+}
+
+static zbarEnumItem *decoder_get_type(zbarDecoder *self, void *closure)
+{
+ zbar_symbol_type_t sym = zbar_decoder_get_type(self->zdcode);
+ if (sym == ZBAR_NONE) {
+ /* hardcode most common case */
+ struct module_state *st = GETMODSTATE();
+ Py_INCREF((PyObject *)st->symbol_NONE);
+ return (st->symbol_NONE);
+ }
+ return (zbarSymbol_LookupEnum(sym));
+}
+
+static PyObject *decoder_get_configs(zbarDecoder *self, void *closure)
+{
+ struct module_state *st = GETMODSTATE();
+ unsigned int sym = zbar_decoder_get_type(self->zdcode);
+ unsigned int mask = zbar_decoder_get_configs(self->zdcode, sym);
+ return (zbarEnum_SetFromMask(st->config_enum, mask));
+}
+
+static PyObject *decoder_get_modifiers(zbarDecoder *self, void *closure)
+{
+ unsigned int mask = zbar_decoder_get_modifiers(self->zdcode);
+ struct module_state *st = GETMODSTATE();
+ return (zbarEnum_SetFromMask(st->modifier_enum, mask));
+}
+
+static PyObject *decoder_get_data(zbarDecoder *self, void *closure)
+{
+#if PY_MAJOR_VERSION >= 3
+ return (PyUnicode_FromStringAndSize(zbar_decoder_get_data(self->zdcode),
+ zbar_decoder_get_data_length(
+ self->zdcode)));
+#else
+ return (
+ PyString_FromStringAndSize(zbar_decoder_get_data(self->zdcode),
+ zbar_decoder_get_data_length(self->zdcode)));
+#endif
+}
+
+static PyObject *decoder_get_direction(zbarDecoder *self, void *closure)
+{
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(zbar_decoder_get_direction(self->zdcode)));
+#else
+ return (PyInt_FromLong(zbar_decoder_get_direction(self->zdcode)));
+#endif
+}
+
+static PyGetSetDef decoder_getset[] = {
+ {
+ "color",
+ (getter)decoder_get_color,
+ },
+ {
+ "type",
+ (getter)decoder_get_type,
+ },
+ {
+ "configs",
+ (getter)decoder_get_configs,
+ },
+ {
+ "modifiers",
+ (getter)decoder_get_modifiers,
+ },
+ {
+ "data",
+ (getter)decoder_get_data,
+ },
+ { "direction", (getter)decoder_get_direction },
+ {
+ NULL,
+ },
+};
+
+static PyObject *decoder_set_config(zbarDecoder *self, PyObject *args,
+ PyObject *kwds)
+{
+ zbar_symbol_type_t sym = ZBAR_NONE;
+ zbar_config_t cfg = ZBAR_CFG_ENABLE;
+ int val = 1;
+ static char *kwlist[] = { "symbology", "config", "value", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &sym, &cfg,
+ &val))
+ return (NULL);
+
+ if (zbar_decoder_set_config(self->zdcode, sym, cfg, val)) {
+ PyErr_SetString(PyExc_ValueError, "invalid configuration setting");
+ return (NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *decoder_get_configs_meth(zbarDecoder *self, PyObject *args,
+ PyObject *kwds)
+{
+ zbar_symbol_type_t sym = ZBAR_NONE;
+ static char *kwlist[] = { "symbology", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &sym))
+ return (NULL);
+
+ if (sym == ZBAR_NONE)
+ sym = zbar_decoder_get_type(self->zdcode);
+
+ struct module_state *st = GETMODSTATE();
+ unsigned int mask = zbar_decoder_get_configs(self->zdcode, sym);
+ return (zbarEnum_SetFromMask(st->config_enum, mask));
+}
+
+static PyObject *decoder_parse_config(zbarDecoder *self, PyObject *args,
+ PyObject *kwds)
+{
+ const char *cfg = NULL;
+ static char *kwlist[] = { "config", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cfg))
+ return (NULL);
+
+ if (zbar_decoder_parse_config(self->zdcode, cfg)) {
+ PyErr_Format(PyExc_ValueError, "invalid configuration setting: %s",
+ cfg);
+ return (NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *decoder_reset(zbarDecoder *self, PyObject *args,
+ PyObject *kwds)
+{
+ static char *kwlist[] = { NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
+ return (NULL);
+
+ zbar_decoder_reset(self->zdcode);
+ Py_RETURN_NONE;
+}
+
+static PyObject *decoder_new_scan(zbarDecoder *self, PyObject *args,
+ PyObject *kwds)
+{
+ static char *kwlist[] = { NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
+ return (NULL);
+
+ zbar_decoder_new_scan(self->zdcode);
+ Py_RETURN_NONE;
+}
+
+void decode_handler(zbar_decoder_t *zdcode)
+{
+ assert(zdcode);
+ zbarDecoder *self = zbar_decoder_get_userdata(zdcode);
+ assert(self);
+ assert(self->zdcode == zdcode);
+ assert(self->handler);
+ assert(self->args);
+ PyObject *junk = PyObject_Call(self->handler, self->args, NULL);
+ Py_XDECREF(junk);
+}
+
+static PyObject *decoder_set_handler(zbarDecoder *self, PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *handler = Py_None;
+ PyObject *closure = Py_None;
+
+ static char *kwlist[] = { "handler", "closure", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &handler,
+ &closure))
+ return (NULL);
+
+ if (handler != Py_None && !PyCallable_Check(handler)) {
+ PyErr_Format(PyExc_ValueError, "handler %.50s is not callable",
+ handler->ob_type->tp_name);
+ return (NULL);
+ }
+ Py_CLEAR(self->handler);
+ Py_CLEAR(self->args);
+
+ if (handler != Py_None) {
+ self->args = PyTuple_New(2);
+ if (!self->args)
+ return (NULL);
+ Py_INCREF(self);
+ Py_INCREF(closure);
+ PyTuple_SET_ITEM(self->args, 0, (PyObject *)self);
+ PyTuple_SET_ITEM(self->args, 1, closure);
+
+ Py_INCREF(handler);
+ self->handler = handler;
+
+ zbar_decoder_set_handler(self->zdcode, decode_handler);
+ } else {
+ self->handler = self->args = NULL;
+ zbar_decoder_set_handler(self->zdcode, NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static zbarEnumItem *decoder_decode_width(zbarDecoder *self, PyObject *args,
+ PyObject *kwds)
+{
+ unsigned int width = 0;
+ static char *kwlist[] = { "width", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &width))
+ return (NULL);
+
+ zbar_symbol_type_t sym = zbar_decode_width(self->zdcode, width);
+ if (PyErr_Occurred())
+ /* propagate errors during callback */
+ return (NULL);
+ if (sym == ZBAR_NONE) {
+ /* hardcode most common case */
+ struct module_state *st = GETMODSTATE();
+ Py_INCREF((PyObject *)st->symbol_NONE);
+ return (st->symbol_NONE);
+ }
+ return (zbarSymbol_LookupEnum(sym));
+}
+
+static PyMethodDef decoder_methods[] = {
+ {
+ "set_config",
+ (PyCFunction)decoder_set_config,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "get_configs",
+ (PyCFunction)decoder_get_configs_meth,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "parse_config",
+ (PyCFunction)decoder_parse_config,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "reset",
+ (PyCFunction)decoder_reset,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "new_scan",
+ (PyCFunction)decoder_new_scan,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "set_handler",
+ (PyCFunction)decoder_set_handler,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "decode_width",
+ (PyCFunction)decoder_decode_width,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ NULL,
+ },
+};
+
+PyTypeObject zbarDecoder_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Decoder",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_doc = decoder_doc,
+ .tp_basicsize = sizeof(zbarDecoder),
+ .tp_new = (newfunc)decoder_new,
+ .tp_traverse = (traverseproc)decoder_traverse,
+ .tp_clear = (inquiry)decoder_clear,
+ .tp_dealloc = (destructor)decoder_dealloc,
+ .tp_getset = decoder_getset,
+ .tp_methods = decoder_methods,
+};
diff --git a/python/enum.c b/python/enum.c
new file mode 100644
index 0000000..b57a880
--- /dev/null
+++ b/python/enum.c
@@ -0,0 +1,259 @@
+/*------------------------------------------------------------------------
+ * Copyright 2009-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
+ *------------------------------------------------------------------------*/
+
+#include "zbarmodule.h"
+
+static char enumitem_doc[] =
+ PyDoc_STR("simple enumeration item.\n"
+ "\n"
+ "associates an int value with a name for printing.");
+
+static zbarEnumItem *enumitem_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ int val = 0;
+ PyObject *name = NULL;
+ static char *kwlist[] = { "value", "name", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "iS", kwlist, &val, &name))
+ return (NULL);
+
+ zbarEnumItem *self = (zbarEnumItem *)type->tp_alloc(type, 0);
+ if (!self)
+ return (NULL);
+
+#if PY_MAJOR_VERSION >= 3
+ PyLongObject *longval = (PyLongObject *)PyLong_FromLong(val);
+ if (!longval) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+
+ /* we assume the "fast path" for a single-digit ints (see longobject.c) */
+ /* this also holds if we get a small_int preallocated long */
+#if PY_VERSION_HEX >= 0x030900A4
+ Py_SET_SIZE(&self->val, Py_SIZE(longval));
+#else
+ Py_SIZE(&self->val) = Py_SIZE(longval);
+#endif
+#if PY_VERSION_HEX >= 0x030c0000
+ self->val.long_value.ob_digit[0] = longval->long_value.ob_digit[0];
+#else
+ self->val.ob_digit[0] = longval->ob_digit[0];
+#endif
+ Py_DECREF(longval);
+#else
+ self->val.ob_ival = val;
+#endif
+ self->name = name;
+ return (self);
+}
+
+static void enumitem_dealloc(zbarEnumItem *self)
+{
+ Py_CLEAR(self->name);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *enumitem_str(zbarEnumItem *self)
+{
+ Py_INCREF(self->name);
+ return (self->name);
+}
+
+#if PY_MAJOR_VERSION < 3
+/* tp_print was dropped on Python 3.9 */
+static int enumitem_print(zbarEnumItem *self, FILE *fp, int flags)
+{
+ return (self->name->ob_type->tp_print(self->name, fp, flags));
+}
+#endif
+
+static PyObject *enumitem_repr(zbarEnumItem *self)
+{
+ PyObject *name = PyObject_Repr(self->name);
+ if (!name)
+ return (NULL);
+#if PY_MAJOR_VERSION >= 3
+ PyObject *repr = PyUnicode_FromFormat("%s(%ld, %U)",
+ ((PyObject *)self)->ob_type->tp_name,
+ PyLong_AsLong((PyObject *)self),
+ name);
+#else
+ char *namestr = PyString_AsString(name);
+ PyObject *repr = PyString_FromFormat("%s(%ld, %s)",
+ ((PyObject *)self)->ob_type->tp_name,
+ self->val.ob_ival, namestr);
+#endif
+ Py_DECREF(name);
+ return ((PyObject *)repr);
+}
+
+PyTypeObject zbarEnumItem_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.EnumItem",
+ .tp_doc = enumitem_doc,
+ .tp_basicsize = sizeof(zbarEnumItem),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_new = (newfunc)enumitem_new,
+ .tp_dealloc = (destructor)enumitem_dealloc,
+ .tp_str = (reprfunc)enumitem_str,
+#if PY_MAJOR_VERSION < 3
+ .tp_print = (printfunc)enumitem_print,
+#endif
+ .tp_repr = (reprfunc)enumitem_repr,
+};
+
+zbarEnumItem *zbarEnumItem_New(PyObject *byname, PyObject *byvalue, int val,
+ const char *name)
+{
+ zbarEnumItem *self = PyObject_New(zbarEnumItem, &zbarEnumItem_Type);
+ if (!self)
+ return (NULL);
+#if PY_MAJOR_VERSION >= 3
+ PyLongObject *longval = (PyLongObject *)PyLong_FromLong(val);
+ if (!longval) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+
+ /* we assume the "fast path" for a single-digit ints (see longobject.c) */
+ /* this also holds if we get a small_int preallocated long */
+#if PY_VERSION_HEX >= 0x030900A4
+ Py_SET_SIZE(&self->val, Py_SIZE(longval));
+#else
+ Py_SIZE(&self->val) = Py_SIZE(longval);
+#endif
+#if PY_VERSION_HEX >= 0x030c0000
+ self->val.long_value.ob_digit[0] = longval->long_value.ob_digit[0];
+#else
+ self->val.ob_digit[0] = longval->ob_digit[0];
+#endif
+ Py_DECREF(longval);
+
+ self->name = PyUnicode_FromString(name);
+#else
+ self->val.ob_ival = val;
+ self->name = PyString_FromString(name);
+#endif
+ if (!self->name ||
+ (byname && PyDict_SetItem(byname, self->name, (PyObject *)self)) ||
+ (byvalue &&
+ PyDict_SetItem(byvalue, (PyObject *)self, (PyObject *)self))) {
+ Py_DECREF((PyObject *)self);
+ return (NULL);
+ }
+ return (self);
+}
+
+static char enum_doc[] = PyDoc_STR("enumeration container for EnumItems.\n"
+ "\n"
+ "exposes items as read-only attributes");
+
+/* FIXME add iteration */
+
+static int enum_traverse(zbarEnum *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->byname);
+ Py_VISIT(self->byvalue);
+ return (0);
+}
+
+static int enum_clear(zbarEnum *self)
+{
+ Py_CLEAR(self->byname);
+ Py_CLEAR(self->byvalue);
+ return (0);
+}
+
+static void enum_dealloc(zbarEnum *self)
+{
+ enum_clear(self);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+PyTypeObject zbarEnum_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Enum",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_doc = enum_doc,
+ .tp_basicsize = sizeof(zbarEnum),
+ .tp_dictoffset = offsetof(zbarEnum, byname),
+ .tp_traverse = (traverseproc)enum_traverse,
+ .tp_clear = (inquiry)enum_clear,
+ .tp_dealloc = (destructor)enum_dealloc,
+};
+
+zbarEnum *zbarEnum_New()
+{
+ zbarEnum *self = PyObject_GC_New(zbarEnum, &zbarEnum_Type);
+ if (!self)
+ return (NULL);
+ self->byname = PyDict_New();
+ self->byvalue = PyDict_New();
+ if (!self->byname || !self->byvalue) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+ return (self);
+}
+
+int zbarEnum_Add(zbarEnum *self, int val, const char *name)
+{
+ zbarEnumItem *item;
+ item = zbarEnumItem_New(self->byname, self->byvalue, val, name);
+ if (!item)
+ return (-1);
+ return (0);
+}
+
+zbarEnumItem *zbarEnum_LookupValue(zbarEnum *self, int val)
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *key = PyLong_FromLong(val);
+#else
+ PyObject *key = PyInt_FromLong(val);
+#endif
+ zbarEnumItem *e = (zbarEnumItem *)PyDict_GetItem(self->byvalue, key);
+ if (!e)
+ return ((zbarEnumItem *)key);
+ Py_INCREF((PyObject *)e);
+ Py_DECREF(key);
+ return (e);
+}
+
+PyObject *zbarEnum_SetFromMask(zbarEnum *self, unsigned int mask)
+{
+ PyObject *result = PySet_New(NULL);
+ PyObject *key, *item;
+ Py_ssize_t i = 0;
+ while (PyDict_Next(self->byvalue, &i, &key, &item)) {
+#if PY_MAJOR_VERSION >= 3
+ unsigned long val = (unsigned long)PyLong_AsLong(item);
+#else
+ int val = PyInt_AsLong(item);
+#endif
+ if (val < sizeof(mask) * 8 && ((mask >> val) & 1))
+ PySet_Add(result, item);
+ }
+ return (result);
+}
diff --git a/python/examples/processor.py b/python/examples/processor.py
new file mode 100644
index 0000000..b8f20f0
--- /dev/null
+++ b/python/examples/processor.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+from sys import argv
+import zbar
+
+# create a Processor
+proc = zbar.Processor()
+
+# configure the Processor
+proc.parse_config('enable')
+
+# initialize the Processor
+device = '/dev/video0'
+if len(argv) > 1:
+ device = argv[1]
+proc.init(device)
+
+# setup a callback
+def my_handler(proc, image, closure):
+ # extract results
+ for symbol in image.symbols:
+ # do something useful with results
+ print('decoded', symbol.type, 'symbol', '"%s"' % symbol.data)
+
+proc.set_data_handler(my_handler)
+
+# enable the preview window
+proc.visible = True
+
+# initiate scanning
+proc.active = True
+try:
+ # keep scanning until user provides key/mouse input
+ proc.user_wait()
+except zbar.WindowClosed as e:
+ pass
diff --git a/python/examples/read_one.py b/python/examples/read_one.py
new file mode 100644
index 0000000..7a18c99
--- /dev/null
+++ b/python/examples/read_one.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+from sys import argv
+import zbar
+
+# create a Processor
+proc = zbar.Processor()
+
+# configure the Processor
+proc.parse_config('enable')
+
+# initialize the Processor
+device = '/dev/video0'
+if len(argv) > 1:
+ device = argv[1]
+proc.init(device)
+
+# enable the preview window
+proc.visible = True
+
+# read at least one barcode (or until window closed)
+proc.process_one()
+
+# hide the preview window
+proc.visible = False
+
+# extract results
+for symbol in proc.results:
+ # do something useful with results
+ print('decoded', symbol.type, 'symbol', '"%s"' % symbol.data)
diff --git a/python/examples/scan_image.py b/python/examples/scan_image.py
new file mode 100644
index 0000000..e26cb42
--- /dev/null
+++ b/python/examples/scan_image.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+from sys import argv
+import zbar
+from PIL import Image
+
+if len(argv) < 2: exit(1)
+
+# create a reader
+scanner = zbar.ImageScanner()
+
+# configure the reader
+scanner.parse_config('enable')
+
+# obtain image data
+pil = Image.open(argv[1]).convert('L')
+width, height = pil.size
+raw = pil.tobytes()
+
+# wrap image data
+image = zbar.Image(width, height, 'Y800', raw)
+
+# scan the image for barcodes
+scanner.scan(image)
+
+# extract results
+for symbol in image:
+ # do something useful with results
+ print('decoded', symbol.type, 'symbol', '"%s"' % symbol.data)
+
+# clean up
+del(image)
diff --git a/python/exception.c b/python/exception.c
new file mode 100644
index 0000000..2edc722
--- /dev/null
+++ b/python/exception.c
@@ -0,0 +1,123 @@
+/*------------------------------------------------------------------------
+ * 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 "zbarmodule.h"
+
+#if PY_MAJOR_VERSION < 3
+
+static inline PyObject *exc_get_message(zbarException *self, void *closure)
+{
+ PyBaseExceptionObject *super = (PyBaseExceptionObject *)self;
+ if (!PyString_Size(super->message)) {
+ Py_CLEAR(super->message);
+ if (!self->obj || !zbarProcessor_Check(self->obj))
+ super->message = PyString_FromString("unknown zbar error");
+ else {
+ const void *zobj = ((zbarProcessor *)self->obj)->zproc;
+ super->message = PyString_FromString(_zbar_error_string(zobj, 1));
+ }
+ }
+ Py_INCREF(super->message);
+ return (super->message);
+}
+
+static int exc_init(zbarException *self, PyObject *args, PyObject *kwds)
+{
+ if (!_PyArg_NoKeywords(self->base.ob_type->tp_name, kwds))
+ return (-1);
+ PyBaseExceptionObject *super = (PyBaseExceptionObject *)self;
+ Py_CLEAR(super->args);
+ Py_INCREF(args);
+ super->args = args;
+
+ if (PyTuple_GET_SIZE(args) == 1) {
+ Py_CLEAR(self->obj);
+ self->obj = PyTuple_GET_ITEM(args, 0);
+ Py_INCREF(self->obj);
+ }
+ return (0);
+}
+
+static int exc_traverse(zbarException *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->obj);
+ PyTypeObject *base = (PyTypeObject *)PyExc_Exception;
+ return (base->tp_traverse((PyObject *)self, visit, arg));
+}
+
+static int exc_clear(zbarException *self)
+{
+ Py_CLEAR(self->obj);
+ ((PyTypeObject *)PyExc_Exception)->tp_clear((PyObject *)self);
+ return (0);
+}
+
+static void exc_dealloc(zbarException *self)
+{
+ exc_clear(self);
+ ((PyTypeObject *)PyExc_Exception)->tp_dealloc((PyObject *)self);
+}
+
+static PyObject *exc_str(zbarException *self)
+{
+ return (exc_get_message(self, NULL));
+}
+
+static int exc_set_message(zbarException *self, PyObject *value, void *closure)
+{
+ PyBaseExceptionObject *super = (PyBaseExceptionObject *)self;
+ Py_CLEAR(super->message);
+ if (!value)
+ value = PyString_FromString("");
+ else
+ Py_INCREF(value);
+ super->message = value;
+ return (0);
+}
+
+static PyGetSetDef exc_getset[] = {
+ {
+ "message",
+ (getter)exc_get_message,
+ (setter)exc_set_message,
+ },
+ {
+ NULL,
+ },
+};
+
+PyTypeObject zbarException_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Exception",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_basicsize = sizeof(zbarException),
+ .tp_init = (initproc)exc_init,
+ .tp_traverse = (traverseproc)exc_traverse,
+ .tp_clear = (inquiry)exc_clear,
+ .tp_dealloc = (destructor)exc_dealloc,
+ .tp_str = (reprfunc)exc_str,
+ .tp_getset = exc_getset,
+};
+
+#endif
diff --git a/python/image.c b/python/image.c
new file mode 100644
index 0000000..b3ff5cd
--- /dev/null
+++ b/python/image.c
@@ -0,0 +1,482 @@
+/*------------------------------------------------------------------------
+ * Copyright 2009-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
+ *------------------------------------------------------------------------*/
+
+#include "zbarmodule.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+static char image_doc[] = PyDoc_STR(
+ "image object.\n"
+ "\n"
+ "stores image data samples along with associated format and size metadata.");
+
+static zbarImage *image_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ zbarImage *self = (zbarImage *)type->tp_alloc(type, 0);
+ if (!self)
+ return (NULL);
+
+ self->zimg = zbar_image_create();
+ if (!self->zimg) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+ zbar_image_set_userdata(self->zimg, self);
+ return (self);
+}
+
+static int image_traverse(zbarImage *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->data);
+ return (0);
+}
+
+static int image_clear(zbarImage *self)
+{
+ zbar_image_t *zimg = self->zimg;
+ self->zimg = NULL;
+ if (zimg) {
+ assert(zbar_image_get_userdata(zimg) == self);
+ if (self->data) {
+ /* attach data directly to zbar image */
+ zbar_image_set_userdata(zimg, self->data);
+ self->data = NULL;
+ } else
+ zbar_image_set_userdata(zimg, NULL);
+ zbar_image_destroy(zimg);
+ }
+ return (0);
+}
+
+static void image_dealloc(zbarImage *self)
+{
+ image_clear(self);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static zbarSymbolSet *image_get_symbols(zbarImage *self, void *closure)
+{
+ const zbar_symbol_set_t *zsyms = zbar_image_get_symbols(self->zimg);
+ return (zbarSymbolSet_FromSymbolSet(zsyms));
+}
+
+static int image_set_symbols(zbarImage *self, PyObject *value, void *closure)
+{
+ const zbar_symbol_set_t *zsyms;
+ if (!value || value == Py_None)
+ zsyms = NULL;
+ else if (zbarSymbolSet_Check(value))
+ zsyms = ((zbarSymbolSet *)value)->zsyms;
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "must set image symbols to a zbar.SymbolSet, not '%.50s'",
+ value->ob_type->tp_name);
+ return (-1);
+ }
+
+ zbar_image_set_symbols(self->zimg, zsyms);
+ return (0);
+}
+
+static zbarSymbolIter *image_iter(zbarImage *self)
+{
+ zbarSymbolSet *syms = image_get_symbols(self, NULL);
+ if (!syms)
+ return (NULL);
+ return (zbarSymbolIter_FromSymbolSet(syms));
+}
+
+static PyObject *image_get_format(zbarImage *self, void *closure)
+{
+ unsigned long format = zbar_image_get_format(self->zimg);
+#if PY_MAJOR_VERSION >= 3
+ return (PyBytes_FromStringAndSize((char *)&format, 4));
+#else
+ return (PyString_FromStringAndSize((char *)&format, 4));
+#endif
+}
+
+static int image_set_format(zbarImage *self, PyObject *value, void *closure)
+{
+ if (!value) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete format attribute");
+ return (-1);
+ }
+ char *format = NULL;
+ Py_ssize_t len;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *bytes;
+
+ if (PyUnicode_Check(value))
+ bytes = PyUnicode_AsEncodedString(value, "utf-8", "surrogateescape");
+ else
+ bytes = value;
+ if (PyBytes_AsStringAndSize(bytes, &format, &len) < 0 || !format ||
+ len != 4) {
+#else
+ if (PyString_AsStringAndSize(value, &format, &len) || !format || len != 4) {
+#endif
+ if (!format)
+ format = "(nil)";
+ PyErr_Format(PyExc_ValueError,
+ "format '%.50s' is not a valid four character code",
+ format);
+ return (-1);
+ }
+ zbar_image_set_format(self->zimg, zbar_fourcc_parse(format));
+ return (0);
+}
+
+static PyObject *image_get_size(zbarImage *self, void *closure)
+{
+ unsigned int w, h;
+ zbar_image_get_size(self->zimg, &w, &h);
+#if PY_MAJOR_VERSION >= 3
+ return (PyTuple_Pack(2, PyLong_FromLong(w), PyLong_FromLong(h)));
+#else
+ return (PyTuple_Pack(2, PyInt_FromLong(w), PyInt_FromLong(h)));
+#endif
+}
+
+static int image_set_size(zbarImage *self, PyObject *value, void *closure)
+{
+ if (!value) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete size attribute");
+ return (-1);
+ }
+
+ int dims[2];
+ if (parse_dimensions(value, dims, 2) || dims[0] < 0 || dims[1] < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "size must be a sequence of two positive ints");
+ return (-1);
+ }
+
+ zbar_image_set_size(self->zimg, dims[0], dims[1]);
+ return (0);
+}
+
+static PyObject *image_get_crop(zbarImage *self, void *closure)
+{
+ unsigned int x, y, w, h;
+ zbar_image_get_crop(self->zimg, &x, &y, &w, &h);
+#if PY_MAJOR_VERSION >= 3
+ return (PyTuple_Pack(4, PyLong_FromLong(x), PyLong_FromLong(y),
+ PyLong_FromLong(w), PyLong_FromLong(h)));
+#else
+ return (PyTuple_Pack(4, PyInt_FromLong(x), PyInt_FromLong(y),
+ PyInt_FromLong(w), PyInt_FromLong(h)));
+#endif
+}
+
+static int image_set_crop(zbarImage *self, PyObject *value, void *closure)
+{
+ unsigned w, h;
+ zbar_image_get_size(self->zimg, &w, &h);
+ if (!value) {
+ zbar_image_set_crop(self->zimg, 0, 0, w, h);
+ return (0);
+ }
+
+ int dims[4];
+ if (parse_dimensions(value, dims, 4) || dims[2] < 0 || dims[3] < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "crop must be a sequence of four positive ints");
+ return (-1);
+ }
+
+ if (dims[0] < 0) {
+ dims[2] += dims[0];
+ dims[0] = 0;
+ }
+ if (dims[1] < 0) {
+ dims[3] += dims[1];
+ dims[1] = 0;
+ }
+
+ zbar_image_set_crop(self->zimg, dims[0], dims[1], dims[2], dims[3]);
+ return (0);
+}
+
+static PyObject *image_get_int(zbarImage *self, void *closure)
+{
+ unsigned int val = -1;
+ switch ((intptr_t)closure) {
+ case 0:
+ val = zbar_image_get_width(self->zimg);
+ break;
+ case 1:
+ val = zbar_image_get_height(self->zimg);
+ break;
+ case 2:
+ val = zbar_image_get_sequence(self->zimg);
+ break;
+ default:
+ assert(0);
+ }
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(val));
+#else
+ return (PyInt_FromLong(val));
+#endif
+}
+
+static int image_set_int(zbarImage *self, PyObject *value, void *closure)
+{
+ unsigned int tmp;
+#if PY_MAJOR_VERSION >= 3
+ long val = PyLong_AsLong(value);
+#else
+ unsigned int val = PyInt_AsSsize_t(value);
+#endif
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "expecting an integer");
+ return (-1);
+ }
+ switch ((intptr_t)closure) {
+ case 0:
+ tmp = zbar_image_get_height(self->zimg);
+ zbar_image_set_size(self->zimg, val, tmp);
+ break;
+ case 1:
+ tmp = zbar_image_get_width(self->zimg);
+ zbar_image_set_size(self->zimg, tmp, val);
+ break;
+ case 2:
+ zbar_image_set_sequence(self->zimg, val);
+ default:
+ assert(0);
+ }
+ return (0);
+}
+
+static PyObject *image_get_data(zbarImage *self, void *closure)
+{
+ assert(zbar_image_get_userdata(self->zimg) == self);
+ if (self->data) {
+ Py_INCREF(self->data);
+ return (self->data);
+ }
+
+ const char *data = zbar_image_get_data(self->zimg);
+ unsigned long datalen = zbar_image_get_data_length(self->zimg);
+ if (!data || !datalen) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+
+#if PY_MAJOR_VERSION >= 3
+ self->data = PyMemoryView_FromMemory((void *)data, datalen, PyBUF_READ);
+#else
+ self->data = PyBuffer_FromMemory((void *)data, datalen);
+#endif
+ Py_INCREF(self->data);
+ return (self->data);
+}
+
+void image_cleanup(zbar_image_t *zimg)
+{
+ PyObject *data = zbar_image_get_userdata(zimg);
+ zbar_image_set_userdata(zimg, NULL);
+ if (!data)
+ return; /* FIXME internal error */
+ if (PyObject_TypeCheck(data, &zbarImage_Type)) {
+ zbarImage *self = (zbarImage *)data;
+ assert(self->zimg == zimg);
+ Py_CLEAR(self->data);
+ } else
+ Py_DECREF(data);
+}
+
+static int image_set_data(zbarImage *self, PyObject *value, void *closure)
+{
+ if (!value) {
+ zbar_image_free_data(self->zimg);
+ return (0);
+ }
+ char *data;
+ Py_ssize_t datalen;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *bytes;
+
+ if (PyUnicode_Check(value))
+ bytes = PyUnicode_AsEncodedString(value, "utf-8", "surrogateescape");
+ else
+ bytes = value;
+ if (PyBytes_AsStringAndSize(bytes, &data, &datalen))
+ return (-1);
+#else
+ if (PyString_AsStringAndSize(value, &data, &datalen))
+ return (-1);
+#endif
+
+ Py_INCREF(value);
+ zbar_image_set_data(self->zimg, data, datalen, image_cleanup);
+ assert(!self->data);
+ self->data = value;
+ zbar_image_set_userdata(self->zimg, self);
+ return (0);
+}
+
+static PyGetSetDef image_getset[] = {
+ {
+ "format",
+ (getter)image_get_format,
+ (setter)image_set_format,
+ },
+ {
+ "size",
+ (getter)image_get_size,
+ (setter)image_set_size,
+ },
+ {
+ "crop",
+ (getter)image_get_crop,
+ (setter)image_set_crop,
+ },
+ { "width", (getter)image_get_int, (setter)image_set_int, NULL, (void *)0 },
+ { "height", (getter)image_get_int, (setter)image_set_int, NULL, (void *)1 },
+ { "sequence", (getter)image_get_int, (setter)image_set_int, NULL,
+ (void *)2 },
+ {
+ "data",
+ (getter)image_get_data,
+ (setter)image_set_data,
+ },
+ {
+ "symbols",
+ (getter)image_get_symbols,
+ (setter)image_set_symbols,
+ },
+ {
+ NULL,
+ },
+};
+
+static int image_init(zbarImage *self, PyObject *args, PyObject *kwds)
+{
+ int width = -1, height = -1;
+ PyObject *format = NULL, *data = NULL;
+ static char *kwlist[] = { "width", "height", "format", "data", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iiOO", kwlist, &width,
+ &height, &format, &data))
+ return (-1);
+
+ if (width > 0 && height > 0)
+ zbar_image_set_size(self->zimg, width, height);
+ if (format && image_set_format(self, format, NULL))
+ return (-1);
+ if (data && image_set_data(self, data, NULL))
+ return (-1);
+ return (0);
+}
+
+static zbarImage *image_convert(zbarImage *self, PyObject *args, PyObject *kwds)
+{
+ const char *format = NULL;
+ int width = -1, height = -1;
+ static char *kwlist[] = { "format", "width", "height", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ii", kwlist, &format,
+ &width, &height))
+ return (NULL);
+ assert(format);
+
+ if (strlen(format) != 4) {
+ PyErr_Format(PyExc_ValueError,
+ "format '%.50s' is not a valid four character code",
+ format);
+ return (NULL);
+ }
+ unsigned long fourcc = zbar_fourcc_parse(format);
+
+ zbarImage *img = PyObject_GC_New(zbarImage, &zbarImage_Type);
+ if (!img)
+ return (NULL);
+ img->data = NULL;
+ if (width > 0 && height > 0)
+ img->zimg =
+ zbar_image_convert_resize(self->zimg, fourcc, width, height);
+ else
+ img->zimg = zbar_image_convert(self->zimg, fourcc);
+
+ if (!img->zimg) {
+ /* FIXME propagate exception */
+ Py_DECREF(img);
+ return (NULL);
+ }
+ zbar_image_set_userdata(img->zimg, img);
+
+ return (img);
+}
+
+static PyMethodDef image_methods[] = {
+ {
+ "convert",
+ (PyCFunction)image_convert,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ NULL,
+ },
+};
+
+PyTypeObject zbarImage_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Image",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_doc = image_doc,
+ .tp_basicsize = sizeof(zbarImage),
+ .tp_new = (newfunc)image_new,
+ .tp_init = (initproc)image_init,
+ .tp_traverse = (traverseproc)image_traverse,
+ .tp_clear = (inquiry)image_clear,
+ .tp_dealloc = (destructor)image_dealloc,
+ .tp_getset = image_getset,
+ .tp_methods = image_methods,
+ .tp_iter = (getiterfunc)image_iter,
+};
+
+zbarImage *zbarImage_FromImage(zbar_image_t *zimg)
+{
+ zbarImage *self = PyObject_GC_New(zbarImage, &zbarImage_Type);
+ if (!self)
+ return (NULL);
+ zbar_image_ref(zimg, 1);
+ zbar_image_set_userdata(zimg, self);
+ self->zimg = zimg;
+ self->data = NULL;
+ return (self);
+}
+
+int zbarImage_validate(zbarImage *img)
+{
+ if (!zbar_image_get_width(img->zimg) || !zbar_image_get_height(img->zimg) ||
+ !zbar_image_get_data(img->zimg) ||
+ !zbar_image_get_data_length(img->zimg)) {
+ PyErr_Format(PyExc_ValueError, "image size and data must be defined");
+ return (-1);
+ }
+ return (0);
+}
diff --git a/python/imagescanner.c b/python/imagescanner.c
new file mode 100644
index 0000000..54966b7
--- /dev/null
+++ b/python/imagescanner.c
@@ -0,0 +1,195 @@
+/*------------------------------------------------------------------------
+ * 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 "zbarmodule.h"
+
+static char imagescanner_doc[] =
+ PyDoc_STR("scan images for barcodes.\n"
+ "\n"
+ "attaches symbols to image for each decoded result.");
+
+static zbarImageScanner *imagescanner_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ static char *kwlist[] = { NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
+ return (NULL);
+
+ zbarImageScanner *self = (zbarImageScanner *)type->tp_alloc(type, 0);
+ if (!self)
+ return (NULL);
+
+ self->zscn = zbar_image_scanner_create();
+ if (!self->zscn) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+
+ return (self);
+}
+
+static void imagescanner_dealloc(zbarImageScanner *self)
+{
+ zbar_image_scanner_destroy(self->zscn);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static zbarSymbolSet *imagescanner_get_results(zbarImageScanner *self,
+ void *closure)
+{
+ const zbar_symbol_set_t *zsyms = zbar_image_scanner_get_results(self->zscn);
+ return (zbarSymbolSet_FromSymbolSet(zsyms));
+}
+
+static PyGetSetDef imagescanner_getset[] = {
+ { "results", (getter)imagescanner_get_results, NULL, NULL, NULL },
+ { NULL } /* Sentinel */
+};
+
+static PyObject *imagescanner_set_config(zbarImageScanner *self, PyObject *args,
+ PyObject *kwds)
+{
+ zbar_symbol_type_t sym = ZBAR_NONE;
+ zbar_config_t cfg = ZBAR_CFG_ENABLE;
+ int val = 1;
+ static char *kwlist[] = { "symbology", "config", "value", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &sym, &cfg,
+ &val))
+ return (NULL);
+
+ if (zbar_image_scanner_set_config(self->zscn, sym, cfg, val)) {
+ PyErr_SetString(PyExc_ValueError, "invalid configuration setting");
+ return (NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *imagescanner_parse_config(zbarImageScanner *self,
+ PyObject *args, PyObject *kwds)
+{
+ const char *cfg = NULL;
+ static char *kwlist[] = { "config", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cfg))
+ return (NULL);
+
+ if (zbar_image_scanner_parse_config(self->zscn, cfg)) {
+ PyErr_Format(PyExc_ValueError, "invalid configuration setting: %s",
+ cfg);
+ return (NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *imagescanner_enable_cache(zbarImageScanner *self,
+ PyObject *args, PyObject *kwds)
+{
+ unsigned char enable = 1;
+ static char *kwlist[] = { "enable", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, object_to_bool,
+ &enable))
+ return (NULL);
+
+ zbar_image_scanner_enable_cache(self->zscn, enable);
+ Py_RETURN_NONE;
+}
+
+static PyObject *imagescanner_recycle(zbarImageScanner *self, PyObject *args,
+ PyObject *kwds)
+{
+ zbarImage *img = NULL;
+ static char *kwlist[] = { "image", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &zbarImage_Type,
+ &img))
+ return (NULL);
+
+ zbar_image_scanner_recycle_image(self->zscn, img->zimg);
+ Py_RETURN_NONE;
+}
+
+static PyObject *imagescanner_scan(zbarImageScanner *self, PyObject *args,
+ PyObject *kwds)
+{
+ zbarImage *img = NULL;
+ static char *kwlist[] = { "image", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &zbarImage_Type,
+ &img))
+ return (NULL);
+
+ if (zbarImage_validate(img))
+ return (NULL);
+
+ int n = zbar_scan_image(self->zscn, img->zimg);
+ if (n < 0) {
+ PyErr_Format(PyExc_ValueError, "unsupported image format");
+ return (NULL);
+ }
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(n));
+#else
+ return (PyInt_FromLong(n));
+#endif
+}
+
+static PyMethodDef imagescanner_methods[] = {
+ {
+ "set_config",
+ (PyCFunction)imagescanner_set_config,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "parse_config",
+ (PyCFunction)imagescanner_parse_config,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "enable_cache",
+ (PyCFunction)imagescanner_enable_cache,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "recycle",
+ (PyCFunction)imagescanner_recycle,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "scan",
+ (PyCFunction)imagescanner_scan,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ NULL,
+ },
+};
+
+PyTypeObject zbarImageScanner_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.ImageScanner",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = imagescanner_doc,
+ .tp_basicsize = sizeof(zbarImageScanner),
+ .tp_new = (newfunc)imagescanner_new,
+ .tp_dealloc = (destructor)imagescanner_dealloc,
+ .tp_getset = imagescanner_getset,
+ .tp_methods = imagescanner_methods,
+};
diff --git a/python/processor.c b/python/processor.c
new file mode 100644
index 0000000..a9e4c47
--- /dev/null
+++ b/python/processor.c
@@ -0,0 +1,456 @@
+/*------------------------------------------------------------------------
+ * 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 "zbarmodule.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+static char processor_doc[] =
+ PyDoc_STR("low level decode of measured bar/space widths.\n"
+ "\n"
+ "FIXME.");
+
+static zbarProcessor *processor_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ static char *kwlist[] = { "enable_threads", NULL };
+ int threaded = -1;
+ zbarProcessor *self;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, object_to_bool,
+ &threaded))
+ return (NULL);
+
+#ifdef WITH_THREAD
+#if (PY_MAJOR_VERSION < 3) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
+ /* the processor creates a thread that calls back into python,
+ * so we must ensure that threads are initialized before attempting
+ * to manipulate the GIL (bug #3349199)
+ */
+ PyEval_InitThreads();
+#endif
+#else
+ if (threaded > 0 &&
+ PyErr_WarnEx(NULL, "threading requested but not available", 1))
+ return (NULL);
+ threaded = 0;
+#endif
+
+ self = (zbarProcessor *)type->tp_alloc(type, 0);
+ if (!self)
+ return (NULL);
+
+ self->zproc = zbar_processor_create(threaded);
+ zbar_processor_set_userdata(self->zproc, self);
+ if (!self->zproc) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+ return (self);
+}
+
+static int processor_traverse(zbarProcessor *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->handler);
+ Py_VISIT(self->closure);
+ return (0);
+}
+
+static int processor_clear(zbarProcessor *self)
+{
+ zbar_processor_set_data_handler(self->zproc, NULL, NULL);
+ zbar_processor_set_userdata(self->zproc, NULL);
+ Py_CLEAR(self->handler);
+ Py_CLEAR(self->closure);
+ return (0);
+}
+
+static void processor_dealloc(zbarProcessor *self)
+{
+ processor_clear(self);
+ zbar_processor_destroy(self->zproc);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *processor_get_bool(zbarProcessor *self, void *closure)
+{
+ int val;
+ switch ((intptr_t)closure) {
+ case 0:
+ val = zbar_processor_is_visible(self->zproc);
+ break;
+ default:
+ assert(0);
+ return (NULL);
+ }
+ if (val < 0)
+ return (zbarErr_Set((PyObject *)self));
+ return (PyBool_FromLong(val));
+}
+
+static int processor_set_bool(zbarProcessor *self, PyObject *value,
+ void *closure)
+{
+ int rc, val;
+
+ if (!value) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return (-1);
+ }
+ val = PyObject_IsTrue(value);
+ if (val < 0)
+ return (-1);
+ switch ((intptr_t)closure) {
+ case 0:
+ rc = zbar_processor_set_visible(self->zproc, val);
+ break;
+ case 1:
+ rc = zbar_processor_set_active(self->zproc, val);
+ break;
+ default:
+ assert(0);
+ return (-1);
+ }
+ if (rc < 0) {
+ zbarErr_Set((PyObject *)self);
+ return (-1);
+ }
+ return (0);
+}
+
+static zbarSymbolSet *processor_get_results(zbarProcessor *self, void *closure)
+{
+ const zbar_symbol_set_t *zsyms = zbar_processor_get_results(self->zproc);
+
+ return (zbarSymbolSet_FromSymbolSet(zsyms));
+}
+
+static int processor_set_request_size(zbarProcessor *self, PyObject *value,
+ void *closure)
+{
+ int dims[2];
+
+ if (!value) {
+ zbar_processor_request_size(self->zproc, 0, 0);
+ return (0);
+ }
+
+ if (parse_dimensions(value, dims, 2) || dims[0] < 0 || dims[1] < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "request_size must be a sequence of two positive ints");
+ return (-1);
+ }
+
+ zbar_processor_request_size(self->zproc, dims[0], dims[1]);
+ return (0);
+}
+
+static PyGetSetDef processor_getset[] = {
+ { "visible", (getter)processor_get_bool, (setter)processor_set_bool, NULL,
+ (void *)0 },
+ { "active", NULL, (setter)processor_set_bool, NULL, (void *)1 },
+ {
+ "results",
+ (getter)processor_get_results,
+ },
+ {
+ "request_size",
+ NULL,
+ (setter)processor_set_request_size,
+ },
+ {
+ NULL,
+ },
+};
+
+static PyObject *processor_set_config(zbarProcessor *self, PyObject *args,
+ PyObject *kwds)
+{
+ zbar_symbol_type_t sym = ZBAR_NONE;
+ zbar_config_t cfg = ZBAR_CFG_ENABLE;
+ int val = 1;
+ static char *kwlist[] = { "symbology", "config", "value", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &sym, &cfg,
+ &val))
+ return (NULL);
+
+ if (zbar_processor_set_config(self->zproc, sym, cfg, val)) {
+ PyErr_SetString(PyExc_ValueError, "invalid configuration setting");
+ return (NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *processor_init_(zbarProcessor *self, PyObject *args,
+ PyObject *kwds)
+{
+ const char *dev = "";
+ int disp = 1;
+ static char *kwlist[] = { "video_device", "enable_display", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zO&", kwlist, &dev,
+ object_to_bool, &disp))
+ return (NULL);
+
+ if (zbar_processor_init(self->zproc, dev, disp))
+ return (zbarErr_Set((PyObject *)self));
+ Py_RETURN_NONE;
+}
+
+static PyObject *processor_parse_config(zbarProcessor *self, PyObject *args,
+ PyObject *kwds)
+{
+ const char *cfg = NULL;
+ static char *kwlist[] = { "config", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cfg))
+ return (NULL);
+
+ if (zbar_processor_parse_config(self->zproc, cfg)) {
+ PyErr_Format(PyExc_ValueError, "invalid configuration setting: %s",
+ cfg);
+ return (NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static int object_to_timeout(PyObject *obj, int *val)
+{
+ long tmp;
+
+ if (PyFloat_Check(obj))
+ tmp = PyFloat_AS_DOUBLE(obj) * 1000;
+ else
+#if PY_MAJOR_VERSION >= 3
+ tmp = PyLong_AsLong(obj) * 1000;
+#else
+ tmp = PyInt_AsLong(obj) * 1000;
+#endif
+ if (tmp < 0 && PyErr_Occurred())
+ return (0);
+ *val = tmp;
+ return (1);
+}
+
+static PyObject *processor_user_wait(zbarProcessor *self, PyObject *args,
+ PyObject *kwds)
+{
+ int timeout = -1;
+ int rc = -1;
+ static char *kwlist[] = { "timeout", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist,
+ object_to_timeout, &timeout))
+ return (NULL);
+
+ Py_BEGIN_ALLOW_THREADS rc = zbar_processor_user_wait(self->zproc, timeout);
+ Py_END_ALLOW_THREADS
+
+ if (rc < 0) return (zbarErr_Set((PyObject *)self));
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(rc));
+#else
+ return (PyInt_FromLong(rc));
+#endif
+}
+
+static PyObject *processor_process_one(zbarProcessor *self, PyObject *args,
+ PyObject *kwds)
+{
+ int timeout = -1;
+ int rc = -1;
+ static char *kwlist[] = { "timeout", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist,
+ object_to_timeout, &timeout))
+ return (NULL);
+
+ Py_BEGIN_ALLOW_THREADS rc = zbar_process_one(self->zproc, timeout);
+ Py_END_ALLOW_THREADS
+
+ if (rc < 0) return (zbarErr_Set((PyObject *)self));
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(rc));
+#else
+ return (PyInt_FromLong(rc));
+#endif
+}
+
+static PyObject *processor_process_image(zbarProcessor *self, PyObject *args,
+ PyObject *kwds)
+{
+ zbarImage *img = NULL;
+ static char *kwlist[] = { "image", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, &zbarImage_Type,
+ &img))
+ return (NULL);
+
+ if (zbarImage_validate(img))
+ return (NULL);
+
+ int n = -1;
+ Py_BEGIN_ALLOW_THREADS n = zbar_process_image(self->zproc, img->zimg);
+ Py_END_ALLOW_THREADS
+
+ if (n < 0) return (zbarErr_Set((PyObject *)self));
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(n));
+#else
+ return (PyInt_FromLong(n));
+#endif
+}
+
+void process_handler(zbar_image_t *zimg, const void *userdata)
+{
+ PyGILState_STATE gstate;
+ gstate = PyGILState_Ensure();
+ zbarImage *img;
+
+ zbarProcessor *self = (zbarProcessor *)userdata;
+ assert(self);
+ assert(self->handler);
+ assert(self->closure);
+
+ img = zbar_image_get_userdata(zimg);
+ if (!img || img->zimg != zimg) {
+ img = zbarImage_FromImage(zimg);
+ if (!img) {
+ PyErr_NoMemory();
+ goto done;
+ }
+ } else
+ Py_INCREF(img);
+
+ PyObject *args = PyTuple_New(3);
+ Py_INCREF(self);
+ Py_INCREF(self->closure);
+ PyTuple_SET_ITEM(args, 0, (PyObject *)self);
+ PyTuple_SET_ITEM(args, 1, (PyObject *)img);
+ PyTuple_SET_ITEM(args, 2, self->closure);
+
+ PyObject *junk = PyObject_Call(self->handler, args, NULL);
+ if (junk)
+ Py_DECREF(junk);
+ else {
+ PySys_WriteStderr("in ZBar Processor data_handler:\n");
+ assert(PyErr_Occurred());
+ PyErr_Print();
+ }
+ Py_DECREF(args);
+
+done:
+ PyGILState_Release(gstate);
+}
+
+static PyObject *processor_set_data_handler(zbarProcessor *self, PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *handler = Py_None;
+ PyObject *closure = Py_None;
+
+ static char *kwlist[] = { "handler", "closure", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &handler,
+ &closure))
+ return (NULL);
+
+ if (handler != Py_None && !PyCallable_Check(handler)) {
+ PyErr_Format(PyExc_ValueError, "handler %.50s is not callable",
+ handler->ob_type->tp_name);
+ return (NULL);
+ }
+ Py_CLEAR(self->handler);
+ Py_CLEAR(self->closure);
+
+ if (handler != Py_None) {
+ Py_INCREF(handler);
+ self->handler = handler;
+
+ Py_INCREF(closure);
+ self->closure = closure;
+
+ zbar_processor_set_data_handler(self->zproc, process_handler, self);
+ } else {
+ self->handler = self->closure = NULL;
+ zbar_processor_set_data_handler(self->zproc, NULL, self);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef processor_methods[] = {
+ {
+ "init",
+ (PyCFunction)processor_init_,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "set_config",
+ (PyCFunction)processor_set_config,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "parse_config",
+ (PyCFunction)processor_parse_config,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "user_wait",
+ (PyCFunction)processor_user_wait,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "process_one",
+ (PyCFunction)processor_process_one,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "process_image",
+ (PyCFunction)processor_process_image,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "set_data_handler",
+ (PyCFunction)processor_set_data_handler,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ NULL,
+ },
+};
+
+PyTypeObject zbarProcessor_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Processor",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_doc = processor_doc,
+ .tp_basicsize = sizeof(zbarProcessor),
+ .tp_new = (newfunc)processor_new,
+ .tp_traverse = (traverseproc)processor_traverse,
+ .tp_clear = (inquiry)processor_clear,
+ .tp_dealloc = (destructor)processor_dealloc,
+ .tp_getset = processor_getset,
+ .tp_methods = processor_methods,
+};
diff --git a/python/scanner.c b/python/scanner.c
new file mode 100644
index 0000000..e5ad8bf
--- /dev/null
+++ b/python/scanner.c
@@ -0,0 +1,193 @@
+/*------------------------------------------------------------------------
+ * 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 "zbarmodule.h"
+
+static char scanner_doc[] = PyDoc_STR(
+ "low level intensity sample stream scanner. identifies \"bar\" edges"
+ "and measures width between them.\n"
+ "\n"
+ "FIXME.");
+
+static zbarScanner *scanner_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ zbarDecoder *decoder = NULL;
+ static char *kwlist[] = { "decoder", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", kwlist, &decoder,
+ zbarDecoder_Type))
+ return (NULL);
+
+ zbarScanner *self = (zbarScanner *)type->tp_alloc(type, 0);
+ if (!self)
+ return (NULL);
+
+ zbar_decoder_t *zdcode = NULL;
+ if (decoder) {
+ Py_INCREF(decoder);
+ self->decoder = decoder;
+ zdcode = decoder->zdcode;
+ }
+ self->zscn = zbar_scanner_create(zdcode);
+ if (!self->zscn) {
+ Py_DECREF(self);
+ return (NULL);
+ }
+
+ return (self);
+}
+
+static int scanner_traverse(zbarScanner *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->decoder);
+ return (0);
+}
+
+static int scanner_clear(zbarScanner *self)
+{
+ Py_CLEAR(self->decoder);
+ return (0);
+}
+
+static void scanner_dealloc(zbarScanner *self)
+{
+ scanner_clear(self);
+ zbar_scanner_destroy(self->zscn);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *scanner_get_width(zbarScanner *self, void *closure)
+{
+ unsigned int width = zbar_scanner_get_width(self->zscn);
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(width));
+#else
+ return (PyInt_FromLong(width));
+#endif
+}
+
+static zbarEnumItem *scanner_get_color(zbarScanner *self, void *closure)
+{
+ zbar_color_t zcol = zbar_scanner_get_color(self->zscn);
+ assert(zcol == ZBAR_BAR || zcol == ZBAR_SPACE);
+ struct module_state *st = GETMODSTATE();
+ zbarEnumItem *color = st->color_enum[zcol];
+ Py_INCREF((PyObject *)color);
+ return (color);
+}
+
+static PyGetSetDef scanner_getset[] = {
+ {
+ "color",
+ (getter)scanner_get_color,
+ },
+ {
+ "width",
+ (getter)scanner_get_width,
+ },
+ {
+ NULL,
+ },
+};
+
+static PyObject *scanner_reset(zbarScanner *self, PyObject *args,
+ PyObject *kwds)
+{
+ static char *kwlist[] = { NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
+ return (NULL);
+
+ zbar_scanner_reset(self->zscn);
+ Py_RETURN_NONE;
+}
+
+static PyObject *scanner_new_scan(zbarScanner *self, PyObject *args,
+ PyObject *kwds)
+{
+ static char *kwlist[] = { NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
+ return (NULL);
+
+ zbar_scanner_new_scan(self->zscn);
+ Py_RETURN_NONE;
+}
+
+static zbarEnumItem *scanner_scan_y(zbarScanner *self, PyObject *args,
+ PyObject *kwds)
+{
+ /* FIXME should accept sequence of values */
+ int y = 0;
+ static char *kwlist[] = { "y", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &y))
+ return (NULL);
+
+ zbar_symbol_type_t sym = zbar_scan_y(self->zscn, y);
+ if (PyErr_Occurred())
+ /* propagate errors during callback */
+ return (NULL);
+ if (sym == ZBAR_NONE) {
+ /* hardcode most common case */
+ struct module_state *st = GETMODSTATE();
+ Py_INCREF((PyObject *)st->symbol_NONE);
+ return (st->symbol_NONE);
+ }
+ return (zbarSymbol_LookupEnum(sym));
+}
+
+static PyMethodDef scanner_methods[] = {
+ {
+ "reset",
+ (PyCFunction)scanner_reset,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "new_scan",
+ (PyCFunction)scanner_new_scan,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ "scan_y",
+ (PyCFunction)scanner_scan_y,
+ METH_VARARGS | METH_KEYWORDS,
+ },
+ {
+ NULL,
+ },
+};
+
+PyTypeObject zbarScanner_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Scanner",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_doc = scanner_doc,
+ .tp_basicsize = sizeof(zbarScanner),
+ .tp_new = (newfunc)scanner_new,
+ .tp_traverse = (traverseproc)scanner_traverse,
+ .tp_clear = (inquiry)scanner_clear,
+ .tp_dealloc = (destructor)scanner_dealloc,
+ .tp_getset = scanner_getset,
+ .tp_methods = scanner_methods,
+};
diff --git a/python/setup.py b/python/setup.py
new file mode 100644
index 0000000..5c27951
--- /dev/null
+++ b/python/setup.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+from distutils.core import setup, Extension
+
+setup(
+ name = 'zbar',
+ version = '0.22.2',
+ author = 'Jeff Brown',
+ author_email = 'spadix@users.sourceforge.net',
+ url = 'http://zbar.sourceforge.net',
+ description = 'read barcodes from images or video',
+ license = 'LGPL',
+ long_description = open('README').read(),
+ classifiers = [
+ 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'Environment :: Console',
+ 'Environment :: X11 Applications',
+ 'Environment :: Win32 (MS Windows)',
+ 'Operating System :: POSIX',
+ 'Operating System :: Unix',
+ 'Operating System :: Microsoft :: Windows',
+ 'Topic :: Communications',
+ 'Topic :: Multimedia :: Graphics',
+ 'Topic :: Software Development :: Libraries',
+ ],
+ ext_modules = [
+ Extension('zbar', [
+ 'zbarmodule.c',
+ 'enum.c',
+ 'exception.c',
+ 'symbol.c',
+ 'symbolset.c',
+ 'symboliter.c',
+ 'image.c',
+ 'processor.c',
+ 'imagescanner.c',
+ 'decoder.c',
+ 'scanner.c',
+ ],
+ libraries = [ 'zbar' ],
+ include_dirs = ['../include']
+ ),
+ ],
+)
diff --git a/python/symbol.c b/python/symbol.c
new file mode 100644
index 0000000..cc7cb83
--- /dev/null
+++ b/python/symbol.c
@@ -0,0 +1,230 @@
+/*------------------------------------------------------------------------
+ * Copyright 2009-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
+ *------------------------------------------------------------------------*/
+
+#include "zbarmodule.h"
+
+static char symbol_doc[] =
+ PyDoc_STR("symbol result object.\n"
+ "\n"
+ "data and associated information about a successful decode.");
+
+static int symbol_traverse(zbarSymbol *self, visitproc visit, void *arg)
+{
+ return (0);
+}
+
+static int symbol_clear(zbarSymbol *self)
+{
+ if (self->zsym) {
+ zbar_symbol_t *zsym = (zbar_symbol_t *)self->zsym;
+ self->zsym = NULL;
+ zbar_symbol_ref(zsym, -1);
+ }
+ Py_CLEAR(self->data);
+ Py_CLEAR(self->loc);
+ return (0);
+}
+
+static void symbol_dealloc(zbarSymbol *self)
+{
+ symbol_clear(self);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static zbarSymbolSet *symbol_get_components(zbarSymbol *self, void *closure)
+{
+ const zbar_symbol_set_t *zsyms = zbar_symbol_get_components(self->zsym);
+ return (zbarSymbolSet_FromSymbolSet(zsyms));
+}
+
+static zbarSymbolIter *symbol_iter(zbarSymbol *self)
+{
+ zbarSymbolSet *syms = symbol_get_components(self, NULL);
+ zbarSymbolIter *iter = zbarSymbolIter_FromSymbolSet(syms);
+ Py_XDECREF(syms);
+ return (iter);
+}
+
+static zbarEnumItem *symbol_get_type(zbarSymbol *self, void *closure)
+{
+ return (zbarSymbol_LookupEnum(zbar_symbol_get_type(self->zsym)));
+}
+
+static PyObject *symbol_get_configs(zbarSymbol *self, void *closure)
+{
+ unsigned int mask = zbar_symbol_get_configs(self->zsym);
+ struct module_state *st = GETMODSTATE();
+ return (zbarEnum_SetFromMask(st->config_enum, mask));
+}
+
+static PyObject *symbol_get_modifiers(zbarSymbol *self, void *closure)
+{
+ unsigned int mask = zbar_symbol_get_modifiers(self->zsym);
+ struct module_state *st = GETMODSTATE();
+ return (zbarEnum_SetFromMask(st->modifier_enum, mask));
+}
+
+static PyObject *symbol_get_long(zbarSymbol *self, void *closure)
+{
+ int val;
+ if (!closure)
+ val = zbar_symbol_get_quality(self->zsym);
+ else
+ val = zbar_symbol_get_count(self->zsym);
+#if PY_MAJOR_VERSION >= 3
+ return (PyLong_FromLong(val));
+#else
+ return (PyInt_FromLong(val));
+#endif
+}
+
+static PyObject *symbol_get_data(zbarSymbol *self, void *closure)
+{
+ if (!self->data) {
+#if PY_MAJOR_VERSION >= 3
+ self->data = PyUnicode_FromStringAndSize(
+ zbar_symbol_get_data(self->zsym),
+ zbar_symbol_get_data_length(self->zsym));
+#else
+ /* FIXME this could be a buffer now */
+ self->data =
+ PyString_FromStringAndSize(zbar_symbol_get_data(self->zsym),
+ zbar_symbol_get_data_length(self->zsym));
+#endif
+ if (!self->data)
+ return (NULL);
+ }
+ Py_INCREF(self->data);
+ return (self->data);
+}
+
+static PyObject *symbol_get_location(zbarSymbol *self, void *closure)
+{
+ if (!self->loc) {
+ /* build tuple of 2-tuples representing location polygon */
+ unsigned int n = zbar_symbol_get_loc_size(self->zsym);
+ self->loc = PyTuple_New(n);
+ unsigned int i;
+ for (i = 0; i < n; i++) {
+ PyObject *x, *y;
+#if PY_MAJOR_VERSION >= 3
+ x = PyLong_FromLong(zbar_symbol_get_loc_x(self->zsym, i));
+ y = PyLong_FromLong(zbar_symbol_get_loc_y(self->zsym, i));
+#else
+ x = PyInt_FromLong(zbar_symbol_get_loc_x(self->zsym, i));
+ y = PyInt_FromLong(zbar_symbol_get_loc_y(self->zsym, i));
+#endif
+ PyTuple_SET_ITEM(self->loc, i, PyTuple_Pack(2, x, y));
+ }
+ }
+ Py_INCREF(self->loc);
+ return (self->loc);
+}
+
+static zbarEnumItem *symbol_get_orientation(zbarSymbol *self, void *closure)
+{
+ struct module_state *st = GETMODSTATE();
+ return (zbarEnum_LookupValue(st->orient_enum,
+ zbar_symbol_get_orientation(self->zsym)));
+}
+
+static PyGetSetDef symbol_getset[] = {
+ {
+ "type",
+ (getter)symbol_get_type,
+ },
+ {
+ "configs",
+ (getter)symbol_get_configs,
+ },
+ {
+ "modifiers",
+ (getter)symbol_get_modifiers,
+ },
+ { "quality", (getter)symbol_get_long, NULL, NULL, (void *)0 },
+ { "count", (getter)symbol_get_long, NULL, NULL, (void *)1 },
+ {
+ "data",
+ (getter)symbol_get_data,
+ },
+ {
+ "location",
+ (getter)symbol_get_location,
+ },
+ {
+ "orientation",
+ (getter)symbol_get_orientation,
+ },
+ {
+ "components",
+ (getter)symbol_get_components,
+ },
+ {
+ NULL,
+ },
+};
+
+PyTypeObject zbarSymbol_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Symbol",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_doc = symbol_doc,
+ .tp_basicsize = sizeof(zbarSymbol),
+ .tp_traverse = (traverseproc)symbol_traverse,
+ .tp_clear = (inquiry)symbol_clear,
+ .tp_dealloc = (destructor)symbol_dealloc,
+ .tp_iter = (getiterfunc)symbol_iter,
+ .tp_getset = symbol_getset,
+};
+
+zbarSymbol *zbarSymbol_FromSymbol(const zbar_symbol_t *zsym)
+{
+ /* FIXME symbol object recycle cache */
+ zbarSymbol *self = PyObject_GC_New(zbarSymbol, &zbarSymbol_Type);
+ if (!self)
+ return (NULL);
+ assert(zsym);
+ zbar_symbol_t *zs = (zbar_symbol_t *)zsym;
+ zbar_symbol_ref(zs, 1);
+ self->zsym = zsym;
+ self->data = NULL;
+ self->loc = NULL;
+ return (self);
+}
+
+zbarEnumItem *zbarSymbol_LookupEnum(zbar_symbol_type_t type)
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *key = PyLong_FromLong(type);
+#else
+ PyObject *key = PyInt_FromLong(type);
+#endif
+ struct module_state *st = GETMODSTATE();
+ zbarEnumItem *e = (zbarEnumItem *)PyDict_GetItem(st->symbol_enum, key);
+ if (!e)
+ return ((zbarEnumItem *)key);
+ Py_INCREF((PyObject *)e);
+ Py_DECREF(key);
+ return (e);
+}
diff --git a/python/symboliter.c b/python/symboliter.c
new file mode 100644
index 0000000..6ebd040
--- /dev/null
+++ b/python/symboliter.c
@@ -0,0 +1,103 @@
+/*------------------------------------------------------------------------
+ * 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 "zbarmodule.h"
+
+static char symboliter_doc[] =
+ PyDoc_STR("symbol iterator.\n"
+ "\n"
+ "iterates over decode results attached to an image.");
+
+static int symboliter_traverse(zbarSymbolIter *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->syms);
+ return (0);
+}
+
+static int symboliter_clear(zbarSymbolIter *self)
+{
+ if (self->zsym) {
+ zbar_symbol_t *zsym = (zbar_symbol_t *)self->zsym;
+ self->zsym = NULL;
+ zbar_symbol_ref(zsym, -1);
+ }
+ Py_CLEAR(self->syms);
+ return (0);
+}
+
+static void symboliter_dealloc(zbarSymbolIter *self)
+{
+ symboliter_clear(self);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static zbarSymbolIter *symboliter_iter(zbarSymbolIter *self)
+{
+ Py_INCREF(self);
+ return (self);
+}
+
+static zbarSymbol *symboliter_iternext(zbarSymbolIter *self)
+{
+ if (self->zsym) {
+ zbar_symbol_t *zsym = (zbar_symbol_t *)self->zsym;
+ zbar_symbol_ref(zsym, -1);
+ self->zsym = zbar_symbol_next(self->zsym);
+ } else if (self->syms->zsyms)
+ self->zsym = zbar_symbol_set_first_symbol(self->syms->zsyms);
+ else
+ self->zsym = NULL;
+
+ zbar_symbol_t *zsym = (zbar_symbol_t *)self->zsym;
+ if (!zsym)
+ return (NULL);
+ zbar_symbol_ref(zsym, 1);
+ return (zbarSymbol_FromSymbol(self->zsym));
+}
+
+PyTypeObject zbarSymbolIter_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.SymbolIter",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+
+ .tp_doc = symboliter_doc,
+ .tp_basicsize = sizeof(zbarSymbolIter),
+ .tp_traverse = (traverseproc)symboliter_traverse,
+ .tp_clear = (inquiry)symboliter_clear,
+ .tp_dealloc = (destructor)symboliter_dealloc,
+ .tp_iter = (getiterfunc)symboliter_iter,
+ .tp_iternext = (iternextfunc)symboliter_iternext,
+};
+
+zbarSymbolIter *zbarSymbolIter_FromSymbolSet(zbarSymbolSet *syms)
+{
+ zbarSymbolIter *self;
+ self = PyObject_GC_New(zbarSymbolIter, &zbarSymbolIter_Type);
+ if (!self)
+ return (NULL);
+
+ Py_INCREF(syms);
+ self->syms = syms;
+ self->zsym = NULL;
+ return (self);
+}
diff --git a/python/symbolset.c b/python/symbolset.c
new file mode 100644
index 0000000..9d65e80
--- /dev/null
+++ b/python/symbolset.c
@@ -0,0 +1,85 @@
+/*------------------------------------------------------------------------
+ * 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 "zbarmodule.h"
+
+static char symbolset_doc[] = PyDoc_STR("symbol result container.\n"
+ "\n"
+ "collection of symbols.");
+
+static int symbolset_clear(zbarSymbolSet *self)
+{
+ if (self->zsyms) {
+ zbar_symbol_set_t *zsyms = (zbar_symbol_set_t *)self->zsyms;
+ self->zsyms = NULL;
+ zbar_symbol_set_ref(zsyms, -1);
+ }
+ return (0);
+}
+
+static void symbolset_dealloc(zbarSymbolSet *self)
+{
+ symbolset_clear(self);
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self);
+}
+
+static zbarSymbolIter *symbolset_iter(zbarSymbolSet *self)
+{
+ return (zbarSymbolIter_FromSymbolSet(self));
+}
+
+Py_ssize_t symbolset_length(zbarSymbolSet *self)
+{
+ if (self->zsyms)
+ return (zbar_symbol_set_get_size(self->zsyms));
+ return (0);
+}
+
+static PySequenceMethods symbolset_as_sequence = {
+ .sq_length = (lenfunc)symbolset_length,
+};
+
+PyTypeObject zbarSymbolSet_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.SymbolSet",
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = symbolset_doc,
+ .tp_basicsize = sizeof(zbarSymbolSet),
+ .tp_dealloc = (destructor)symbolset_dealloc,
+ .tp_iter = (getiterfunc)symbolset_iter,
+ .tp_as_sequence = &symbolset_as_sequence,
+};
+
+zbarSymbolSet *zbarSymbolSet_FromSymbolSet(const zbar_symbol_set_t *zsyms)
+{
+ zbarSymbolSet *self = PyObject_New(zbarSymbolSet, &zbarSymbolSet_Type);
+ if (!self)
+ return (NULL);
+ if (zsyms) {
+ zbar_symbol_set_t *ncsyms = (zbar_symbol_set_t *)zsyms;
+ zbar_symbol_set_ref(ncsyms, 1);
+ }
+ self->zsyms = zsyms;
+ return (self);
+}
diff --git a/python/test/barcode.png b/python/test/barcode.png
new file mode 100644
index 0000000..72846ce
--- /dev/null
+++ b/python/test/barcode.png
Binary files differ
diff --git a/python/test/test_zbar.py b/python/test/test_zbar.py
new file mode 100755
index 0000000..5b63de4
--- /dev/null
+++ b/python/test/test_zbar.py
@@ -0,0 +1,506 @@
+#!/usr/bin/env python
+import sys, os, re
+import unittest as ut
+import zbar
+
+# FIXME this needs to be conditional
+# would be even better to auto-select PIL or ImageMagick (or...)
+from PIL import Image
+
+data = None
+size = (0, 0)
+
+def load_image():
+ image = Image.open(os.path.join(sys.path[0], "barcode.png")).convert('L')
+ return(image.tobytes(), image.size)
+
+# FIXME this could be integrated w/fixture creation
+(data, size) = load_image()
+
+encoded_widths = \
+ '9 111 212241113121211311141132 11111 311213121312121332111132 111 9'
+
+databar_widths = \
+ '11 31111333 13911 31131231 11214222 11553 21231313 1'
+
+VIDEO_DEVICE = None
+if 'VIDEO_DEVICE' in os.environ:
+ VIDEO_DEVICE = os.environ['VIDEO_DEVICE']
+
+is_identifier = re.compile(r'^[A-Z][A-Z_0-9]*$')
+
+class TestZBarFunctions(ut.TestCase):
+ def test_version(self):
+ ver = zbar.version()
+ self.assertTrue(isinstance(ver, tuple))
+ self.assertEqual(len(ver), 2)
+ for v in ver:
+ self.assertTrue(isinstance(v, int))
+
+ def test_verbosity(self):
+ zbar.increase_verbosity()
+ zbar.set_verbosity(16)
+
+ def test_exceptions(self):
+ self.assertTrue(isinstance(zbar.Exception, type))
+ for err in (zbar.InternalError,
+ zbar.UnsupportedError,
+ zbar.InvalidRequestError,
+ zbar.SystemError,
+ zbar.LockingError,
+ zbar.BusyError,
+ zbar.X11DisplayError,
+ zbar.X11ProtocolError,
+ zbar.WindowClosed,
+ zbar.WinAPIError):
+ self.assertTrue(issubclass(err, zbar.Exception))
+
+ def test_configs(self):
+ for cfg in (zbar.Config.ENABLE,
+ zbar.Config.ADD_CHECK,
+ zbar.Config.EMIT_CHECK,
+ zbar.Config.ASCII,
+ zbar.Config.MIN_LEN,
+ zbar.Config.MAX_LEN,
+ zbar.Config.UNCERTAINTY,
+ zbar.Config.POSITION,
+ zbar.Config.X_DENSITY,
+ zbar.Config.Y_DENSITY):
+ self.assertTrue(isinstance(cfg, zbar.EnumItem))
+ self.assertTrue(int(cfg) >= 0)
+ self.assertTrue(is_identifier.match(str(cfg)))
+
+ def test_modifiers(self):
+ for mod in (zbar.Modifier.GS1,
+ zbar.Modifier.AIM):
+ self.assertTrue(isinstance(mod, zbar.EnumItem))
+ self.assertTrue(int(mod) >= 0)
+ self.assertTrue(is_identifier.match(str(mod)))
+
+ def test_symbologies(self):
+ for sym in (zbar.Symbol.NONE,
+ zbar.Symbol.PARTIAL,
+ zbar.Symbol.EAN8,
+ zbar.Symbol.UPCE,
+ zbar.Symbol.ISBN10,
+ zbar.Symbol.UPCA,
+ zbar.Symbol.EAN13,
+ zbar.Symbol.ISBN13,
+ zbar.Symbol.DATABAR,
+ zbar.Symbol.DATABAR_EXP,
+ zbar.Symbol.I25,
+ zbar.Symbol.CODABAR,
+ zbar.Symbol.CODE39,
+ zbar.Symbol.PDF417,
+ zbar.Symbol.QRCODE,
+ zbar.Symbol.CODE93,
+ zbar.Symbol.CODE128):
+ self.assertTrue(isinstance(sym, zbar.EnumItem))
+ self.assertTrue(int(sym) >= 0)
+ self.assertTrue(is_identifier.match(str(sym)))
+
+ def test_orientations(self):
+ for orient in (zbar.Orient.UNKNOWN,
+ zbar.Orient.UP,
+ zbar.Orient.RIGHT,
+ zbar.Orient.DOWN,
+ zbar.Orient.LEFT):
+ self.assertTrue(isinstance(orient, zbar.EnumItem))
+ self.assertTrue(-1 <= int(orient) <= 3)
+ self.assertTrue(is_identifier.match(str(orient)))
+
+class TestScanner(ut.TestCase):
+ def setUp(self):
+ self.scn = zbar.Scanner()
+
+ def tearDown(self):
+ del(self.scn)
+
+ def test_type(self):
+ self.assertTrue(isinstance(self.scn, zbar.Scanner))
+ self.assertTrue(callable(self.scn.reset))
+ self.assertTrue(callable(self.scn.new_scan))
+ self.assertTrue(callable(self.scn.scan_y))
+
+ def set_color(color):
+ self.scn.color = color
+ self.assertRaises(AttributeError, set_color, zbar.BAR)
+
+ def set_width(width):
+ self.scn.width = width
+ self.assertRaises(AttributeError, set_width, 1)
+
+ # FIXME more scanner tests
+
+class TestDecoder(ut.TestCase):
+ def setUp(self):
+ self.dcode = zbar.Decoder()
+
+ def tearDown(self):
+ del(self.dcode)
+
+ def test_type(self):
+ self.assertTrue(isinstance(self.dcode, zbar.Decoder))
+ self.assertTrue(callable(self.dcode.set_config))
+ self.assertTrue(callable(self.dcode.parse_config))
+ self.assertTrue(callable(self.dcode.reset))
+ self.assertTrue(callable(self.dcode.new_scan))
+ self.assertTrue(callable(self.dcode.set_handler))
+ self.assertTrue(callable(self.dcode.decode_width))
+
+ def set_type(typ):
+ self.dcode.type = typ
+ self.assertRaises(AttributeError, set_type, zbar.Symbol.CODE128)
+
+ def set_color(color):
+ self.dcode.color = color
+ self.assertRaises(AttributeError, set_color, zbar.BAR)
+
+ def set_data(data):
+ self.dcode.data = data
+ self.assertRaises(AttributeError, set_data, 'yomama')
+
+ self.assertRaises(AttributeError,
+ self.dcode.__setattr__, 'direction', -1)
+
+ def test_width(self):
+ sym = self.dcode.decode_width(5)
+ self.assertTrue(sym is zbar.Symbol.NONE)
+ self.assertTrue(not sym)
+ self.assertEqual(str(sym), 'NONE')
+
+ typ = self.dcode.type
+ self.assertTrue(sym is typ)
+
+ def test_reset(self):
+ self.assertTrue(self.dcode.color is zbar.SPACE)
+ sym = self.dcode.decode_width(1)
+ self.assertTrue(self.dcode.color is zbar.BAR)
+ self.dcode.reset()
+ self.assertTrue(self.dcode.color is zbar.SPACE)
+ self.assertEqual(self.dcode.direction, 0)
+
+ def test_decode(self):
+ inline_sym = [ -1 ]
+ def handler(dcode, closure):
+ self.assertTrue(dcode is self.dcode)
+ if dcode.type > zbar.Symbol.PARTIAL:
+ inline_sym[0] = dcode.type
+ closure[0] += 1
+
+ explicit_closure = [ 0 ]
+ self.dcode.set_handler(handler, explicit_closure)
+ self.dcode.set_config(zbar.Symbol.QRCODE, zbar.Config.ENABLE, 0)
+
+ for (i, width) in enumerate(encoded_widths):
+ if width == ' ': continue
+ sym = self.dcode.decode_width(int(width))
+ if i < len(encoded_widths) - 1:
+ self.assertTrue(sym is zbar.Symbol.NONE or
+ sym is zbar.Symbol.PARTIAL)
+ else:
+ self.assertTrue(sym is zbar.Symbol.EAN13)
+
+ self.assertEqual(self.dcode.configs,
+ set((zbar.Config.ENABLE, zbar.Config.EMIT_CHECK)))
+ self.assertEqual(self.dcode.modifiers, set())
+ self.assertEqual(self.dcode.data, '6268964977804')
+ self.assertTrue(self.dcode.color is zbar.BAR)
+ self.assertEqual(self.dcode.direction, 1)
+ self.assertTrue(sym is zbar.Symbol.EAN13)
+ self.assertTrue(inline_sym[0] is zbar.Symbol.EAN13)
+ self.assertEqual(explicit_closure, [ 2 ])
+
+ def test_databar(self):
+ self.dcode.set_config(zbar.Symbol.QRCODE, zbar.Config.ENABLE, 0)
+ for (i, width) in enumerate(databar_widths):
+ if width == ' ': continue
+ sym = self.dcode.decode_width(int(width))
+ if i < len(databar_widths) - 1:
+ self.assertTrue(sym is zbar.Symbol.NONE or
+ sym is zbar.Symbol.PARTIAL)
+
+ self.assertTrue(sym is zbar.Symbol.DATABAR)
+ self.assertEqual(self.dcode.get_configs(zbar.Symbol.EAN13),
+ set((zbar.Config.ENABLE, zbar.Config.EMIT_CHECK)))
+ self.assertEqual(self.dcode.modifiers, set((zbar.Modifier.GS1,)))
+ self.assertEqual(self.dcode.data, '0124012345678905')
+ self.assertTrue(self.dcode.color is zbar.BAR)
+ self.assertEqual(self.dcode.direction, 1)
+
+ # FIXME test exception during callback
+
+class TestImage(ut.TestCase):
+ def setUp(self):
+ self.image = zbar.Image(123, 456, 'Y800')
+
+ def tearDown(self):
+ del(self.image)
+
+ def test_type(self):
+ self.assertTrue(isinstance(self.image, zbar.Image))
+ self.assertTrue(callable(self.image.convert))
+
+ def test_new(self):
+ self.assertEqual(self.image.format, 'Y800')
+ self.assertEqual(self.image.size, (123, 456))
+ self.assertEqual(self.image.crop, (0, 0, 123, 456))
+
+ image = zbar.Image()
+ self.assertTrue(isinstance(image, zbar.Image))
+ self.assertEqual(image.format, '\0\0\0\0')
+ self.assertEqual(image.size, (0, 0))
+ self.assertEqual(image.crop, (0, 0, 0, 0))
+
+ def test_format(self):
+ def set_format(fmt):
+ self.image.format = fmt
+ self.assertRaises(ValueError, set_format, 10)
+ self.assertEqual(self.image.format, 'Y800')
+ self.image.format = 'gOOb'
+ self.assertEqual(self.image.format, 'gOOb')
+ self.assertRaises(ValueError, set_format, 'yomama')
+ self.assertEqual(self.image.format, 'gOOb')
+ self.assertRaises(ValueError, set_format, 'JPG')
+ self.assertEqual(self.image.format, 'gOOb')
+
+ def test_size(self):
+ def set_size(sz):
+ self.image.size = sz
+ self.assertRaises(ValueError, set_size, (1,))
+ self.assertRaises(ValueError, set_size, 1)
+ self.image.size = (12, 6)
+ self.assertRaises(ValueError, set_size, (1, 2, 3))
+ self.assertEqual(self.image.size, (12, 6))
+ self.assertRaises(ValueError, set_size, "foo")
+ self.assertEqual(self.image.size, (12, 6))
+ self.assertEqual(self.image.width, 12)
+ self.assertEqual(self.image.height, 6)
+ self.image.width = 81
+ self.assertEqual(self.image.size, (81, 6))
+ self.image.height = 64
+ self.assertEqual(self.image.size, (81, 64))
+ self.assertEqual(self.image.width, 81)
+ self.assertEqual(self.image.height, 64)
+
+ def test_crop(self):
+ def set_crop(crp):
+ self.image.crop = crp
+ self.assertRaises(ValueError, set_crop, (1,))
+ self.assertRaises(ValueError, set_crop, 1)
+ self.image.crop = (1, 2, 100, 200)
+ self.assertRaises(ValueError, set_crop, (1, 2, 3, 4, 5))
+ self.assertEqual(self.image.crop, (1, 2, 100, 200))
+ self.assertRaises(ValueError, set_crop, "foo")
+ self.assertEqual(self.image.crop, (1, 2, 100, 200))
+ self.image.crop = (-100, -100, 400, 700)
+ self.assertEqual(self.image.crop, (0, 0, 123, 456))
+ self.image.crop = (40, 50, 60, 70)
+ self.assertEqual(self.image.crop, (40, 50, 60, 70))
+ self.image.size = (82, 65)
+ self.assertEqual(self.image.crop, (0, 0, 82, 65))
+
+class TestImageScanner(ut.TestCase):
+ def setUp(self):
+ self.scn = zbar.ImageScanner()
+
+ def tearDown(self):
+ del(self.scn)
+
+ def test_type(self):
+ self.assertTrue(isinstance(self.scn, zbar.ImageScanner))
+ self.assertTrue(callable(self.scn.set_config))
+ self.assertTrue(callable(self.scn.parse_config))
+ self.assertTrue(callable(self.scn.enable_cache))
+ self.assertTrue(callable(self.scn.scan))
+
+ def test_set_config(self):
+ self.scn.set_config()
+ self.assertRaises(ValueError, self.scn.set_config, -1)
+ self.assertRaises(TypeError, self.scn.set_config, "yomama")
+ self.scn.set_config()
+
+ def test_parse_config(self):
+ self.scn.parse_config("disable")
+ self.assertRaises(ValueError, self.scn.set_config, -1)
+ self.scn.set_config()
+
+class TestImageScan(ut.TestCase):
+ def setUp(self):
+ self.scn = zbar.ImageScanner()
+ self.image = zbar.Image(size[0], size[1], 'Y800', data)
+
+ def tearDown(self):
+ del(self.image)
+ del(self.scn)
+
+ def test_scan(self):
+ n = self.scn.scan(self.image)
+ self.assertEqual(n, 1)
+
+ syms = self.image.symbols
+ self.assertTrue(isinstance(syms, zbar.SymbolSet))
+ self.assertEqual(len(syms), 1)
+
+ i = iter(self.image)
+ j = iter(syms)
+ self.assertTrue(isinstance(i, zbar.SymbolIter))
+ self.assertTrue(isinstance(j, zbar.SymbolIter))
+ symi = next(i)
+ symj = next(j)
+ self.assertRaises(StopIteration, i.__next__)
+ self.assertRaises(StopIteration, j.__next__)
+
+ # this is the only way to obtain a Symbol,
+ # so test Symbol here
+ for sym in (symi, symj):
+ self.assertTrue(isinstance(sym, zbar.Symbol))
+ self.assertTrue(sym.type is zbar.Symbol.EAN13)
+ self.assertTrue(sym.type is sym.EAN13)
+ self.assertEqual(str(sym.type), 'EAN13')
+
+ cfgs = sym.configs
+ self.assertTrue(isinstance(cfgs, set))
+ for cfg in cfgs:
+ self.assertTrue(isinstance(cfg, zbar.EnumItem))
+ self.assertEqual(cfgs,
+ set((zbar.Config.ENABLE, zbar.Config.EMIT_CHECK)))
+
+ mods = sym.modifiers
+ self.assertTrue(isinstance(mods, set))
+ for mod in mods:
+ self.assertTrue(isinstance(mod, zbar.EnumItem))
+ self.assertEqual(mods, set())
+
+ self.assertTrue(sym.quality > 0)
+ self.assertEqual(sym.count, 0)
+
+ # FIXME put a nice QR S-A in here
+ comps = sym.components
+ self.assertTrue(isinstance(comps, zbar.SymbolSet))
+ self.assertEqual(len(comps), 0)
+ self.assertTrue(not comps)
+ self.assertTrue(tuple(comps) is ())
+
+ data = sym.data
+ self.assertEqual(data, '9876543210128')
+
+ loc = sym.location
+ self.assertTrue(len(loc) >= 4) # FIXME
+ self.assertTrue(isinstance(loc, tuple))
+ for pt in loc:
+ self.assertTrue(isinstance(pt, tuple))
+ self.assertEqual(len(pt), 2)
+ # FIXME test values (API currently in flux)
+
+ self.assertTrue(sym.orientation is zbar.Orient.UP)
+ self.assertTrue(data is sym.data)
+ self.assertTrue(loc is sym.location)
+
+ def set_symbols(syms):
+ self.image.symbols = syms
+ self.assertRaises(TypeError, set_symbols, ())
+
+ self.scn.recycle(self.image)
+ self.assertEqual(len(self.image.symbols), 0)
+
+ def test_scan_crop(self):
+ self.image.crop = (0, 71, 114, 9)
+ self.assertEqual(self.image.crop, (0, 71, 114, 9))
+ n = self.scn.scan(self.image)
+ self.assertEqual(n, 0)
+
+ self.image.crop = (12, 24, 90, 12)
+ self.assertEqual(self.image.crop, (12, 24, 90, 12))
+ n = self.scn.scan(self.image)
+ self.assertEqual(n, 0)
+
+ self.image.crop = (9, 24, 96, 12)
+ self.assertEqual(self.image.crop, (9, 24, 96, 12))
+ self.test_scan()
+
+ def test_scan_again(self):
+ self.test_scan()
+
+class TestProcessor(ut.TestCase):
+ def setUp(self):
+ self.proc = zbar.Processor()
+
+ def tearDown(self):
+ del(self.proc)
+
+ def test_type(self):
+ self.assertTrue(isinstance(self.proc, zbar.Processor))
+ self.assertTrue(callable(self.proc.init))
+ self.assertTrue(callable(self.proc.set_config))
+ self.assertTrue(callable(self.proc.parse_config))
+ self.assertTrue(callable(self.proc.set_data_handler))
+ self.assertTrue(callable(self.proc.user_wait))
+ self.assertTrue(callable(self.proc.process_one))
+ self.assertTrue(callable(self.proc.process_image))
+
+ def test_set_config(self):
+ self.proc.set_config()
+ self.assertRaises(ValueError, self.proc.set_config, -1)
+ self.assertRaises(TypeError, self.proc.set_config, "yomama")
+ self.proc.set_config()
+
+ def test_parse_config(self):
+ self.proc.parse_config("disable")
+ self.assertRaises(ValueError, self.proc.set_config, -1)
+ self.proc.set_config()
+
+ def test_request_size(self):
+ def set_size(sz):
+ self.proc.request_size = sz
+ self.assertRaises(ValueError, set_size, (1,))
+ self.assertRaises(ValueError, set_size, 1)
+ self.proc.request_size = (12, 6)
+ self.assertRaises(ValueError, set_size, (1, 2, 3))
+ self.assertRaises(ValueError, set_size, "foo")
+
+ def test_processing(self):
+ self.proc.init(VIDEO_DEVICE)
+ self.assertTrue(self.proc.visible is False)
+ self.proc.visible = 1
+ self.assertTrue(self.proc.visible is True)
+ self.assertEqual(self.proc.user_wait(1.1), 0)
+
+ self.image = zbar.Image(size[0], size[1], 'Y800', data)
+
+ count = [ 0 ]
+ def data_handler(proc, image, closure):
+ self.assertTrue(proc is self.proc)
+ self.assertTrue(image is self.image)
+ self.assertEqual(count[0], 0)
+ count[0] += 1
+
+ symiter = iter(image)
+ self.assertTrue(isinstance(symiter, zbar.SymbolIter))
+
+ syms = tuple(image)
+ self.assertEqual(len(syms), 1)
+ for sym in syms:
+ self.assertTrue(isinstance(sym, zbar.Symbol))
+ self.assertTrue(sym.type is zbar.Symbol.EAN13)
+ self.assertEqual(sym.data, '9876543210128')
+ self.assertTrue(sym.quality > 0)
+ self.assertTrue(sym.orientation is zbar.Orient.UP)
+ closure[0] += 1
+
+ explicit_closure = [ 0 ]
+ self.proc.set_data_handler(data_handler, explicit_closure)
+
+ rc = self.proc.process_image(self.image)
+ self.assertEqual(rc, 0)
+ self.assertEqual(len(self.image.symbols), 1)
+ del(self.image.symbols)
+ self.assertEqual(len(self.image.symbols), 0)
+
+ self.assertEqual(self.proc.user_wait(.9), 0)
+
+ self.assertEqual(explicit_closure, [ 1 ])
+ self.proc.set_data_handler()
+
+if __name__ == '__main__':
+ ut.main()
diff --git a/python/zbarmodule.c b/python/zbarmodule.c
new file mode 100644
index 0000000..e8e68ef
--- /dev/null
+++ b/python/zbarmodule.c
@@ -0,0 +1,340 @@
+/*------------------------------------------------------------------------
+ * Copyright 2009-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
+ *------------------------------------------------------------------------*/
+
+#include "zbarmodule.h"
+
+typedef struct enumdef {
+ const char *strval;
+ int intval;
+} enumdef;
+
+static char *exc_names[] = {
+ "zbar.Exception", NULL,
+ "zbar.InternalError", "zbar.UnsupportedError",
+ "zbar.InvalidRequestError", "zbar.SystemError",
+ "zbar.LockingError", "zbar.BusyError",
+ "zbar.X11DisplayError", "zbar.X11ProtocolError",
+ "zbar.WindowClosed", "zbar.WinAPIError",
+};
+
+static const enumdef symbol_defs[] = { { "NONE", ZBAR_NONE },
+ { "PARTIAL", ZBAR_PARTIAL },
+ { "EAN8", ZBAR_EAN8 },
+ { "UPCE", ZBAR_UPCE },
+ { "ISBN10", ZBAR_ISBN10 },
+ { "UPCA", ZBAR_UPCA },
+ { "EAN13", ZBAR_EAN13 },
+ { "ISBN13", ZBAR_ISBN13 },
+ { "DATABAR", ZBAR_DATABAR },
+ { "DATABAR_EXP", ZBAR_DATABAR_EXP },
+ { "I25", ZBAR_I25 },
+ { "CODABAR", ZBAR_CODABAR },
+ { "CODE39", ZBAR_CODE39 },
+ { "PDF417", ZBAR_PDF417 },
+ { "QRCODE", ZBAR_QRCODE },
+ { "SQCODE", ZBAR_SQCODE },
+ { "CODE93", ZBAR_CODE93 },
+ { "CODE128", ZBAR_CODE128 },
+ {
+ NULL,
+ } };
+
+static const enumdef config_defs[] = { { "ENABLE", ZBAR_CFG_ENABLE },
+ { "ADD_CHECK", ZBAR_CFG_ADD_CHECK },
+ { "EMIT_CHECK", ZBAR_CFG_EMIT_CHECK },
+ { "ASCII", ZBAR_CFG_ASCII },
+ { "BINARY", ZBAR_CFG_BINARY },
+ { "MIN_LEN", ZBAR_CFG_MIN_LEN },
+ { "MAX_LEN", ZBAR_CFG_MAX_LEN },
+ { "UNCERTAINTY", ZBAR_CFG_UNCERTAINTY },
+ { "POSITION", ZBAR_CFG_POSITION },
+ { "X_DENSITY", ZBAR_CFG_X_DENSITY },
+ { "Y_DENSITY", ZBAR_CFG_Y_DENSITY },
+ {
+ NULL,
+ } };
+
+static const enumdef modifier_defs[] = { { "GS1", ZBAR_MOD_GS1 },
+ { "AIM", ZBAR_MOD_AIM },
+ {
+ NULL,
+ } };
+
+static const enumdef orient_defs[] = { { "UNKNOWN", ZBAR_ORIENT_UNKNOWN },
+ { "UP", ZBAR_ORIENT_UP },
+ { "RIGHT", ZBAR_ORIENT_RIGHT },
+ { "DOWN", ZBAR_ORIENT_DOWN },
+ { "LEFT", ZBAR_ORIENT_LEFT },
+ {
+ NULL,
+ } };
+
+#if PY_MAJOR_VERSION < 3
+struct module_state zbar_state;
+#endif
+
+int object_to_bool(PyObject *obj, int *val)
+{
+ int tmp = PyObject_IsTrue(obj);
+ if (tmp < 0)
+ return (0);
+ *val = tmp;
+ return (1);
+}
+
+int parse_dimensions(PyObject *seq, int *dims, int n)
+{
+ if (!PySequence_Check(seq) || PySequence_Size(seq) != n)
+ return (-1);
+
+ int i;
+ for (i = 0; i < n; i++, dims++) {
+ PyObject *dim = PySequence_GetItem(seq, i);
+ if (!dim)
+ return (-1);
+#if PY_MAJOR_VERSION >= 3
+ *dims = PyLong_AsSsize_t(dim);
+#else
+ *dims = PyInt_AsSsize_t(dim);
+#endif
+ Py_DECREF(dim);
+ if (*dims == -1 && PyErr_Occurred())
+ return (-1);
+ }
+ return (0);
+}
+
+static PyObject *version(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return (NULL);
+
+ unsigned int major, minor, patch;
+ zbar_version(&major, &minor, &patch);
+
+ return (Py_BuildValue("III", major, minor, patch));
+}
+
+static PyObject *set_verbosity(PyObject *self, PyObject *args)
+{
+ int verbosity;
+ if (!PyArg_ParseTuple(args, "i", &verbosity))
+ return (NULL);
+
+ zbar_set_verbosity(verbosity);
+
+ Py_INCREF(Py_None);
+ return (Py_None);
+}
+
+static PyObject *increase_verbosity(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return (NULL);
+
+ zbar_increase_verbosity();
+
+ Py_INCREF(Py_None);
+ return (Py_None);
+}
+
+static PyMethodDef zbar_functions[] = {
+ { "version", version, METH_VARARGS, NULL },
+ { "set_verbosity", set_verbosity, METH_VARARGS, NULL },
+ { "increase_verbosity", increase_verbosity, METH_VARARGS, NULL },
+ {
+ NULL,
+ },
+};
+
+#if PY_MAJOR_VERSION >= 3
+
+static int zbar_traverse(PyObject *m, visitproc visit, void *arg)
+{
+ Py_VISIT(GETSTATE(m)->zbar_exc[0]);
+ return 0;
+}
+
+static int zbar_clear(PyObject *m)
+{
+ Py_CLEAR(GETSTATE(m)->zbar_exc[0]);
+ return 0;
+}
+
+struct PyModuleDef zbar_moduledef = { PyModuleDef_HEAD_INIT,
+ "zbar",
+ NULL,
+ sizeof(struct module_state),
+ zbar_functions,
+ NULL,
+ zbar_traverse,
+ zbar_clear,
+ NULL };
+
+#define INITERROR return NULL
+
+PyMODINIT_FUNC PyInit_zbar(void)
+
+#else
+#define INITERROR return
+
+PyMODINIT_FUNC initzbar(void)
+#endif
+{
+#if PY_MAJOR_VERSION >= 3
+ /* initialize types */
+ zbarEnumItem_Type.tp_base = &PyLong_Type;
+#else
+ zbarEnumItem_Type.tp_base = &PyInt_Type;
+ zbarException_Type.tp_base = (PyTypeObject *)PyExc_Exception;
+
+ if (PyType_Ready(&zbarException_Type) < 0)
+ INITERROR;
+#endif
+
+ if (PyType_Ready(&zbarEnumItem_Type) < 0 ||
+ PyType_Ready(&zbarEnum_Type) < 0 || PyType_Ready(&zbarImage_Type) < 0 ||
+ PyType_Ready(&zbarSymbol_Type) < 0 ||
+ PyType_Ready(&zbarSymbolSet_Type) < 0 ||
+ PyType_Ready(&zbarSymbolIter_Type) < 0 ||
+ PyType_Ready(&zbarProcessor_Type) < 0 ||
+ PyType_Ready(&zbarImageScanner_Type) < 0 ||
+ PyType_Ready(&zbarDecoder_Type) < 0 ||
+ PyType_Ready(&zbarScanner_Type) < 0)
+ INITERROR;
+
+ /* initialize module */
+#if PY_MAJOR_VERSION >= 3
+ PyObject *mod = PyModule_Create(&zbar_moduledef);
+#else
+ PyObject *mod = Py_InitModule("zbar", zbar_functions);
+#endif
+ if (!mod)
+ INITERROR;
+
+#if PY_MAJOR_VERSION >= 3
+ if (PyState_AddModule(mod, &zbar_moduledef)) {
+ Py_DECREF(mod);
+ INITERROR;
+ }
+#endif
+
+ struct module_state *st = GETSTATE(mod);
+
+ /* initialize constant containers */
+ st->config_enum = zbarEnum_New();
+ st->modifier_enum = zbarEnum_New();
+ st->symbol_enum = PyDict_New();
+ st->orient_enum = zbarEnum_New();
+ if (!st->config_enum || !st->modifier_enum || !st->symbol_enum ||
+ !st->orient_enum) {
+ Py_DECREF(mod);
+ INITERROR;
+ }
+
+ /* internally created/read-only type overrides */
+ zbarEnum_Type.tp_new = NULL;
+ zbarEnum_Type.tp_setattr = NULL;
+ zbarEnum_Type.tp_setattro = NULL;
+
+ /* zbar internal exception objects */
+#if PY_MAJOR_VERSION >= 3
+ st->zbar_exc[0] = PyErr_NewException("zbar.Exception", NULL, NULL);
+#else
+ st->zbar_exc[0] = (PyObject *)&zbarException_Type;
+#endif
+ if (st->zbar_exc[0] == NULL) {
+ Py_DECREF(mod);
+ INITERROR;
+ }
+
+ st->zbar_exc[ZBAR_ERR_NOMEM] = NULL;
+ zbar_error_t ei;
+ for (ei = ZBAR_ERR_INTERNAL; ei < ZBAR_ERR_NUM; ei++) {
+ st->zbar_exc[ei] =
+ PyErr_NewException(exc_names[ei], st->zbar_exc[0], NULL);
+ if (!st->zbar_exc[ei]) {
+ Py_DECREF(mod);
+ INITERROR;
+ }
+ }
+
+ /* add types to module */
+ PyModule_AddObject(mod, "EnumItem", (PyObject *)&zbarEnumItem_Type);
+ PyModule_AddObject(mod, "Image", (PyObject *)&zbarImage_Type);
+ PyModule_AddObject(mod, "Config", (PyObject *)st->config_enum);
+ PyModule_AddObject(mod, "Modifier", (PyObject *)st->modifier_enum);
+ PyModule_AddObject(mod, "Orient", (PyObject *)st->orient_enum);
+ PyModule_AddObject(mod, "Symbol", (PyObject *)&zbarSymbol_Type);
+ PyModule_AddObject(mod, "SymbolSet", (PyObject *)&zbarSymbolSet_Type);
+ PyModule_AddObject(mod, "SymbolIter", (PyObject *)&zbarSymbolIter_Type);
+ PyModule_AddObject(mod, "Processor", (PyObject *)&zbarProcessor_Type);
+ PyModule_AddObject(mod, "ImageScanner", (PyObject *)&zbarImageScanner_Type);
+ PyModule_AddObject(mod, "Decoder", (PyObject *)&zbarDecoder_Type);
+ PyModule_AddObject(mod, "Scanner", (PyObject *)&zbarScanner_Type);
+
+ for (ei = 0; ei < ZBAR_ERR_NUM; ei++)
+ if (st->zbar_exc[ei])
+ PyModule_AddObject(mod, exc_names[ei] + 5, st->zbar_exc[ei]);
+
+ /* add constants */
+ PyObject *dict = PyModule_GetDict(mod);
+ st->color_enum[ZBAR_SPACE] =
+ zbarEnumItem_New(dict, NULL, ZBAR_SPACE, "SPACE");
+ st->color_enum[ZBAR_BAR] = zbarEnumItem_New(dict, NULL, ZBAR_BAR, "BAR");
+
+ const enumdef *item;
+ for (item = config_defs; item->strval; item++)
+ zbarEnum_Add(st->config_enum, item->intval, item->strval);
+ for (item = modifier_defs; item->strval; item++)
+ zbarEnum_Add(st->modifier_enum, item->intval, item->strval);
+ for (item = orient_defs; item->strval; item++)
+ zbarEnum_Add(st->orient_enum, item->intval, item->strval);
+
+ PyObject *tp_dict = zbarSymbol_Type.tp_dict;
+ for (item = symbol_defs; item->strval; item++)
+ zbarEnumItem_New(tp_dict, st->symbol_enum, item->intval, item->strval);
+ st->symbol_NONE = zbarSymbol_LookupEnum(ZBAR_NONE);
+
+#if PY_MAJOR_VERSION >= 3
+ return mod;
+#endif
+}
+
+PyObject *zbarErr_Set(PyObject *self)
+{
+ const void *zobj = ((zbarProcessor *)self)->zproc;
+ zbar_error_t err = _zbar_get_error_code(zobj);
+
+ struct module_state *st = GETMODSTATE();
+
+ if (err == ZBAR_ERR_NOMEM)
+ PyErr_NoMemory();
+ else if (err < ZBAR_ERR_NUM) {
+ PyObject *type = st->zbar_exc[err];
+ assert(type);
+ PyErr_SetObject(type, self);
+ } else
+ PyErr_SetObject(st->zbar_exc[0], self);
+ return (NULL);
+}
diff --git a/python/zbarmodule.h b/python/zbarmodule.h
new file mode 100644
index 0000000..d61c381
--- /dev/null
+++ b/python/zbarmodule.h
@@ -0,0 +1,164 @@
+/*------------------------------------------------------------------------
+ * Copyright 2009-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
+ *------------------------------------------------------------------------*/
+
+#include <Python.h>
+#include <stddef.h>
+#include <zbar.h>
+
+#ifndef _ZBARMODULE_H_
+#define _ZBARMODULE_H_
+
+#if PY_MAJOR_VERSION < 3
+typedef struct {
+ PyBaseExceptionObject base;
+ PyObject *obj;
+} zbarException;
+
+extern PyTypeObject zbarException_Type;
+#endif
+
+extern struct PyModuleDef zbar_moduledef;
+
+#if PY_MAJOR_VERSION >= 3
+#define GETSTATE(m) ((struct module_state *)PyModule_GetState(m))
+#define GETMODSTATE() (GETSTATE(PyState_FindModule(&zbar_moduledef)))
+#else
+extern struct module_state zbar_state;
+#define GETSTATE(m) (&zbar_state)
+#define GETMODSTATE() (&zbar_state)
+#endif
+
+extern PyObject *zbarErr_Set(PyObject *self);
+
+typedef struct {
+#if PY_MAJOR_VERSION >= 3
+ PyLongObject val; /* parent type is the long type */
+#else
+ PyIntObject val; /* integer value is super type */
+#endif
+ PyObject *name; /* associated string name */
+} zbarEnumItem;
+
+extern PyTypeObject zbarEnumItem_Type;
+
+extern zbarEnumItem *zbarEnumItem_New(PyObject *byname, PyObject *byvalue,
+ int val, const char *name);
+
+typedef struct {
+ PyObject_HEAD PyObject *byname,
+ *byvalue; /* zbarEnumItem content dictionaries */
+} zbarEnum;
+
+extern PyTypeObject zbarEnum_Type;
+
+extern zbarEnum *zbarEnum_New(void);
+extern int zbarEnum_Add(zbarEnum *self, int val, const char *name);
+extern zbarEnumItem *zbarEnum_LookupValue(zbarEnum *self, int val);
+extern PyObject *zbarEnum_SetFromMask(zbarEnum *self, unsigned int mask);
+
+typedef struct {
+ PyObject_HEAD zbar_image_t *zimg;
+ PyObject *data;
+} zbarImage;
+
+extern PyTypeObject zbarImage_Type;
+
+extern zbarImage *zbarImage_FromImage(zbar_image_t *zimg);
+extern int zbarImage_validate(zbarImage *image);
+
+typedef struct {
+ PyObject_HEAD const zbar_symbol_set_t *zsyms;
+} zbarSymbolSet;
+
+extern PyTypeObject zbarSymbolSet_Type;
+
+extern zbarSymbolSet *
+zbarSymbolSet_FromSymbolSet(const zbar_symbol_set_t *zsyms);
+
+#define zbarSymbolSet_Check(obj) PyObject_TypeCheck(obj, &zbarSymbolSet_Type)
+
+typedef struct {
+ PyObject_HEAD const zbar_symbol_t *zsym;
+ PyObject *data;
+ PyObject *loc;
+} zbarSymbol;
+
+extern PyTypeObject zbarSymbol_Type;
+
+extern zbarSymbol *zbarSymbol_FromSymbol(const zbar_symbol_t *zsym);
+extern zbarEnumItem *zbarSymbol_LookupEnum(zbar_symbol_type_t type);
+
+typedef struct {
+ PyObject_HEAD const zbar_symbol_t *zsym;
+ zbarSymbolSet *syms;
+} zbarSymbolIter;
+
+extern PyTypeObject zbarSymbolIter_Type;
+
+extern zbarSymbolIter *zbarSymbolIter_FromSymbolSet(zbarSymbolSet *syms);
+
+typedef struct {
+ PyObject_HEAD zbar_processor_t *zproc;
+ PyObject *handler;
+ PyObject *closure;
+} zbarProcessor;
+
+extern PyTypeObject zbarProcessor_Type;
+
+#define zbarProcessor_Check(obj) PyObject_TypeCheck(obj, &zbarProcessor_Type)
+
+typedef struct {
+ PyObject_HEAD zbar_image_scanner_t *zscn;
+} zbarImageScanner;
+
+extern PyTypeObject zbarImageScanner_Type;
+
+typedef struct {
+ PyObject_HEAD zbar_decoder_t *zdcode;
+ PyObject *handler;
+ PyObject *args;
+} zbarDecoder;
+
+extern PyTypeObject zbarDecoder_Type;
+
+typedef struct {
+ PyObject_HEAD zbar_scanner_t *zscn;
+ zbarDecoder *decoder;
+} zbarScanner;
+
+extern PyTypeObject zbarScanner_Type;
+
+extern int object_to_bool(PyObject *obj, int *val);
+extern int parse_dimensions(PyObject *seq, int *dims, int n);
+
+struct module_state {
+ PyObject *zbar_exc[ZBAR_ERR_NUM];
+ zbarEnumItem *color_enum[2];
+ zbarEnum *config_enum;
+ zbarEnum *modifier_enum;
+ PyObject *symbol_enum;
+ zbarEnumItem *symbol_NONE;
+ zbarEnum *orient_enum;
+};
+
+#endif