Commit Graph

417 Commits

Author SHA1 Message Date
admin 7c7a244b84 Rail without icons, FX glow chip renamed
The rail chips carried a lucide glyph before the label; drop the icons and
the icon field so the labels stand alone (the row is a plain text rail now,
and each chip is ~50px narrower). Also rename the FX knob from the
lens-vendor term to LIGHT GLOW - same key, same maths, just the label.
2026-09-10 10:44:33 +07:00
admin 6379c025c8 HDF on the live camera preview
Mirror export pass 5b in the onFrame worklet: extract the highlights with
the same 2.5x-1.5 contrast curve, blur that selection, Screen it back at
0.15..0.5 alpha. The selection must be built as an image filter so the
highlight curve runs before the blur (a paint color filter would run after,
smearing the matrix into the selection).

Kept the tone/cinema path intact: the base draw now records the shader it
used and the glow pass reuses it (drawRect) or falls back to the plain
drawImage, so the glow always sits on the same processed pixels.

Measured on the Xiaomi 2203121C: 5 interleaved 0/10 pairs, the HDF=10 mean
luma is +0.70..0.84 above HDF=0 every time (AE metering does not track the
software pass, so the toggle is the only variable), and frame counts are
unchanged (488/489 vs 492/488 frames per 15s; GPU busy rises ~30%, still
inside the 3 ms median GPU frame). No fps loss, so the pass stays.
2026-09-10 10:41:39 +07:00
admin 6c7d5b8f43 Keep the existing COLOR chip label
Reverts the COLOR -> SATURATION rename: the control already existed, so
it stays as it was.
2026-09-10 10:28:38 +07:00
admin 65d0850317 FX vignetting, LIGHT vibrance/saturation, reticle unlock
- FX: new VIGNETTING 0-10 control (chip + slider). Darkens the four
  corners of the photo with a radial gradient whose radius is the photo
  diagonal/2, so the falloff stays circular on any aspect. Applied in
  preview (camera overlay, polaroid/wall window, plain library) and in
  exportEngine pass 6b, always on the picture, never on the mat.
- LIGHT: new VIBRANCE -10..+10 (chroma-masked saturation in the tone
  shader: vivid pixels move least). Renamed the existing saturation
  control chip from COLOR to SATURATION - same param, clearer label.
- Fix: <Shader> takes a RuntimeEffect, not a gradient SkShader; the
  preview vignette threw "Object is not a HostObject" when it got one.
  Use the declarative <RadialGradient> child on the Rect instead.
- Preview: drop the "AE/AF LOCKED - TAP TO UNLOCK" banner; the lock
  reticle is now itself the unlock touch target.
2026-09-10 10:22:55 +07:00
admin d7a8e0681e Add CANCEL to the watermark editor, scope the mark's touch layer to that editor, and stop a library frame following the user onto the camera
The custom watermark captured EVERY image touch whenever the chip was ON
with text, in both modes: after switching from a library photo to the
camera there was no way to give the image back to tap-to-focus, and a
frame picked for the still rode along onto the live preview (and into the
capture).

- AdjustPanel: CANCEL chip next to ACCEPT. It drops the un-accepted draft
  and restores the last ACCEPTED mark (none if nothing was accepted).
- Viewfinder: draws the mark whenever the chip is ON with text, but only
  lets it CAPTURE touches while its editor is open (new wmEditing prop).
  A double-tap ON the mark still re-opens that editor from the library
  viewer.
- App: ACCEPT and CANCEL now close the editor (that closes the placement
  layer with it). Switching mode closes the deck panels, and leaves the
  frame behind: camera mode has no FRAME picker to undo one.

