Skip to content

Commit

Permalink
WIP working fillcropspace
Browse files Browse the repository at this point in the history
  • Loading branch information
ikbendewilliam committed Sep 8, 2023
1 parent 0577e61 commit 82eca2c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 39 deletions.
Binary file added example/assets/test2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class _MyHomePageState extends State<MyHomePage> {
Expanded(
child: CustomImageCrop(
cropController: controller,
image: const AssetImage('assets/test.png'), // Any Imageprovider will work, try with a NetworkImage for example...
image: const AssetImage('assets/test2.png'), // Any Imageprovider will work, try with a NetworkImage for example...
// image: const NetworkImage('https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'),
shape: _currentShape,
ratio: _currentShape == CustomCropShape.Ratio ? Ratio(width: _width, height: _height) : null,
Expand Down
34 changes: 25 additions & 9 deletions example/lib/result_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,36 @@ class ResultScreen extends StatelessWidget {
title: const Text('Result'),
systemOverlayStyle: SystemUiOverlayStyle.dark,
),
body: Center(
child: Column(
children: [
const Spacer(),
Image(
body: Stack(
children: [
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.blueGrey.shade400,
Colors.blueGrey.shade600,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
)),
),
Center(
child: Image(
image: image,
),
ElevatedButton(
),
Positioned(
bottom: 16,
left: 16,
right: 16,
child: ElevatedButton(
child: const Text('Back'),
onPressed: () => Navigator.of(context).pop(),
),
const Spacer(),
],
),
),
],
),
);
}
Expand Down
50 changes: 27 additions & 23 deletions lib/src/calculators/calculate_on_crop_params.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ OnCropParams caclulateOnCropParams({
required int imageHeight,
required CustomImageFit imageFit,
}) {
/// the size of the ui screen
final double uiSize;

/// the size of the area to crop (width and/or height depending on the aspect ratio)
final double cropSizeMax;

Expand All @@ -28,35 +25,42 @@ OnCropParams caclulateOnCropParams({

switch (imageFit) {
case CustomImageFit.fillCropSpace:
uiSize = min(screenWidth, screenHeight);
cropSizeMax = max(imageWidth, imageHeight).toDouble();
final double uiSize;
if (screenWidth > screenHeight * aspectRatio) {
uiSize = screenHeight;
cropSizeMax = imageHeight.toDouble();
} else {
uiSize = screenWidth;
cropSizeMax = imageWidth.toDouble();
}
translateScale = cropSizeMax / (uiSize * cropPercentage);
scale = dataScale;
break;

case CustomImageFit.fitCropSpace:
uiSize = min(screenWidth, screenHeight);
cropSizeMax = max(imageWidth, imageHeight).toDouble();
final uiSize = min(screenWidth, screenHeight);
cropSizeMax = max(imageWidth / min(1, aspectRatio), imageHeight * max(1, aspectRatio)).toDouble();
translateScale = cropSizeMax / (uiSize * cropPercentage);
scale = dataScale;
break;

case CustomImageFit.fillCropWidth:
uiSize = screenWidth;
cropSizeMax = imageWidth.toDouble();
final uiSize = screenWidth;
cropSizeMax = imageWidth / min(1, aspectRatio);
translateScale = cropSizeMax / (uiSize * cropPercentage);
scale = dataScale;
break;

case CustomImageFit.fillCropHeight:
uiSize = screenHeight;
cropSizeMax = imageHeight.toDouble();
final uiSize = screenHeight;
cropSizeMax = imageHeight * max(1, aspectRatio);
translateScale = cropSizeMax / (uiSize * cropPercentage);
scale = dataScale;
break;

case CustomImageFit.fitVisibleSpace:
if (screenHeight < screenWidth) {
final double uiSize;
if (screenHeight * aspectRatio < screenWidth) {
uiSize = screenHeight;
cropSizeMax = imageHeight.toDouble();
} else {
Expand All @@ -70,13 +74,13 @@ OnCropParams caclulateOnCropParams({
case CustomImageFit.fillVisibleSpace:
final heightToWidthRatio = (screenHeight / screenWidth);

if (screenHeight > screenWidth) {
uiSize = screenHeight;
if (screenHeight * aspectRatio > screenWidth) {
final uiSize = screenHeight;
cropSizeMax = imageHeight.toDouble();
translateScale = cropSizeMax / uiSize / cropPercentage * heightToWidthRatio;
scale = dataScale / cropPercentage * heightToWidthRatio;
} else {
uiSize = screenWidth;
final uiSize = screenWidth;
cropSizeMax = imageWidth.toDouble();
translateScale = cropSizeMax / uiSize / cropPercentage / heightToWidthRatio;
scale = dataScale / cropPercentage / heightToWidthRatio;
Expand All @@ -85,9 +89,9 @@ OnCropParams caclulateOnCropParams({

case CustomImageFit.fillVisibleHeight:
final heightToWidthRatio = (screenHeight / screenWidth);
uiSize = screenHeight;
final uiSize = screenHeight;
cropSizeMax = imageHeight.toDouble();
if (screenWidth > screenHeight) {
if (screenWidth > screenHeight * aspectRatio) {
translateScale = cropSizeMax / uiSize / cropPercentage;
scale = dataScale / cropPercentage;
} else {
Expand All @@ -98,9 +102,9 @@ OnCropParams caclulateOnCropParams({

case CustomImageFit.fillVisiblelWidth:
final heightToWidthRatio = (screenHeight / screenWidth);
uiSize = screenWidth;
final uiSize = screenWidth;
cropSizeMax = imageWidth.toDouble();
if (screenWidth > screenHeight) {
if (screenWidth > screenHeight * aspectRatio) {
translateScale = cropSizeMax / uiSize / cropPercentage / heightToWidthRatio;
scale = dataScale / cropPercentage / heightToWidthRatio;
} else {
Expand All @@ -113,11 +117,11 @@ OnCropParams caclulateOnCropParams({
final double cropSizeWidth;
final double cropSizeHeight;
if (aspectRatio > 1) {
cropSizeHeight = cropSizeMax;
cropSizeWidth = cropSizeMax * aspectRatio;
} else {
cropSizeWidth = cropSizeMax;
cropSizeHeight = cropSizeMax / aspectRatio;
cropSizeHeight = cropSizeWidth / aspectRatio;
} else {
cropSizeHeight = cropSizeMax;
cropSizeWidth = cropSizeHeight * aspectRatio;
}
return OnCropParams(
cropSizeHeight: cropSizeHeight,
Expand Down
30 changes: 24 additions & 6 deletions lib/src/widgets/custom_image_crop_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,9 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
required double width,
required double height,
required double borderRadius,
bool clipShape = false,
bool clipShape = true,
}) {
if (clipShape) {
if (!clipShape) {
return Path()
..addRect(
Rect.fromCenter(
Expand Down Expand Up @@ -376,17 +376,32 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
clipShape: widget.clipShapeOnCrop,
));
final matrix4Image = Matrix4.diagonal3(vector_math.Vector3.all(1))
..translate(onCropParams.translateScale * data.x + onCropParams.cropSizeWidth / 2, onCropParams.translateScale * data.y + onCropParams.cropSizeHeight / 2)
..translate(
onCropParams.translateScale * data.x + onCropParams.cropSizeWidth / 2,
onCropParams.translateScale * data.y + onCropParams.cropSizeHeight / 2,
)
..scale(onCropParams.scale)
..rotateZ(data.angle);
final bgPaint = Paint()
..color = widget.backgroundColor
..style = PaintingStyle.fill;
canvas.drawRect(Rect.fromLTWH(0, 0, onCropParams.cropSizeWidth, onCropParams.cropSizeHeight), bgPaint);
canvas.drawRect(
Rect.fromLTWH(
0,
0,
onCropParams.cropSizeWidth,
onCropParams.cropSizeHeight,
),
bgPaint,
);
canvas.save();
canvas.clipPath(clipPath);
canvas.transform(matrix4Image.storage);
canvas.drawImage(_imageAsUIImage!, Offset(-imageWidth / 2, -imageHeight / 2), widget.imagePaintDuringCrop);
canvas.drawImage(
_imageAsUIImage!,
Offset(-imageWidth / 2, -imageHeight / 2),
widget.imagePaintDuringCrop,
);
canvas.restore();

// Optionally remove magenta from image by evaluating every pixel
Expand All @@ -395,7 +410,10 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
// final bytes = await compute(computeToByteData, <String, dynamic>{'pictureRecorder': pictureRecorder, 'cropWidth': cropWidth});

ui.Picture picture = pictureRecorder.endRecording();
ui.Image image = await picture.toImage(onCropParams.cropSizeWidth.floor(), onCropParams.cropSizeHeight.floor());
ui.Image image = await picture.toImage(
onCropParams.cropSizeWidth.floor(),
onCropParams.cropSizeHeight.floor(),
);

// Adding compute would be preferrable. Unfortunately we cannot pass an ui image to this.
// A workaround would be to save the image and load it inside of the isolate
Expand Down

0 comments on commit 82eca2c

Please sign in to comment.