getCroppedBitmap static method

Future<Image> getCroppedBitmap({
  1. double? maxSize,
  2. FilterQuality quality = FilterQuality.high,
  3. required Rect crop,
  4. required CropRotation rotation,
  5. required Image image,
  6. CustomPainter? overlayPainter,
})

Returns the bitmap cropped with parameters.

maxSize is the maximum width or height you want. overlayPainter is an optional painter on top of the cropped image; could be used for special effects on the cropped area. The crop Rect is normalized to (0, 0) x (1, 1). You can provide the quality used in the resizing operation.

Implementation

static Future<ui.Image> getCroppedBitmap({
  final double? maxSize,
  final ui.FilterQuality quality = FilterQuality.high,
  required final Rect crop,
  required final CropRotation rotation,
  required final ui.Image image,
  final CustomPainter? overlayPainter,
}) async {
  final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
  final Canvas canvas = Canvas(pictureRecorder);

  final bool tilted = rotation.isSideways;
  final double cropWidth;
  final double cropHeight;
  if (tilted) {
    cropWidth = crop.width * image.height;
    cropHeight = crop.height * image.width;
  } else {
    cropWidth = crop.width * image.width;
    cropHeight = crop.height * image.height;
  }
  // factor between the full size and the maxSize constraint.
  double factor = 1;
  if (maxSize != null) {
    if (cropWidth > maxSize || cropHeight > maxSize) {
      if (cropWidth >= cropHeight) {
        factor = maxSize / cropWidth;
      } else {
        factor = maxSize / cropHeight;
      }
    }
  }

  final Offset cropCenter = rotation.getRotatedOffset(
    crop.center,
    image.width.toDouble(),
    image.height.toDouble(),
  );

  final double alternateWidth = tilted ? cropHeight : cropWidth;
  final double alternateHeight = tilted ? cropWidth : cropHeight;
  if (rotation != CropRotation.up) {
    canvas.save();
    final double x = alternateWidth / 2 * factor;
    final double y = alternateHeight / 2 * factor;
    canvas.translate(x, y);
    canvas.rotate(rotation.radians);
    if (rotation == CropRotation.right) {
      canvas.translate(
        -y,
        -cropWidth * factor + x,
      );
    } else if (rotation == CropRotation.left) {
      canvas.translate(
        y - cropHeight * factor,
        -x,
      );
    } else if (rotation == CropRotation.down) {
      canvas.translate(-x, -y);
    }
  }

  canvas.drawImageRect(
    image,
    Rect.fromCenter(
      center: cropCenter,
      width: alternateWidth,
      height: alternateHeight,
    ),
    Rect.fromLTWH(
      0,
      0,
      alternateWidth * factor,
      alternateHeight * factor,
    ),
    Paint()..filterQuality = quality,
  );

  if (rotation != CropRotation.up) {
    canvas.restore();
  }

  final double outputWidth = cropWidth * factor;
  final double outputHeight = cropHeight * factor;
  overlayPainter?.paint(canvas, ui.Size(outputWidth, outputHeight));

  //FIXME Picture.toImage() crashes on Flutter Web with the HTML renderer. Use CanvasKit or avoid this operation for now. https://github.com/flutter/engine/pull/20750
  return await pictureRecorder.endRecording().toImage(
        outputWidth.round(),
        outputHeight.round(),
      );
}