kivy: use camera

This commit is contained in:
ThomasV 2016-03-16 20:39:59 +01:00
parent 3c1d6fab69
commit 644cb871f5
5 changed files with 70 additions and 22 deletions

View File

@ -16,3 +16,6 @@ then you need to rebuild the distribution. To do so:
Note:
python-for-android must be patched with:
git pull git@github.com:denys-duchier/python-for-android.git fix-recursive-delete
export P4A_pyjnius_DIR=local_clone

View File

@ -35,7 +35,7 @@ Factory.register('InstallWizard',
Factory.register('InfoBubble', module='electrum_gui.kivy.uix.dialogs')
Factory.register('OutputList', module='electrum_gui.kivy.uix.dialogs')
Factory.register('OutputItem', module='electrum_gui.kivy.uix.dialogs')
Factory.register('QrScannerDialog', module='electrum_gui.kivy.uix.dialogs.qr_scanner')
#from kivy.core.window import Window
@ -241,12 +241,15 @@ class ElectrumWindow(App):
self.show_error("invoice error:" + pr.error)
self.send_screen.do_clear()
def on_qr(self, data):
def on_qr(self, d, data):
from electrum.bitcoin import base_decode, is_address
if is_address(data):
self.set_URI(data)
return
if data.startswith('bitcoin:'):
self.set_URI(data)
return
# try to decode transaction
from electrum.bitcoin import base_decode
from electrum.transaction import Transaction
try:
text = base_decode(data, None, base=43).encode('hex')
@ -307,6 +310,17 @@ class ElectrumWindow(App):
popup.open()
def scan_qr(self, on_complete):
self.scan_qr_android(on_complete)
def scan_qr_android(self, on_complete):
dlg = Cache.get('electrum_widgets', 'QrScannerDialog')
if not dlg:
dlg = Factory.QrScannerDialog()
Cache.append('electrum_widgets', 'QrScannerDialog', dlg)
dlg.bind(on_complete=on_complete)
dlg.open()
def scan_qr_zxing(self, on_complete):
if platform != 'android':
return
from jnius import autoclass
@ -555,8 +569,8 @@ class ElectrumWindow(App):
@profiler
def update_wallet(self, *dt):
self._trigger_update_status()
#if self.wallet.up_to_date or not self.network or not self.network.is_connected():
self.update_tabs()
if self.wallet.up_to_date or not self.network or not self.network.is_connected():
self.update_tabs()
@profiler
def notify_transactions(self, *dt):

View File

@ -244,6 +244,19 @@ class AndroidCamera(Widget):
self._holder.pos = pos
from electrum.util import profiler
use_camera = True
if use_camera:
from kivy.uix.camera import Camera
from kivy.clock import Clock
from PIL import Image as PILImage
class MyCamera(Camera):
def start(self):
self.play = True
def stop(self):
self.play = False
class ScannerAndroid(ScannerBase):
'''Widget that use the AndroidCamera and zbar to detect qrcode.
When found, the `symbols` will be updated
@ -251,10 +264,15 @@ class ScannerAndroid(ScannerBase):
def __init__(self, **kwargs):
super(ScannerAndroid, self).__init__(**kwargs)
self._camera = AndroidCamera(
if use_camera:
self._camera = MyCamera(resolution=self.camera_size)
Clock.schedule_interval(self._detect_qrcode_frame2, 1)
else:
self._camera = AndroidCamera(
size=self.camera_size,
size_hint=(None, None))
self._camera.bind(on_preview_frame=self._detect_qrcode_frame)
self._camera.bind(on_preview_frame=self._detect_qrcode_frame)
self.add_widget(self._camera)
# create a scanner used for detecting qrcode
@ -264,6 +282,7 @@ class ScannerAndroid(ScannerBase):
self._scanner.setConfig(0, Config.X_DENSITY, 3)
self._scanner.setConfig(0, Config.Y_DENSITY, 3)
def start(self):
self._camera.start()
@ -271,24 +290,36 @@ class ScannerAndroid(ScannerBase):
self._camera.stop()
def _detect_qrcode_frame(self, instance, camera, data):
# the image we got by default from a camera is using the NV21 format
# zbar only allow Y800/GREY image, so we first need to convert,
# then start the detection on the image
if not self.get_root_window():
self.stop()
return
parameters = camera.getParameters()
size = parameters.getPreviewSize()
barcode = Image(size.width, size.height, 'NV21')
self.check_image(size.width, size.height, data)
def _detect_qrcode_frame2(self, *args):
if not self._camera.play:
return
tex = self._camera.texture
if not tex:
return
im = PILImage.fromstring('RGBA', tex.size, tex.pixels)
im = im.convert('L')
self.check_image(tex.size[0], tex.size[1], im.tostring())
@profiler
def check_image(self, width, height, data):
print "zzz", width, height, len(data)
# the image we got by default from a camera is using the rgba format
# zbar only allow Y800/GREY image, so we first need to convert,
# then start the detection on the image
barcode = Image(width, height, 'NV21')
barcode.setData(data)
barcode = barcode.convert('Y800')
result = self._scanner.scanImage(barcode)
if result == 0:
self.symbols = []
return
# we detected qrcode! extract and dispatch them
symbols = []
it = barcode.getSymbols().iterator()
@ -301,9 +332,9 @@ class ScannerAndroid(ScannerBase):
count=symbol.getCount(),
bounds=symbol.getBounds())
symbols.append(qrcode)
self.symbols = symbols
'''
# can't work, due to the overlay.
def on_symbols(self, instance, value):

View File

@ -11,8 +11,8 @@ class QrScannerDialog(Factory.AnimatedPopup):
def on_symbols(self, instance, value):
instance.stop()
self.dismiss()
uri = App.get_running_app().decode_uri(value[0].data)
self.dispatch('on_complete', uri)
data = value[0].data
self.dispatch('on_complete', data)
def on_complete(self, x):
''' Default Handler for on_complete event.
@ -30,10 +30,10 @@ Builder.load_string('''
size_hint: None, None
size: '340dp', '290dp'
pos_hint: {'center_y': .53}
separator_color: .89, .89, .89, 1
separator_height: '1.2dp'
title_color: .437, .437, .437, 1
background: 'atlas://gui/kivy/theming/light/dialog'
#separator_color: .89, .89, .89, 1
#separator_height: '1.2dp'
#title_color: .437, .437, .437, 1
#background: 'atlas://gui/kivy/theming/light/dialog'
on_activate:
qrscr.start()
qrscr.size = self.size

View File

@ -77,7 +77,7 @@ SendScreen:
IconButton:
id: qr
size_hint: 0.6, 1
on_release: app.scan_qr(on_complete=app.on_qr)
on_release: Clock.schedule_once(lambda dt: app.scan_qr(on_complete=app.on_qr))
icon: 'atlas://gui/kivy/theming/light/camera'
Button:
text: _('Paste')