Files
quik/data
octoshrimpy 2bd62f2f94 perf(mms): decode an image once per attachment instead of per attempt
Addresses the review feedback on #826.

Compression searches for a size that fits under the carrier limit, so it encodes
the same image many times: a binary search over dimensions, then a quality ladder
from 90 down to 40 if nothing fit. Every one of those attempts went through
ImageUtils.getScaledImage, which re-opened the source URI and re-decoded it from
scratch. Decoding is the expensive part and it was the only part being repeated
unnecessarily; a large photo could be decoded a dozen or more times to send once.

ScaledImageEncoder decodes the source a single time, sampled down to no smaller
than the largest width the search will ask for, and re-encodes that bitmap from
memory for each attempt. The search itself is unchanged.

The decode is guarded: with no carrier cap the target size is the original image,
which on a modern camera sensor is large enough to matter, so an OutOfMemoryError
returns null and the caller falls back to Glide, which streams instead of holding
the whole bitmap.

Also fixes three edge cases raised in review:

- A bounds decode that fails leaves outWidth/outHeight at zero, making the aspect
  ratio 0/0 and every derived dimension garbage. Detect it and fall back rather
  than divide by it.

- searchHi was floored at 100, which raised it above the original width, and above
  the carrier maximum when that was under 100. Both upscale the image and inflate
  the payload. The floor is now 1 and the search starts at 1 rather than 100.

- The last-resort fallback hard-coded a width of 100, upscaling anything narrower.
  It is now bounded by searchHi, so it can only shrink.
2026-08-01 17:15:23 -04:00
..
2025-09-04 00:34:50 -04:00