Verified on device (9a6a7277): camera tap locks AE/AF with the watermark
left ON; library polaroid no longer appears on the live preview after the
switch; CANCEL reverts the chip to CUSTOM WATERMARK OFF and closes the
panel; ACCEPT closes it and the next capture embeds the mark (amber text
found at 0.5/0.375 of the 3000x4000 export), while a capture before
ACCEPT carries none.
2026-09-10 09:58:50 +07:00
admin 28e18893cd Add HDF (Highlight Diffusion Filter) to the FX tab
The built-in lens filter, simulated the way it is done in Photoshop: pull the
highlights out with a hard contrast curve (out = 2.5*in - 1.5, black below 0.6),
Gaussian-blur that selection, then Screen it back over the photo at reduced
opacity. Screen against a near-black pixel is a no-op, so areas with no
highlight within the blur radius come back byte-identical while lit areas
spread their light.

One 0..10 knob drives both the radius (4%..1.9% of the width, ~10..50px at
2560 wide) and the opacity (0.15..0.5), matching the recipe's 15-50px radius
range. The extraction composes on top of the recipe colour matrix so a
monochrome look glows white instead of leaking the original colours back.

Runs in the Skia export engine only; the P5 native path is not wired into the
app (dev parity probe only), so it is left alone for now.
2026-09-10 09:45:51 +07:00
admin 3a8b110c1b Edit the watermark in place, rotate the frame photo, place a custom watermark
Watermark editing no longer covers the photo: the preview letterboxes the
image inside its fit rect while the deck is open, and the idle hint is gone.

The FRAME tab can rotate a library photo 90 degrees clockwise. Rotation
swaps the pixel dimensions instead of the frame, so the polaroid/wall window
keeps its aspect and every consumer (cover crop, watermark area, export) picks
up the new orientation from width()/height() with no extra layout branch. The
rotate surface is CPU-backed on purpose - a GPU snapshot loses its pixels
before the next frame and renders the photo black.

Custom watermark text can now be dragged anywhere on the photo, double-tapped
to re-edit, and is only baked into the file once ACCEPT is pressed; the export
engine takes the same position. It also gained COLOR/SIZE/FONT chips, with the
font list read from the OS via Skia's FontMgr so any installed family can be
used.
2026-09-10 09:26:55 +07:00
admin ff06045e02 Pinch/drag library photo inside polaroid & wall frame windows with export parity
The framed windows (polaroid card / wall frame opening) now take the same pinch + double-tap gestures as plain library, clamped so the photo keeps covering the mat opening, and the visible sub-rectangle is handed to the export engine so the file matches the preview.

Wall frame export also stopped crashing: on Android release an image asset resolves to a drawable *name* ('wallframe') and is flagged downloaded, so Asset.downloadAsync short-circuited and readAsStringAsync threw 'Unsupported scheme for location wallframe'. Clearing that state lets the native module copy the drawable into the cache.
2026-09-10 08:02:55 +07:00
admin c0c2f8532f Lift bottom deck above the keyboard so the custom watermark input stays visible
Edge-to-edge (edgeToEdgeEnabled) makes Android ignore the manifest's
adjustResize, so the IME never shrank the window and the text input sat
under the keyboard. Track keyboardDidShow/Hide height and pad the deck.
2026-09-10 07:44:03 +07:00
admin 3eeef6feb9 Persist device/camera settings across restarts independent of startup mode
Restore shutter sound/metering/RAW from a dedicated key under both 'default'
and 'last session' startup (the session file only stores the look and is
written on background events, so it can be stale after a force-kill). Guard
the persist effect until hydration finishes so the mount-time defaults cannot
overwrite the stored values; drop the stale session override of these three.
2026-09-10 07:36:22 +07:00
admin 144b211d35 Add WATERMARK tab with custom draggable text; hide FRAME in camera; fix double-dark after highlight capture 2026-09-10 07:17:14 +07:00
admin 2512e05c92 Rename launcher label to RecipesCam 2026-09-09 21:55:34 +07:00
admin 4261806dc4 Replace app icon with recipes_icon.png for legacy and adaptive layers 2026-09-09 21:53:23 +07:00
admin f2de481708 Keep GPS watermark user-owned across presets; add pinch/double-tap zoom to photo preview; collapse chrome strip on WB selection 2026-09-09 21:40:28 +07:00
admin 5799210949 Add embedded about & open-source credits screen (license audit) 2026-09-09 21:05:59 +07:00
admin 568f06306a Fix preview wedge after flip: remount SkiaCamera on facing change and as watchdog recovery
Flip only reconfigured the CameraSession in place, leaving the Skia
offscreen-surface cache from the old lens wedged on this Xiaomi: after a
flip the preview banded then went black while the frame pipeline kept
delivering (heartbeat kept rising) and only a full app restart revived it.

