Commit Graph

11 Commits

Author SHA1 Message Date
admin 588fbf77d9 perf(capture): trade CameraX MFNR for latency, average our own low-light burst off the shutter path
Measured on the 12S Ultra (2203121C), same scene, 1x, EV 0, 3 shots per arm:

- qualityPrioritization 'quality' -> 'balanced': tap->file 1013 ms vs 736 ms
  (-277 ms, -27%), settled 1552 ms vs 1280 ms, in-camera 521 ms vs 286 ms.
  Repeat on a second session: -228 ms. Image quality at ISO ~450 is inside the
  scatter of one arm (flat sigma +2.4%, edge +0.1%, texture -1.1%), so the MFNR
  pass quality would have bought is not measurable here. Also removes the
  EXPO_PUBLIC_CAPTURE_MODE seam: Metro inlines EXPO_PUBLIC_* in dev only, the
  release HBC build does not, so it could never gate shipped behaviour.
- Dark scenes now go through the app's own burst (ISO >= 100 gate for the probe)
  and mergeBurst runs in the export queue instead of on the shutter path, so a
  second shot is accepted while the frames are still being averaged: double-tap
  at 1.2 s used to drop the second photo, now it lands. Output stays the merged
  frame (flat sigma 0.825 vs 0.939 for a single frame).

Burst is skipped when the LED is the light source, when the shot came from the
native 0.5x session, for a held burst, for RAW, and below the devicePerf RAM
floor (deviceFloor.ts) where three raws plus the alignment rasters would be
seconds of shutter lag.

Bundles in the work this sits on: frame averaging (burstAlign/burstMerge),
the per-device floor, and the EXIF/ISO readback the burst gate needs (exifWrite,
photoMeta, exportEngine, RecipescamExportModule).

Self-checks: src/utils/{burstAlign,deviceFloor,exifWrite}.check.ts.
2026-09-26 11:37:48 +07:00
admin a85ebf0a81 Sell PRO as an in-app unlock, take shared photos, and let FX run negative
- One free Play app (com.locphamtran.recipescamera) with an expo-iap PRO
  unlock, replacing the paid apk for the store channel
- Android SEND/SEND_MULTIPLE share target feeds photos into the editor,
  on cold start and on resume
- BACK button in the TopBar and press-and-hold PEEK replace the chip row
- NOISE REDUCTION and SHARPENING accept -10: a negative SHARPENING softens
  the frame before the grain pass, a negative NOISE REDUCTION re-grains it,
  in the Skia engine, the live preview and the Kotlin export path alike
2026-09-16 06:48:22 +07:00
admin 1d84fe8a4a Zoom the FRAME preview instead of the photo, and save to DCIM/Camera
- FRAME tab now pinches the whole view (frame + photo + watermark) in both
  camera and library; one finger pans that view. Preview only: the exported
  file is identical at 1x and while the view is magnified.
- Watermark pinch/drag stay relative and keep priority while the WATERMARK
  row is open, so they still work after returning from the FRAME tab.
- Exports go through a native MediaStore insert into DCIM/Camera, falling
  back to expo-media-library when the native save fails.
2026-09-11 23:09:26 +07:00
admin 17ee01b62a feat(exif): write the Xiaomi watermark blob (0x889e) so HyperOS Gallery can frame our captures
HyperOS Gallery reads EXIF 0x889e (a JSON blob) to build its watermark
frame; without it a photo fails with "cannot recognize the parameters".
CameraX/HAL never supplies that vendor tag, so a capture from this app
lacked it while a stock-camera photo carried it.

Read back the same props the stock camera derives the blob from
(ro.product.device / ro.product.marketname / Build.MANUFACTURER) via the
native module, synthesize the blob in exifWrite, and write it only when
the source has none and the device is Xiaomi/Redmi/POCO - a source blob
is never overwritten.
2026-09-11 18:47:44 +07:00
admin 1cda62e039 P5 native export hooked (camera+library) — real photo to gallery on Xiaomi 2026-09-09 16:44:49 +07:00
admin 25e4f21917 P4 native frames (classic/polaroid/wallframe) + GPS watermark verified on Xiaomi (sample gates pass) 2026-09-09 16:34:24 +07:00
admin 11635a0d33 P3 native cinema/clarity/denoise/grain (exportEngine port) verified on Xiaomi (gates pass) 2026-09-09 15:58:15 +07:00
admin 71b9476901 P2 native tone DR/hl/sh (TONE_SKSL port) parity verified on Xiaomi (gates 140/75/209/104/11 pass) 2026-09-09 15:38:35 +07:00
admin d412f40861 P1 native color matrix + crop (processColorAsync): parity verified on Xiaomi (classic-neg on black -> rgb(13,5,0), translate*255) 2026-09-09 15:18:30 +07:00
admin dfcf0f3a28 P0 native decode/encode benchmark passes on Xiaomi (12MP decode+encode ~210-270ms, off-main-thread) 2026-09-09 15:10:30 +07:00
3dtours a8932f52ed feat(native-export): scaffold local Expo module + native decode/encode bench probe (P0)
Local Kotlin module modules/recipescam-export (autolinked via expo ./modules)
exposes decodeEncodeAsync — BitmapFactory decode -> JPEG q95 encode -> file,
all on Dispatchers.IO off the JS/main threads. EXPO_PUBLIC_BENCH=1 builds run
src/dev/nativeBenchProbe.ts: 3 timed decode+encode passes on the bundled
wallframe artwork plus a JS-timer gap check proving the JS thread never
blocks during native rendering. Legacy Skia engine untouched (reference).
2026-09-09 12:39:35 +07:00