Skip to content

Commit

Permalink
Expose "multi" as an API option.
Browse files Browse the repository at this point in the history
ZXing has multiple detectors available.
The two main ones, judging from their own CLI,
are GenericMultipleBarcodeReader and MultiFormatReader.

On my system, GenericMultipleBarcodeReader
is crashing (#5),
so I would like the option to use the other one.
  • Loading branch information
kousu authored and lubo committed Mar 20, 2019
1 parent 99abb09 commit 780c654
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 14 deletions.
17 changes: 14 additions & 3 deletions tests/test_read_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,18 @@ def test_two_qr_code(self):
'first zxinglight test qr code', 'second zxinglight test qr code'
])

def test_finding_one_of_two_qr_code(self):
self.assertEqual(
read_codes(get_image('two_qr_codes'), multi=False), ['first zxinglight test qr code'],
)

def test_small_rotated_qr_code(self):
self.assertEqual(read_codes(get_image('small_rotated_qr_code'), try_harder=True), [
'217EXP0112'
])
self.assertEqual(
read_codes(get_image('small_rotated_qr_code'), try_harder=True), ['217EXP0112'],
)

def test_small_rotated_qr_code_single(self):
self.assertEqual(
read_codes(get_image('small_rotated_qr_code'), try_harder=True, multi=False),
['217EXP0112'],
)
5 changes: 3 additions & 2 deletions zxinglight/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class BarcodeType(IntEnum):
UPC_EAN_EXTENSION = 17


def read_codes(image, barcode_type=BarcodeType.NONE, try_harder=False, hybrid=False):
def read_codes(image, barcode_type=BarcodeType.NONE, try_harder=False, hybrid=False, multi=True):
"""
Reads codes from a PIL Image.
Expand All @@ -77,6 +77,7 @@ def read_codes(image, barcode_type=BarcodeType.NONE, try_harder=False, hybrid=Fa
try_harder (bool): Spend more time trying to find a barcode.
hybrid (bool): Use Hybrid Binarizer instead of Global Binarizer. For more information,
see `ZXing's documentation`_.
multi (bool): Search for multiple barcodes in a single image.
Returns:
A list of barcode values.
Expand All @@ -96,4 +97,4 @@ def read_codes(image, barcode_type=BarcodeType.NONE, try_harder=False, hybrid=Fa
raw_image = grayscale_image.tobytes()
width, height = grayscale_image.size

return zxing_read_codes(raw_image, width, height, barcode_type, try_harder, hybrid)
return zxing_read_codes(raw_image, width, height, barcode_type, try_harder, hybrid, multi)
27 changes: 18 additions & 9 deletions zxinglight/_zxinglight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ static void log_error(const string &msg) {
PyObject_CallMethod(logger, "error", "O", PyUnicode_FromString(msg.c_str()));
}

static vector<string> *_zxing_read_codes(char *image, int image_size, int width, int height,
int barcode_type, bool try_harder, bool hybrid) {
static vector<string> *_zxing_read_codes(
char *image, int image_size, int width, int height,int barcode_type, bool try_harder,
bool hybrid, bool multi
) {
try {
ArrayRef<char> data = ArrayRef<char>(image, image_size);

Expand Down Expand Up @@ -65,9 +67,16 @@ static vector<string> *_zxing_read_codes(char *image, int image_size, int width,

Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));

MultiFormatReader delegate;
GenericMultipleBarcodeReader reader(delegate);
vector<Ref<Result> > results = reader.decodeMultiple(bitmap, hints);
vector<Ref<Result> > results;
if (multi) {
MultiFormatReader delegate;
GenericMultipleBarcodeReader reader(delegate);
results = reader.decodeMultiple(bitmap, hints);
} else {
// Ref<T> is an autodestructor; the `new` *does not leak*.
Ref<Reader> reader(new MultiFormatReader);
results = vector<Ref<Result> >(1, reader->decode(bitmap, hints));
}

vector<string> *codes = new vector<string>();

Expand All @@ -92,10 +101,10 @@ static vector<string> *_zxing_read_codes(char *image, int image_size, int width,
static PyObject* zxing_read_codes(PyObject *self, PyObject *args) {
PyObject *python_image;
int width, height, barcode_type;
int try_harder, hybrid;
int try_harder, hybrid, multi;

if (!PyArg_ParseTuple(args, "Siiipp", &python_image, &width, &height, &barcode_type,
&try_harder, &hybrid)) {
if (!PyArg_ParseTuple(args, "Siiippp", &python_image, &width, &height, &barcode_type,
&try_harder, &hybrid, &multi)) {
return NULL;
}

Expand All @@ -105,7 +114,7 @@ static PyObject* zxing_read_codes(PyObject *self, PyObject *args) {
PyBytes_AsStringAndSize(python_image, &image, &image_size);

vector<string> *results = _zxing_read_codes(
image, image_size, width, height, barcode_type, try_harder, hybrid
image, image_size, width, height, barcode_type, try_harder, hybrid, multi
);

PyObject *codes = PyList_New(0);
Expand Down

0 comments on commit 780c654

Please sign in to comment.