Skip to content

Commit

Permalink
Migrating to pyzbar, refs #32
Browse files Browse the repository at this point in the history
Also requests permissions earlier before importing kv code.
  • Loading branch information
AndreMiras committed Mar 2, 2019
1 parent d6f5ab2 commit 0e4c93b
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions zbarcam/zbarcam.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
from collections import namedtuple

import PIL
import zbarlight
from pyzbar import pyzbar
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
Expand Down Expand Up @@ -30,12 +31,13 @@ class ZBarCam(AnchorLayout):
"""
resolution = ListProperty([640, 480])

codes = ListProperty([])
symbols = ListProperty([])
Symbol = namedtuple('Symbol', ['type', 'data'])
# checking all possible types by default
code_types = ListProperty(zbarlight.Symbologies.keys())
code_types = ListProperty(set(pyzbar.ZBarSymbol))

# TODO: handle code types
def __init__(self, **kwargs):
self._request_android_permissions()
# lazy loading the kv file rather than loading at module level,
# that way the `XCamera` import doesn't happen too early
Builder.load_file(os.path.join(MODULE_DIRECTORY, "zbarcam.kv"))
Expand All @@ -46,9 +48,6 @@ def _setup(self):
"""
Postpones some setup tasks that require self.ids dictionary.
"""
if platform == 'android':
from android.permissions import request_permission, Permission
request_permission(Permission.CAMERA)
self._remove_shoot_button()
self._enable_android_autofocus()
self.xcamera._camera.bind(on_texture=self._on_texture)
Expand All @@ -74,8 +73,18 @@ def _enable_android_autofocus(self):
params.setFocusMode('continuous-video')
camera.setParameters(params)

def _request_android_permissions(self):
"""
Requests CAMERA permission on Android.
"""
print('_request_android_permissions()')
if not self.is_android():
return
from android.permissions import request_permission, Permission
request_permission(Permission.CAMERA)

def _on_texture(self, instance):
self.codes = self._detect_qrcode_frame(
self.symbols = self._detect_qrcode_frame(
texture=instance.texture, code_types=self.code_types)

@staticmethod
Expand All @@ -89,7 +98,12 @@ def _detect_qrcode_frame(texture, code_types):
if platform == 'ios' and fmt == 'BGRA':
fmt = 'RGBA'
pil_image = PIL.Image.frombytes(mode=fmt, size=size, data=image_data)
return zbarlight.scan_codes(code_types, pil_image) or []
symbols = []
codes = pyzbar.decode(pil_image, symbols=code_types)
for code in codes:
symbol = ZBarCam.Symbol(type=code.type, data=code.data)
symbols.append(symbol)
return symbols

@property
def xcamera(self):
Expand All @@ -106,15 +120,16 @@ def is_android(self):


DEMO_APP_KV_LANG = """
#:import ZBarSymbol pyzbar.pyzbar.ZBarSymbol
BoxLayout:
orientation: 'vertical'
ZBarCam:
id: zbarcam
code_types: 'qrcode', 'ean13'
code_types: ZBarSymbol.QRCODE, ZBarSymbol.EAN13
Label:
size_hint: None, None
size: self.texture_size[0], 50
text: ', '.join([str(code) for code in zbarcam.codes])
text: ', '.join([str(symbol.data) for symbol in zbarcam.symbols])
"""


Expand Down

1 comment on commit 0e4c93b

@Cheaterman
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pyzbar cannot work on iOS - it relies on zbar being available as a dynamic library.

Please sign in to comment.