fluttercandies / extended_image

A powerful official extension library of image, which support placeholder(loading)/ failed state, cache network, zoom pan image, photo view, slide out page, editor(crop,rotate,flip), paint custom etc.
https://fluttercandies.github.io/extended_image/
MIT License
1.94k stars 505 forks source link

How to crop image as a circle? #653

Closed ember11498 closed 1 month ago

ember11498 commented 10 months ago

I have asked this before but I got a vague response. After reading the example I still could not crop the image correctly as a circle. Can anyone point what how to have a circle editor crop layer that actually crops a circle?

class CircleEditorCropLayerPainter extends EditorCropLayerPainter {
const CircleEditorCropLayerPainter();

@override
void paintCorners(
    Canvas canvas, Size size, ExtendedImageCropLayerPainter painter) {
  final Paint paint = Paint()
    ..color = painter.cornerColor
    ..style = PaintingStyle.fill;
  final Rect cropRect = painter.cropRect;
  const double radius = 6;
  canvas.drawCircle(Offset(cropRect.left, cropRect.top), radius, paint);
  canvas.drawCircle(Offset(cropRect.right, cropRect.top), radius, paint);
  canvas.drawCircle(Offset(cropRect.left, cropRect.bottom), radius, paint);
  canvas.drawCircle(Offset(cropRect.right, cropRect.bottom), radius, paint);
}

@override
void paintMask(
    Canvas canvas, Size size, ExtendedImageCropLayerPainter painter) {
  final Rect rect = Offset.zero & size;
  final Rect cropRect = painter.cropRect;
  final Color maskColor = painter.maskColor;
  canvas.saveLayer(rect, Paint());
  canvas.drawRect(
      rect,
      Paint()
        ..style = PaintingStyle.fill
        ..color = maskColor);
  canvas.drawCircle(cropRect.center, cropRect.width / 2.0,
      Paint()..blendMode = BlendMode.clear);
  canvas.restore();
}

@override
void paintLines(
    Canvas canvas, Size size, ExtendedImageCropLayerPainter painter) {
  final Rect cropRect = painter.cropRect;
  if (painter.pointerDown) {
    canvas.save();
    canvas.clipPath(Path()..addOval(cropRect));
    super.paintLines(canvas, size, painter);
    canvas.restore();
  }
}
}
rambozzang commented 9 months ago

same problem here. plz~~

Darkildo commented 6 months ago

maybe you can use ClipRRect?

zmtzawqlp commented 1 month ago

you should handle the image data base on the crop rect, and setPixel to transparent out of the circular

    final imageBytes = await _image!.readAsBytes();
    img.Image originalImage = img.decodeImage(imageBytes)!;

    int size = originalImage.width > originalImage.height ? originalImage.height : originalImage.width;
    img.Image circularImage = img.Image(size, size);

    for (int y = 0; y < size; y++) {
      for (int x = 0; x < size; x++) {
        int centerX = size ~/ 2;
        int centerY = size ~/ 2;
        int radius = size ~/ 2;
        if (((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY)) <= radius * radius) {
          int srcX = (x * originalImage.width / size).toInt();
          int srcY = (y * originalImage.height / size).toInt();
          circularImage.setPixel(x, y, originalImage.getPixel(srcX, srcY));
        } else {
          circularImage.setPixel(x, y, img.getColor(0, 0, 0, 0));  
        }
      }
    }