Commit graph

11 commits

Author SHA1 Message Date
4f8661f648 Revert orientation tracking on the camera image
Roll back the rendering-pipeline changes from v1.1.6 (and the
subsequent attempts in 1.1.7/1.1.8/1.1.9): no more
SurfaceTexture transform-matrix-driven re-orientation, no more
rebinding on rotation, no more inverse-rotation correction. The
camera passthrough goes back to fixed portrait-oriented texcoords
and the crop-to-fill math treats the camera buffer as portrait
unconditionally.

The activity stays `fullSensor`, so the Compose UI and the GL
blur passes continue to follow the device orientation — only the
camera image itself is left untouched, which matches the
"normal camera doesn't flip the picture when rotating the phone"
behaviour requested.

Bump to 1.1.10.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:59:18 +02:00
6d7be66341 Fix one landscape orientation rendering image upside down
`SurfaceTexture.getTransformMatrix()` for a custom SurfaceProvider does
not vary with `Preview.targetRotation` — it only encodes the static
sensor-to-buffer transform. The v1.1.8 rebind-on-rotation fix did
update Preview's target rotation, but the matrix returned to the GL
renderer was identical across all four device orientations. Combined
with the activity rotating under fullSensor (so the GL clip-space "up"
direction tracks the device, not the world), one of the two landscape
orientations rendered the image upside down on a real device. The
emulator masked this because its virtual scene is roughly symmetric.

Compose the missing piece on the GL thread: rotate the texcoord
sampling pattern around its centre by the inverse of the activity
rotation before sampling the camera texture. The four orientations
now produce four distinct matrices, keeping world-up at screen-up in
all of them while leaving portrait unchanged.

Bump to 1.1.9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:46:28 +02:00
f0d81db068 Fix landscape preview by rebinding on rotation change
`Preview.targetRotation = …` on an already-bound use case does not
refresh the live SurfaceTexture's transform matrix or trigger a new
SurfaceRequest with a rotation-appropriate buffer size — the new
rotation only applies to subsequently bound streams. With our custom
SurfaceProvider, the result was that rotating to landscape left the
camera still writing portrait-oriented frames into the now-landscape
GL surface, so the preview appeared to rotate with the device instead
of switching to landscape.

Rebind the camera use cases when the target rotation changes so
CameraX fires a fresh SurfaceRequest with the correct resolution
and matrix. Also revert the OrientationDetector mapping back to its
original (matches Display.rotation for a fullSensor activity, which
is what setTargetRotation expects); the previous "fix" went the wrong
direction and was not the root cause.

Bump to 1.1.8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:05:45 +02:00
5eb476a059 Fix landscape image rotating opposite to device
OrientationDetector mapped the OrientationEventListener angle to
Surface.ROTATION_* with 90 and 270 swapped relative to the CameraX
docs example. The angle reports the device's physical clockwise
rotation, whereas Surface.ROTATION_* describes the screen's logical
rotation (opposite direction), so the values must be inverted.

Symptom: rotating the phone clockwise rotated the live preview counter-
clockwise (and vice versa), instead of keeping world-up at screen-up.
The bug was previously masked because the only consumer of the value
(deviceRotation in capturePhoto) is unused — the live preview commit
(d321f07) wired this same value into CameraX's setTargetRotation, which
exposed the inverted mapping.

Bump to 1.1.7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:51:17 +02:00
d321f07973 Support landscape orientation
Replace hardcoded portrait-only texture coordinate rotation with
SurfaceTexture.getTransformMatrix(), so the camera preview and capture
re-orient correctly when the device rotates. Also drive
Preview/ImageCapture targetRotation from the live display rotation, fix
the crop-to-fill aspect math to swap effective camera dimensions
between portrait and landscape, and make the slider control panel
scroll if it doesn't fit the shorter landscape height.

Bump to 1.1.6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:31:43 +02:00
2633f261ef Bump version to 1.1.5
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:52:33 +01:00
5b9aedd109 Update all dependencies to March 2026 versions
Major version bumps:
- AGP 8.7.3 → 9.1.0 (remove kotlin-android plugin, now built-in)
- Kotlin 2.0.21 → 2.3.20
- Gradle 8.9 → 9.4.0
- Compose BOM 2024.12.01 → 2026.03.00
- compileSdk/targetSdk 35 → 36

Library updates:
- core-ktx 1.15.0 → 1.18.0
- lifecycle 2.8.7 → 2.10.0
- activity-compose 1.9.3 → 1.13.0
- CameraX 1.4.1 → 1.5.1
- exifinterface 1.3.7 → 1.4.2

AGP 9 migration: removed org.jetbrains.kotlin.android plugin (Kotlin
support is now built into AGP), removed kotlinOptions block (JVM
target handled by compileOptions).

Bump version to 1.1.4.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:46:37 +01:00
f3baa723be Implement two-pass separable Gaussian blur for camera preview
Replace the single-pass 9-tap directional blur with a three-pass
pipeline: passthrough (camera→FBO), horizontal blur (FBO-A→FBO-B),
vertical blur (FBO-B→screen). This produces a true 2D Gaussian with
a 13-tap kernel per pass, eliminating the visible banding/streaking
of the old approach.

Key changes:
- TiltShiftRenderer: FBO ping-pong with two color textures, separate
  fullscreen quad for blur passes (no crop-to-fill), drawQuad helper
- TiltShiftShader: manages two programs (passthrough + blur), blur
  program uses raw screen-space angle (no camera rotation adjustment)
- tiltshift_fragment.glsl: rewritten for sampler2D in screen space,
  aspect correction on X axis (height-normalized), uBlurDirection
  uniform for H/V selection, wider falloff (3x multiplier)
- New tiltshift_passthrough_fragment.glsl for camera→FBO copy
- TiltShiftOverlay: shrink PINCH_SIZE zone (1.3x, was 2.0x) so
  pinch-to-zoom is reachable over more of the screen
- CameraManager: optimistic zoom update fixes pinch-to-zoom stalling
  (stale zoomRatio base prevented delta accumulation)

Bump version to 1.1.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:38:50 +01:00
878c23bf89 Replace Accompanist Permissions with first-party activity-compose API
Accompanist Permissions (0.36.0) is deprecated and experimental. Migrate
to the stable ActivityResultContracts.RequestPermission /
RequestMultiplePermissions APIs already available via activity-compose.

Adds explicit state tracking with a cameraResultReceived flag to
correctly distinguish "never asked" from "permanently denied" — an
improvement over the previous Accompanist-based detection.

Bump version to 1.1.2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 16:43:56 +01:00
1212604cf7 Bump version to 1.1.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:58:40 +01:00
52af9f6047 Add version management with auto-bump script
Version is tracked in version.properties and read by build.gradle.kts.
Run ./bump-version.sh [major|minor|patch] before release builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:58:22 +01:00