Grayscale monochrome AVIF BLE photo pipeline with text-region crop#3413
Draft
nic-olo wants to merge 5 commits into
Draft
Grayscale monochrome AVIF BLE photo pipeline with text-region crop#3413nic-olo wants to merge 5 commits into
nic-olo wants to merge 5 commits into
Conversation
BLE photos exist for on-phone text recognition, not viewing. Replace the full-res ARGB decode + createScaledBitmap + RGB sharpen chain with a 1-byte/pixel luma pipeline (subsampled RGB_565 decode, row-wise luma extraction, contrast stretch, luma unsharp, bilinear resize), cutting peak transient memory per BLE photo from ~36MB to ~9MB. Legacy color path kept behind ENABLE_GRAYSCALE_BLE_PHOTOS. Adds bytes/KB size and dimension logging around the AVIF encode. Co-authored-by: Nicolo Micheletti <michelettinik@gmail.com>
Forks awxkee/avif-coder 1.7.3 (additive only): new encodeAvifMono() taking a raw 8-bit luma plane and emitting a true monochrome (YUV400) AVIF via libheif heif_colorspace_monochrome, plus the AOM speed (cpu-used) parameter upstream never exposes. Same package/classes as upstream so existing encodeAvif/decode call sites are untouched. ABIs trimmed to armeabi-v7a/arm64-v8a. Patch + rebuild instructions in third_party/avif-coder-mono/; prebuilt AAR in app/libs/. Validated against the exact bundled libs (libheif 1.17.6, AOM 3.8.1): monochrome encode round-trips, and speed=8 cut encode time ~2.6x in a 1920x1440 synthetic document benchmark. Co-authored-by: Nicolo Micheletti <michelettinik@gmail.com>
Route the grayscale BLE path through the forked encoder's encodeAvifMono(): GrayscaleBleProcessor now hands its 1-byte/pixel luma buffer directly to the encoder (LumaImage), eliminating the final RGBA bitmap rehydration (~5-6MB at 1920x1440) so no color buffer exists anywhere in the pipeline. New encodeAvifForBleMono() in PhotoExifMetadataWriter reuses the BMFF EXIF injector for IMU metadata. BLE_AVIF_ENCODE_SPEED=8 sets AOM cpu-used, ~2.6x faster than the plugin default on the software AV1 encoder that dominates BLE photo latency. Legacy full-color path unchanged behind ENABLE_GRAYSCALE_BLE_PHOTOS. Adds Robolectric coverage for the luma pipeline (aspect fit, contrast, ROI crop, gray bitmap rehydration). Co-authored-by: Nicolo Micheletti <michelettinik@gmail.com>
Edge-density ROI detection (Sobel magnitude on a ~320px grayscale decode, 8x6 grid, bounding box of cells >=1.5x frame mean, 10% pad) per docs/agents/BLE_PHOTO_QUALITY_PLAN.md. Cropping keeps native resolution on the region OCR actually reads instead of downscaling the whole frame. Detection is conservative: weak signal, edges spread across the frame, or a crop covering >80% of the frame all fall back to full frame, and any detection failure degrades to the previous behavior. ENABLE_BLE_TEXT_ROI_CROP kill switch for on-device tuning.
Fixture generated with the exact glasses encoder stack (libheif 1.17.6 + AOM, monochrome colorspace, EXIF item): AvifExifStripper strips the Exif tail and BlePhotoUploadService converts to JPEG for the webhook, proving the phone-side BLE photo path handles YUV400 input unchanged.
Contributor
📋 PR Review Helper📱 Mobile App Build✅ Ready to test! (commit 🕶️ ASG Client Build✅ Ready to test! (commit 🔀 Test Locallygh pr checkout 3413 |
Contributor
PR Agent Orchestrator State{
"cycle": 3,
"fixRound": 0,
"totalReviewerRuns": 3,
"consecutiveNoNewReviews": 0,
"openFindings": [],
"resolvedFindings": [],
"nitFindings": [
{
"id": "bb5f98",
"fingerprint": "asg_client/app/libs/avif-coder-mono-1.7.3-mono1.aar:bcada628f89e",
"source": "standards",
"severity": "nit",
"file": "asg_client/app/libs/avif-coder-mono-1.7.3-mono1.aar",
"line": 0,
"message": "~8.36MB prebuilt AAR committed directly to git (not Git LFS) permanently bloats repo history. Well-documented in third_party/avif-coder-mono/, but consider Git LFS or a published JitPack fork as the README itself suggests. Non-blocking.",
"status": "open",
"introducedCycle": 2,
"lastSeenCycle": 2
}
],
"phase": "discovery",
"status": "in_progress",
"lastPair": [
"bugbot",
"standards"
],
"stagnationFixRounds": 0,
"lastOpenCount": 0,
"fingerprintReopenCounts": {},
"mutedFingerprints": []
} |
Contributor
🤖 PR Agent Review — cycle 3✅ No blocking findings · 0 blocking · 1 nit Claude — standards — ✅ approveCommander, recon complete. The mission is resolved — I've inspected the governing Review — PR #3413 (BLE monochrome AVIF photo pipeline)Standards & conventions
Testing (per AGENTS.md — BLE features need unit coverage + E2E path)
Commit / PR hygiene
Security
Nit (non-blocking)
Verdict: no blocking issues or regressions — the diff is self-contained, tested, and standards-compliant. Approving. Updated automatically by the PR Agent Orchestrator each review cycle. Nits do not block merge. |
Contributor
|
bugbot run |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
BLE photos exist to be transferred to the phone for text recognition, not viewing. This reworks the glasses-side
compressAndSendViaBle()pipeline around that:GrayscaleBleProcessor) — subsampled RGB_565 JPEG decode, row-wise luma extraction, contrast stretch, single-channel unsharp, bilinear resize. Every intermediate buffer is 1 byte/pixel instead of the old full-res ARGB decode →createScaledBitmap→ RGB sharpen chain. Peak transient memory per BLE photo drops from ~36 MB to ~4 MB.encodeAvifMono()in a Mentra fork ofawxkee/avif-coder1.7.3 (additive-only patch; same package/classes, drop-in AAR inasg_client/app/libs/, patch + rebuild instructions inasg_client/third_party/avif-coder-mono/). No Bitmap/RGBA round-trip anywhere; the bitstream carries no chroma planes. Also exposes AOMspeed(cpu-used):BLE_AVIF_ENCODE_SPEED = 8benchmarked ~2.6x faster than the plugin default on the software AV1 encode that dominates BLE photo latency (4–5.5 s of ~7.4 s end-to-end on MTK8766).TextRegionDetector) — Sobel edge-density grid on a ~320 px decode; crops to the concentrated text region (10% pad) so the byte budget concentrates on what OCR reads. Conservative: weak/spread signal or a >80%-area crop falls back to full frame; any detection failure degrades to previous behavior.Kill switches:
ENABLE_GRAYSCALE_BLE_PHOTOS(falls back to the legacy full-color YUV420 path, kept verbatim) andENABLE_BLE_TEXT_ROI_CROP. Size logging now prints original and AVIF bytes/KB per photo.No SDK API, transfer-protocol, WiFi-path, or gallery changes. Phone-side code is unchanged except a new test fixture.
Test evidence
colorspace=monochrome, no chroma planes); speed=8 encoded 1920x1440 in 75 ms vs 198 ms host-side, with comparable size.avifdec(libavif + dav1d, the same decoder family the phone'sHeifCoderbundles) decodes the mono output asFormat: YUV400into a correct 8-bit grayscale PNG.scripts/check-android-compile.sh asgand full:app:testDebugUnitTestgreen, including new Robolectric suites forGrayscaleBleProcessor(aspect fit, contrast, ROI crop, gray rehydration) andTextRegionDetector(concentrated block detected, flat/noise frames rejected, source-coordinate mapping).scripts/check-android-compile.sh bluetooth-sdkgreen; phone-sideAvifExifStripperTestextended with a monochrome+EXIF fixture generated by the exact glasses encoder stack — strip + JPEG conversion pass.Outstanding hardware verification
Requires physical devices (not possible from this environment):
⏱️ Compression took/✅ Compressed photo for BLElogs), ROI crop behavior on real documents/scenes.UIImage(data:)render of a monochrome AVIF on iOS 16/17/18 devices (Android decode is covered by the dav1d-family check above). If a specific iOS version misbehaves, flipENABLE_GRAYSCALE_BLE_PHOTOSor ship YUV420 gray via the legacy path.