1414
1515class CameraApp (Activity ):
1616
17- DEFAULT_WIDTH = 320 # 240 would be better but webcam doesn't support this (yet)
18- DEFAULT_HEIGHT = 240
1917 PACKAGE = "com.micropythonos.camera"
2018 CONFIGFILE = "config.json"
2119 SCANQR_CONFIG = "config_scanqr_mode.json"
2220
2321 button_width = 60
2422 button_height = 45
25- colormode = False
2623
2724 status_label_text = "No camera found."
2825 status_label_text_searching = "Searching QR codes...\n \n Hold still and try varying scan distance (10-25cm) and make the QR code big (4-12cm). Ensure proper lighting."
@@ -32,28 +29,28 @@ class CameraApp(Activity):
3229 current_cam_buffer = None # Holds the current memoryview to prevent garba
3330 width = None
3431 height = None
32+ colormode = False
3533
36- image = None
3734 image_dsc = None
38- scanqr_mode = None
35+ scanqr_mode = False
36+ scanqr_intent = False
3937 use_webcam = False
40- keepliveqrdecoding = False
41-
4238 capture_timer = None
39+
40+ prefs = None # regular prefs
41+ scanqr_prefs = None # qr code scanning prefs
4342
4443 # Widgets:
4544 main_screen = None
45+ image = None
4646 qr_label = None
4747 qr_button = None
4848 snap_button = None
4949 status_label = None
5050 status_label_cont = None
5151
5252 def onCreate (self ):
53- self .scanqr_mode = self .getIntent ().extras .get ("scanqr_mode" )
54- from mpos .config import SharedPreferences
55- self .prefs = SharedPreferences (self .PACKAGE , filename = self .SCANQR_CONFIG if self .scanqr_mode else self .CONFIGFILE )
56-
53+ self .scanqr_intent = self .getIntent ().extras .get ("scanqr_intent" )
5754 self .main_screen = lv .obj ()
5855 self .main_screen .set_style_pad_all (1 , 0 )
5956 self .main_screen .set_style_border_width (0 , 0 )
@@ -118,13 +115,31 @@ def onCreate(self):
118115 self .setContentView (self .main_screen )
119116
120117 def onResume (self , screen ):
121- self .parse_camera_init_preferences ()
118+ self .load_settings_cached ()
119+ self .start_cam ()
120+ if not self .cam and self .scanqr_mode :
121+ print ("No camera found, stopping camera app" )
122+ self .finish ()
123+ # Camera is running and refreshing
124+ self .status_label_cont .add_flag (lv .obj .FLAG .HIDDEN )
125+ if self .scanqr_mode :
126+ self .start_qr_decoding ()
127+ else :
128+ self .qr_button .remove_flag (lv .obj .FLAG .HIDDEN )
129+ self .snap_button .remove_flag (lv .obj .FLAG .HIDDEN )
130+
131+ def onPause (self , screen ):
132+ print ("camera app backgrounded, cleaning up..." )
133+ self .stop_cam ()
134+ print ("camera app cleanup done." )
135+
136+ def start_cam (self ):
122137 # Init camera:
123138 self .cam = self .init_internal_cam (self .width , self .height )
124139 if self .cam :
125140 self .image .set_rotation (900 ) # internal camera is rotated 90 degrees
126141 # Apply saved camera settings, only for internal camera for now:
127- self .apply_camera_settings (self .cam , self .use_webcam ) # needs to be done AFTER the camera is initialized
142+ self .apply_camera_settings (self .scanqr_prefs if self . scanqr_mode else self . prefs , self . cam , self .use_webcam ) # needs to be done AFTER the camera is initialized
128143 else :
129144 print ("camera app: no internal camera found, trying webcam on /dev/video0" )
130145 try :
@@ -139,19 +154,8 @@ def onResume(self, screen):
139154 print ("Camera app initialized, continuing..." )
140155 self .update_preview_image ()
141156 self .capture_timer = lv .timer_create (self .try_capture , 100 , None )
142- self .status_label_cont .add_flag (lv .obj .FLAG .HIDDEN )
143- if self .scanqr_mode or self .keepliveqrdecoding :
144- self .start_qr_decoding ()
145- else :
146- self .qr_button .remove_flag (lv .obj .FLAG .HIDDEN )
147- self .snap_button .remove_flag (lv .obj .FLAG .HIDDEN )
148- else :
149- print ("No camera found, stopping camera app" )
150- if self .scanqr_mode :
151- self .finish ()
152157
153- def onPause (self , screen ):
154- print ("camera app backgrounded, cleaning up..." )
158+ def stop_cam (self ):
155159 if self .capture_timer :
156160 self .capture_timer .delete ()
157161 if self .use_webcam :
@@ -172,20 +176,24 @@ def onPause(self, screen):
172176 i2c .writeto (camera_addr , bytes ([reg_high , reg_low , power_off_command ]))
173177 except Exception as e :
174178 print (f"Warning: powering off camera got exception: { e } " )
175- print ("camera app cleanup done." )
179+ print ("emptying self.current_cam_buffer..." )
180+ self .image_dsc .data = None # it's important to delete the image when stopping the camera, otherwise LVGL might try to display it and crash
176181
177- def parse_camera_init_preferences (self ):
178- resolution_str = self .prefs .get_string ("resolution" , f"{ self .DEFAULT_WIDTH } x{ self .DEFAULT_HEIGHT } " )
179- self .colormode = self .prefs .get_bool ("colormode" , False )
180- try :
181- width_str , height_str = resolution_str .split ('x' )
182- self .width = int (width_str )
183- self .height = int (height_str )
184- print (f"Camera resolution loaded: { self .width } x{ self .height } " )
185- except Exception as e :
186- print (f"Error parsing resolution '{ resolution_str } ': { e } , using default 320x240" )
187- self .width = self .DEFAULT_WIDTH
188- self .height = self .DEFAULT_HEIGHT
182+ def load_settings_cached (self ):
183+ from mpos .config import SharedPreferences
184+ if self .scanqr_mode :
185+ print ("loading scanqr settings..." )
186+ if not self .scanqr_prefs :
187+ self .scanqr_prefs = SharedPreferences (self .PACKAGE , filename = self .SCANQR_CONFIG )
188+ self .width = self .scanqr_prefs .get_int ("resolution_width" , CameraSettingsActivity .DEFAULT_SCANQR_WIDTH )
189+ self .height = self .scanqr_prefs .get_int ("resolution_height" , CameraSettingsActivity .DEFAULT_SCANQR_HEIGHT )
190+ self .colormode = self .scanqr_prefs .get_bool ("colormode" , CameraSettingsActivity .DEFAULT_SCANQR_COLORMODE )
191+ else :
192+ if not self .prefs :
193+ self .prefs = SharedPreferences (self .PACKAGE )
194+ self .width = self .prefs .get_int ("resolution_width" , CameraSettingsActivity .DEFAULT_WIDTH )
195+ self .height = self .prefs .get_int ("resolution_height" , CameraSettingsActivity .DEFAULT_HEIGHT )
196+ self .colormode = self .prefs .get_bool ("colormode" , CameraSettingsActivity .DEFAULT_COLORMODE )
189197
190198 def update_preview_image (self ):
191199 self .image_dsc = lv .image_dsc_t ({
@@ -238,7 +246,7 @@ def qrdecode_one(self):
238246 result = self .print_qr_buffer (result )
239247 print (f"QR decoding found: { result } " )
240248 self .stop_qr_decoding ()
241- if self .scanqr_mode :
249+ if self .scanqr_intent :
242250 self .setResult (True , result )
243251 self .finish ()
244252 else :
@@ -270,21 +278,40 @@ def snap_button_click(self, e):
270278
271279 def start_qr_decoding (self ):
272280 print ("Activating live QR decoding..." )
273- self .keepliveqrdecoding = True
281+ self .scanqr_mode = True
282+ oldwidth = self .width
283+ oldheight = self .height
284+ oldcolormode = self .colormode
285+ # Activate QR mode settings
286+ self .load_settings_cached ()
287+ # Check if it's necessary to restart the camera:
288+ if self .width != oldwidth or self .height != oldheight or self .colormode != oldcolormode :
289+ self .stop_cam ()
290+ self .start_cam ()
274291 self .qr_label .set_text (lv .SYMBOL .EYE_CLOSE )
275292 self .status_label_cont .remove_flag (lv .obj .FLAG .HIDDEN )
276293 self .status_label .set_text (self .status_label_text_searching )
277294
278295 def stop_qr_decoding (self ):
279296 print ("Deactivating live QR decoding..." )
280- self .keepliveqrdecoding = False
297+ self .scanqr_mode = False
281298 self .qr_label .set_text (lv .SYMBOL .EYE_OPEN )
282299 self .status_label_text = self .status_label .get_text ()
283300 if self .status_label_text not in (self .status_label_text_searching or self .status_label_text_found ): # if it found a QR code, leave it
284301 self .status_label_cont .add_flag (lv .obj .FLAG .HIDDEN )
302+ # Check if it's necessary to restart the camera:
303+ oldwidth = self .width
304+ oldheight = self .height
305+ oldcolormode = self .colormode
306+ # Activate non-QR mode settings
307+ self .load_settings_cached ()
308+ # Check if it's necessary to restart the camera:
309+ if self .width != oldwidth or self .height != oldheight or self .colormode != oldcolormode :
310+ self .stop_cam ()
311+ self .start_cam ()
285312
286313 def qr_button_click (self , e ):
287- if not self .keepliveqrdecoding :
314+ if not self .scanqr_mode :
288315 self .start_qr_decoding ()
289316 else :
290317 self .stop_qr_decoding ()
@@ -311,11 +338,10 @@ def zoom_button_click(self, e):
311338 print (f"self.cam.set_res_raw returned { result } " )
312339
313340 def open_settings (self ):
314- intent = Intent (activity_class = CameraSettingsActivity , extras = {"prefs" : self .prefs , "use_webcam" : self .use_webcam , "scanqr_mode" : self .scanqr_mode })
341+ intent = Intent (activity_class = CameraSettingsActivity , extras = {"prefs" : self .prefs if not self . scanqr_mode else self . scanqr_prefs , "use_webcam" : self .use_webcam , "scanqr_mode" : self .scanqr_mode })
315342 self .startActivity (intent )
316343
317344 def try_capture (self , event ):
318- #print("capturing camera frame")
319345 try :
320346 if self .use_webcam :
321347 self .current_cam_buffer = webcam .capture_frame (self .cam , "rgb565" if self .colormode else "grayscale" )
@@ -328,7 +354,7 @@ def try_capture(self, event):
328354 self .image_dsc .data = self .current_cam_buffer
329355 #self.image.invalidate() # does not work so do this:
330356 self .image .set_src (self .image_dsc )
331- if self .keepliveqrdecoding :
357+ if self .scanqr_mode :
332358 self .qrdecode_one ()
333359 if not self .use_webcam :
334360 self .cam .free_buffer () # After QR decoding, free the old buffer, otherwise the camera doesn't provide a new one
0 commit comments