- key <SkiaCamera> by facing + mount nonce so a flip fully unmounts and
  remounts the camera (lib clears its surface cache on unmount), i.e. a
  clean restart on every lens switch instead of an in-place reconfigure.
- watchdog now recovers by the same full remount instead of an isActive
  toggle (which never revives a wedged preview), budgeted to 3 restarts.
- bump a re-render on every onStarted: after a remount cameraActive never
  drops (no onStopped on unmount) so the reopen did not re-render and the
  new controller was never re-read, leaving the 1x-10x zoom chips hidden
  until the next touch.

Verified on device: 15+ flips with no wedge, chips visible immediately
after each flip, preview stays live (was ~5 min to black before).
2026-09-09 20:49:24 +07:00
admin 999f49b87f Center shutter between balanced side clusters; tighten flip/preview gap; enlarge active tool tab label 2026-09-09 18:48:04 +07:00
admin a0ca68f176 Keep screen awake in camera mode; nudge flip button toward shutter 2026-09-09 18:40:58 +07:00
admin 55f4184e74 Native zoom presets 1x-10x; back/front camera flip 2026-09-09 18:21:08 +07:00
admin ca3532023a Startup mode default/last-session; GPS watermark default OFF; shutter OFF truly silent
- Settings STARTUP MODE chips (AsyncStorage startup_mode): default = clean camera
  + PROVIA neutral 4:3, last = restore full session look.
- initSession: resolve sim-* recipe ids via FILM_SIMS (fix clobber of session
  ratio/adjustments to 4:3 canonical); restore via setSelectedRecipe not
  applyRecipe so user tweaks (frame/geotag/ratio) survive restore.
- applyDefaultStartup turns GPS watermark OFF (user-requested default).
- Shutter: OFF must not play click on must-play-policy devices. VisionCamera
  v5.2.3 HybridPhotoOutput.kt plays MediaActionSound itself gated by
  (enableShutterSound ?: true) || mustPlayShutterSound — on Xiaomi mustPlay=true
  so OFF still clicked. Both capture paths now gate on enableShutterSound != false.
  node_modules patch not trackable -> artifacts/patches/vision-camera-shutter-silent.patch.
  Verified on Xiaomi 12S Ultra: log SND user=false -> play=false; cold-start
  DEFAULT shows GPS WATERMARK OFF.
