Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 52 - added an optional painter between the image and the crop grid #53

Merged
merged 2 commits into from
Jun 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions lib/src/crop_controller.dart
Original file line number Diff line number Diff line change
@@ -186,23 +186,29 @@ class CropController extends ValueNotifier<CropControllerValue> {
/// Returns the bitmap cropped with the current crop rectangle.
///
/// [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.
/// You can provide the [quality] used in the resizing operation.
/// Returns an [ui.Image] asynchronously.
Future<ui.Image> croppedBitmap({
final double? maxSize,
final ui.FilterQuality quality = FilterQuality.high,
final CustomPainter? overlayPainter,
}) async =>
getCroppedBitmap(
maxSize: maxSize,
quality: quality,
crop: crop,
rotation: value.rotation,
image: _bitmap!,
overlayPainter: 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.
static Future<ui.Image> getCroppedBitmap({
@@ -211,6 +217,7 @@ class CropController extends ValueNotifier<CropControllerValue> {
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);
@@ -286,20 +293,34 @@ class CropController extends ValueNotifier<CropControllerValue> {
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((cropWidth * factor).round(), (cropHeight * factor).round());
return await pictureRecorder.endRecording().toImage(
outputWidth.round(),
outputHeight.round(),
);
}

/// Returns the image cropped with the current crop rectangle.
///
/// You can provide the [quality] used in the resizing operation.
/// [overlayPainter] is an optional painter on top of the cropped image;
/// could be used for special effects on the cropped area.
/// Returns an [Image] asynchronously.
Future<Image> croppedImage(
{ui.FilterQuality quality = FilterQuality.high}) async {
Future<Image> croppedImage({
ui.FilterQuality quality = FilterQuality.high,
final CustomPainter? overlayPainter,
}) async {
return Image(
image: UiImageProvider(await croppedBitmap(quality: quality)),
image: UiImageProvider(
await croppedBitmap(
quality: quality,
overlayPainter: overlayPainter,
),
),
fit: BoxFit.contain,
);
}
12 changes: 12 additions & 0 deletions lib/src/crop_image.dart
Original file line number Diff line number Diff line change
@@ -107,6 +107,11 @@ class CropImage extends StatefulWidget {
/// When `false`, moves when panning beyond corners but inside the crop rect.
final bool alwaysMove;

/// An optional painter between the image and the crop grid.
///
/// Could be used for special effects on the cropped area.
final CustomPainter? overlayPainter;

const CropImage({
Key? key,
this.controller,
@@ -126,6 +131,7 @@ class CropImage extends StatefulWidget {
this.minimumImageSize = 100,
this.maximumImageSize = double.infinity,
this.alwaysMove = false,
this.overlayPainter,
}) : gridInnerColor = gridInnerColor ?? gridColor,
gridCornerColor = gridCornerColor ?? gridColor,
assert(gridCornerSize > 0, 'gridCornerSize cannot be zero'),
@@ -293,6 +299,12 @@ class _CropImageState extends State<CropImage> {
),
),
),
if (widget.overlayPainter != null)
SizedBox(
width: width,
height: height,
child: CustomPaint(painter: widget.overlayPainter),
),
SizedBox(
width: width + 2 * widget.paddingSize,
height: height + 2 * widget.paddingSize,