2

There are a couple of cropping plugins for flutter, but they crop only as rectangles, square or oval shapes. I need to crop an specific object(Ex: only an animal of a photo without its background). This is very similar to the 'Lasso Selector Tool or Magnetic Lasso Tool of Photoshop. enter image description here

Is there any such plugin in Flutter? I search in pub.dev, but no luck.

Débora
  • 5,816
  • 28
  • 99
  • 171

1 Answers1

3

Flutter has a ClipPath() widget that can clip a child with a structured path (like Photoshop path+layer->create vector mask, or drawing a path with the lasso tool and cutting out the image). You can have a Container() contain a background image, and clip it with ClipPath().

//in your build()
ClipPath(
  clipper: MyClipperPath(), //you can pass in your own args if you want
  child: Container(
    decoration: BoxDecoration(
      image: DecorationImage(
        image: //your image - AssetImage(), NetworkImage() etc.
        fit: BoxFit.fill, //or whatever BoxFit you want
      )
    )
  )
)

Then outside your widget class

class MyClipperPath extends CustomClipper<Path> {
  MyClipperPath();

  @override
  Path getClip(Size size) {
    //size.height and size.width are the width and height of your child: Container() above

    Path path = Path();
    path.moveTo(0,0);
    path.lineTo(size.width,0);
    path.lineTo(size.width/3,size.height/3);
    path.lineTo(0,size.height);
    path.close();
    
    return path;
  }
}

The above path is an L-like shape. Change the lineTo values and you'll see the clipping path update on screen.

The Path class has a bunch of methods to create lines and curves, including multiple methods for bezier segment types which is what you'd use to copy the way paths or the lasso tool in Photoshop define arbitrary shapes.


Here's a CustomClipper object I'm using in my app. It creates an S-shaped edge on a box.

class TabClipper extends CustomClipper<Path> {
  final double radius;
  const TabClipper([this.radius = 0]);
  @override
  Path getClip(Size size) {
    double _radius = radius;
    if(_radius==0) _radius = size.height * 16 / 57;
    final path = Path();
    path.arcToPoint(Offset(_radius,_radius), radius: Radius.circular(_radius*0.95),rotation: 90.0);
    path.lineTo(_radius, size.height - _radius);
    path.arcToPoint(Offset(_radius*2,size.height), radius: Radius.circular(_radius*0.95),rotation: 90.0, clockwise: false);
    path.lineTo(size.width, size.height);
    path.lineTo(size.width, 0.0);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper oldClipper) {return false;}
}
Pat9RB
  • 580
  • 3
  • 7
  • 1
    Thanks so much. Actually, I initially took a look at clipping based on custom paths. However, my issue is, how to get the final cropped image and process it further (Ex: upload the cropped image to a server? ). I am still learning Flutter and feel like, this will only for showing on the screen. Could you please let me know how to get the cropped image? – Débora Sep 20 '21 at 04:49
  • 2
    You could put a RepaintBoundary around the ClipPath and grab a screenshot as described here: https://stackoverflow.com/a/51118092/7365215 I don't know if you'll get transparency in the PNG alpha channel though. You'll probably get your cut out image over black or over whatever you have behind it on the screen. If you need an alpha channel you can do the same thing again except with a solid white Container() - no image - over a black background and copy those pixels into the alpha channel of the RGBA image data before converting to a png. – Pat9RB Sep 20 '21 at 06:00