2026-09-09 17:59:15 +07:00
admin 3dcfd19d35 PLAN: P6 parity probe results — pending user QA before native default 2026-09-09 17:07:04 +07:00
admin 1fdf765d54 P6 parity probe: same photo through legacy Skia + native engines, 3-panel composite+diff on Xiaomi 2026-09-09 17:06:54 +07:00
admin a51b28f32a PLAN: P5 done 2026-09-09 16:45:00 +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 a72804f081 docs(plan): tick P1 matrix done 2026-09-09 15:18:37 +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
3dtours f588849ac5 perf(capture): render exports off the shutter path via FIFO background queue 2026-09-09 12:22:07 +07:00
3dtours bd7efce600 feat(presets): add LEICA simulation chip; collapse recipe strip on sim select 2026-09-09 11:32:30 +07:00
3dtours 09dbc72cce feat: v1.1 — highlight-weighted metering, settings modal, photo viewer, shutter sound control, cleanup 2026-09-09 09:41:55 +07:00
3dtours e9a9005ef2 fix(ev): preview EV via software matrix, flush AE bias only at capture 2026-09-08 21:28:38 +07:00
3dtours dca4ba0b7c fix(4x3): force frame stream to 4:3 sensor aspect via targetResolution 2026-09-08 21:21:05 +07:00
3dtours 5a94978f33 debug(4x3): use console.error for release-build visibility + build marker 2026-09-08 21:15:25 +07:00
3dtours fcad148798 debug(4x3): log actual frame stream geometry at runtime 2026-09-08 21:01:15 +07:00
3dtours 30a2f768da Restore width-fit ratio bands for native FOV plain preview
Plain frame 'none' with ratio 4:3 shows the whole sensor at screen width (85 deg FOV, like the built-in app at 23mm equiv); 3:2 crops the two vertical sides, same height and zoom, matching the export crop. The fullscreen-cover plain preview from 7985f25 was a wrong interpretation of the built-in view and made every ratio look identical fullscreen.
2026-09-08 20:39:24 +07:00
3dtours 7985f25aa8 Match built-in camera 1x FOV for plain ratio preview
Plain frame 'none' with an aspect ratio no longer bands the feed into a letterboxed strip; it keeps the fullscreen cover view like FULL/1x, so 4:3 preview shows the same angle of view as the built-in camera app at 1x (export crop unchanged). Border/bars frames (classic-white, cinematic) keep the banded contain view.
2026-09-08 20:27:24 +07:00
3dtours 125c1280fa Keep ratio bands at native sensor zoom
The band region was the ratio photo re-scaled to the screen width, so 3:2
(0.667) rendered taller than the 4:3 (== native 3:4) band and zoomed the
scene. Anchor the band on the contain-fitted native sensor box instead and
cut the ratio strip out of it at the same scale: 3:2 is now the identical
vertical view with a narrower horizontal crop, never a taller image.
2026-09-08 19:54:45 +07:00
3dtours 56c86df1b5 Show native sensor in viewfinder composition band
SkiaCamera cover-fits the upright frame snapshot onto the fullscreen view,
so a 4:3 ratio band (aspect == native 3:4 sensor) only revealed a center
slice of the sensor instead of the whole frame. Redraw the feed inside the
frame worklet: when a photo-area rect is active (ratio band / polaroid
window / wall window) black the surface, clip to the rect's raw-frame
inverse under the renderToTexture rotation/mirror CTM, and cover-map the
sensor there. Equal-aspect bands now show the full sensor; narrower ratios
(3:2) crop center like the export. Inactive feed keeps the legacy draw.
2026-09-08 19:34:32 +07:00
3dtours d43405a4de Add aspect-ratio composition band and RAW DNG sidecar capture 2026-09-08 18:43:02 +07:00
3dtours a16c8734a8 Rotate wall frame portrait, letterbox feed to frame window 2026-09-08 18:14:25 +07:00
3dtours a1769e8c84 Add wall frame overlay with transparent PNG window 2026-09-08 17:56:50 +07:00
3dtours 669224fa39 Add D.RANGE toggle chip to LIGHT tab; letterbox camera polaroid to 3:4 card 2026-09-08 17:26:39 +07:00
3dtours b5a257e033 Fix camera polaroid overflow and chrome WB chips; move GPS watermark to top 2026-09-08 17:06:22 +07:00
3dtours bfdc964f65 Polaroid print layout in viewfinder and export; split chip rows; drop cinematic; debounce EV bias 2026-09-08 16:30:29 +07:00
3dtours 7f7ceeddc6 Refresh launcher icon and splash logo from 1024px sources 2026-09-08 15:48:23 +07:00
3dtours b581ecea2f Install icon.png launcher icon and app_logo.png Android splash logo 2026-09-08 15:37:38 +07:00