Skip to content

Commit 263854e

Browse files
committed
Object with pre-creation of the needed structures and memory allocation.
Useful for streaming recognition, but still in development
1 parent 2a67198 commit 263854e

5 files changed

Lines changed: 95 additions & 25 deletions

File tree

quirc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
__version__ = '0.6.2'
77

88
import api
9-
from base import decode
9+
from base import decode, Decoder

quirc/base.py

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22

33
import ctypes
44

5-
from quirc import api
5+
import api
6+
import compat
7+
import converters
68

7-
USING_PIL = True
8-
try:
9-
from PIL import Image
10-
except ImportError:
9+
if compat.have_pil:
1110
try:
1211
import Image
1312
except ImportError:
14-
USING_PIL = False
13+
from PIL import Image
1514

1615

1716
def decode(image):
@@ -34,24 +33,16 @@ def decode(image):
3433
buffer = api.begin(obj, width, height)
3534

3635
# Fill buffer with a image pixels. One cell, one pixel.
37-
# TODO: looks like a very slow operation
38-
idx = 0
39-
for i in range(width):
40-
for j in range(height):
41-
buffer[idx] = ctypes.c_uint8(pixels[j, i])
42-
idx += 1
43-
44-
del idx
36+
for idx, pixel in enumerate(converters.pil(image)):
37+
buffer[idx] = pixel
4538

4639
# Finish codes identification
4740
api.end(obj)
4841

49-
num_codes = api.count(obj)
50-
5142
code = api.structures.Code()
5243
data = api.structures.Data()
5344

54-
for i in range(num_codes):
45+
for i in range(api.count(obj)):
5546

5647
# Extract first code
5748
api.extract(obj, i, code)
@@ -67,3 +58,37 @@ def decode(image):
6758
}
6859

6960
api.destroy(obj)
61+
62+
63+
class Decoder(object):
64+
65+
def __init__(self, width, height):
66+
self._width = width
67+
self._height = height
68+
69+
self._obj = api.new()
70+
api.resize(self._obj, self._width, self._height)
71+
72+
self._code = api.structures.Code()
73+
self._data = api.structures.Data()
74+
75+
def decode(self, image):
76+
buffer = api.begin(self._obj, self._width, self._height)
77+
78+
if image.mode not in ('1', 'L'):
79+
image = image.convert('L')
80+
pixels = image.load()
81+
82+
idx = 0
83+
for i in range(self._width):
84+
for j in range(self._height):
85+
buffer[idx] = ctypes.c_uint8(pixels[j, i])
86+
idx += 1
87+
88+
del idx
89+
90+
# Finish codes identification
91+
api.end(self._obj)
92+
93+
def __del__(self):
94+
api.destroy(self._obj)

quirc/compat.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""Miscellaneous compatibility checks"""
4+
5+
# Image libraries
6+
have_pil = True
7+
try:
8+
from PIL import Image
9+
except ImportError:
10+
try:
11+
import Image
12+
except ImportError:
13+
have_pil = False

quirc/converters.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""Converters from the external libraries image objects to the internal format
4+
5+
Handles convertion into a grayscale mode internally.
6+
"""
7+
8+
import ctypes
9+
10+
def pil(image):
11+
"""Convert the PIL.Image object to the pixels buffer
12+
13+
Parameters::
14+
image : PIL.Image object
15+
"""
16+
17+
if image.mode not in ('1', 'L'):
18+
image = image.convert('L')
19+
width, height = image.size
20+
21+
pixels = image.load()
22+
23+
for i in range(width):
24+
for j in range(height):
25+
yield ctypes.c_uint8(pixels[j, i])

tests/test_quirc.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,31 @@
77
import unittest
88

99
import quirc
10+
from quirc import compat
1011

11-
USING_PIL = True
12-
try:
13-
import Image
14-
except ImportError:
12+
if compat.have_pil:
1513
try:
16-
from PIL import Image
14+
import Image
1715
except ImportError:
18-
USING_PIL = False
16+
from PIL import Image
1917

2018

2119
class TestQuircCase(unittest.TestCase):
2220

2321
def setUp(self):
2422
self._folder = os.path.abspath(os.path.dirname(__file__))
2523

26-
@unittest.skipIf(not USING_PIL, 'PIL is unaccessible')
24+
def test_decoder(self):
25+
decoder = quirc.Decoder(148, 148)
26+
decoder.decode(Image.open(os.path.join(self._folder, 'images', 'link.gif')))
27+
28+
@unittest.skipIf(not compat.have_pil, 'PIL is unaccessible')
2729
def test_pil(self):
30+
try:
31+
import Image
32+
except ImportError:
33+
from PIL import Image
34+
2835
image = Image.open(os.path.join(self._folder, 'images', 'link.gif'))
2936

3037
result = list(quirc.decode(image))

0 commit comments

Comments
 (0)