encodeToSize method

  1. @override
Future<EncodeResult> encodeToSize(
  1. EncodeSizeRequest request
)
override

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);
}