encodeToSize method
Decode request once, then binary-search quality down to minQuality
until the output fits under maxBytes. Returns the best fitting result,
or (if nothing fits) the smallest achievable with reachedTarget false.
Implementation
@override
Future<EncodeResult> encodeToSize(EncodeSizeRequest request) async {
final mime = _mime(request.format);
if (mime == null) throw UnsupportedFormatError(request.format);
final canvas = await _draw(
request.bytes,
request.autoOrient,
request.maxWidth,
request.maxHeight,
);
// PNG is lossless; quality does nothing — encode once.
if (request.format == ImageFormat.png) {
final bytes = await _encode(canvas, request.format, mime, 100);
return _sized(canvas, bytes, 100, bytes.length <= request.maxBytes);
}
var lo = request.minQuality.clamp(0, 100);
var hi = 100;
Uint8List? best;
var bestQuality = 0;
Uint8List? smallest;
var smallestQuality = lo;
while (lo <= hi) {
final mid = (lo + hi) ~/ 2;
final bytes = await _encode(canvas, request.format, mime, mid);
if (smallest == null || bytes.length < smallest.length) {
smallest = bytes;
smallestQuality = mid;
}
if (bytes.length <= request.maxBytes) {
best = bytes;
bestQuality = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return best != null
? _sized(canvas, best, bestQuality, true)
: _sized(canvas, smallest!, smallestQuality, false);
}