Skip to content

Commit e8665d0

Browse files
Camera app: eliminate tearing by copying buffer
1 parent bfbf52b commit e8665d0

File tree

1 file changed

+17
-11
lines changed
  • internal_filesystem/apps/com.micropythonos.camera/assets

1 file changed

+17
-11
lines changed

internal_filesystem/apps/com.micropythonos.camera/assets/camera_app.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class CameraApp(Activity):
3131

3232
cam = None
3333
current_cam_buffer = None # Holds the current memoryview to prevent garbage collection
34+
current_cam_buffer_copy = None # Holds a copy so that the memoryview can be free'd
3435

3536
image = None
3637
image_dsc = None
@@ -188,7 +189,8 @@ def onPause(self, screen):
188189
def set_image_size(self):
189190
disp = lv.display_get_default()
190191
target_h = disp.get_vertical_resolution()
191-
target_w = disp.get_horizontal_resolution() - self.button_width - 5 # leave 5px for border
192+
#target_w = disp.get_horizontal_resolution() - self.button_width - 5 # leave 5px for border
193+
target_w = target_h # leave 5px for border
192194
if target_w == self.width and target_h == self.height:
193195
print("Target width and height are the same as native image, no scaling required.")
194196
return
@@ -225,7 +227,7 @@ def qrdecode_one(self):
225227
import qrdecode
226228
import utime
227229
before = utime.ticks_ms()
228-
result = qrdecode.qrdecode_rgb565(self.current_cam_buffer, self.width, self.height)
230+
result = qrdecode.qrdecode_rgb565(self.current_cam_buffer_copy, self.width, self.height)
229231
after = utime.ticks_ms()
230232
#result = bytearray("INSERT_QR_HERE", "utf-8")
231233
if not result:
@@ -261,12 +263,12 @@ def snap_button_click(self, e):
261263
os.mkdir("data/images")
262264
except OSError:
263265
pass
264-
if self.current_cam_buffer is not None:
266+
if self.current_cam_buffer_copy is not None:
265267
filename=f"data/images/camera_capture_{mpos.time.epoch_seconds()}_{self.width}x{self.height}_RGB565.raw"
266268
try:
267269
with open(filename, 'wb') as f:
268-
f.write(self.current_cam_buffer)
269-
print(f"Successfully wrote current_cam_buffer to {filename}")
270+
f.write(self.current_cam_buffer_copy)
271+
print(f"Successfully wrote current_cam_buffer_copy to {filename}")
270272
except OSError as e:
271273
print(f"Error writing to file: {e}")
272274

@@ -380,16 +382,19 @@ def try_capture(self, event):
380382
try:
381383
if self.use_webcam:
382384
self.current_cam_buffer = webcam.capture_frame(self.cam, "rgb565")
385+
self.current_cam_buffer_copy = bytes(self.current_cam_buffer)
383386
elif self.cam.frame_available():
384387
self.current_cam_buffer = self.cam.capture()
388+
self.current_cam_buffer_copy = bytes(self.current_cam_buffer)
389+
self.cam.free_buffer()
385390

386-
if self.current_cam_buffer and len(self.current_cam_buffer):
391+
if self.current_cam_buffer_copy and len(self.current_cam_buffer_copy):
387392
# Defensive check: verify buffer size matches expected dimensions
388393
expected_size = self.width * self.height * 2 # RGB565 = 2 bytes per pixel
389-
actual_size = len(self.current_cam_buffer)
394+
actual_size = len(self.current_cam_buffer_copy)
390395

391396
if actual_size == expected_size:
392-
self.image_dsc.data = self.current_cam_buffer
397+
self.image_dsc.data = self.current_cam_buffer_copy
393398
#image.invalidate() # does not work so do this:
394399
self.image.set_src(self.image_dsc)
395400
if not self.use_webcam:
@@ -456,7 +461,8 @@ def init_internal_cam(width, height):
456461
reset_pin=-1,
457462
pixel_format=PixelFormat.RGB565,
458463
frame_size=frame_size,
459-
grab_mode=GrabMode.LATEST
464+
grab_mode=GrabMode.WHEN_EMPTY,
465+
fb_count=1
460466
)
461467
cam.set_vflip(True)
462468
return cam
@@ -899,7 +905,7 @@ def create_basic_tab(self, tab, prefs):
899905

900906
# Special Effect
901907
special_effect_options = [
902-
("None", 0), ("Negative", 1), ("B&W", 2),
908+
("None", 0), ("Negative", 1), ("Grayscale", 2),
903909
("Reddish", 3), ("Greenish", 4), ("Blue", 5), ("Retro", 6)
904910
]
905911
special_effect = prefs.get_int("special_effect", 0)
@@ -1070,7 +1076,7 @@ def create_expert_tab(self, tab, prefs):
10701076

10711077
# DCW Mode
10721078
dcw = prefs.get_bool("dcw", True)
1073-
checkbox, cont = self.create_checkbox(tab, "DCW Mode", dcw, "dcw")
1079+
checkbox, cont = self.create_checkbox(tab, "Downsize Crop Window", dcw, "dcw")
10741080
self.ui_controls["dcw"] = checkbox
10751081

10761082
# Black Point Compensation

0 commit comments

Comments
 (0)