How to crop circular(or Square or Hexagon ) area from canvas in Flutter

痞子三分冷 提交于 2020-01-06 04:49:08

问题


I want to crop a rectangular image-file and make it circular or square or hexagon shape and save it as image-file locally. I have a bitmap and I want to crop a circular or hexagon region from this bitmap. All pixels outside the circle should be transparent. How can I do this?

I found the similar question in android platform. But unable to find a good resource that really help or direct me to achieve this in flutter. Please share me the idea to achieve this result.


回答1:


Use Clipper to crop your image use ClipRRect, ClipOval and you can also use custom Clipper to give your Custom shape to image check this link https://www.woolha.com/tutorials/flutter-using-clipper-examples

new ClipRRect(
borderRadius: new BorderRadius.circular(8.0),
child: your image child,

)




回答2:


These simple steps get the required result.

  1. Create a PictureRecorder.
  2. Create a Canvas with your PictureRecorder.
  3. Draw circle in canvas using canvas.drawCircle().
  4. Call endRecording() on the PictureRecorder to get a Picture.
  5. Call toImage() on the Picture.
  6. Convert image toByteData() .
  7. Save image locally using getApplicationDocumentsDirectory().

Canvas Screen

Saved Image Canvas as png

Full Source Code:

        import 'dart:io';

        import 'package:flutter/material.dart';
        import 'dart:ui' as ui;
        import 'package:flutter/services.dart' show rootBundle;
        import 'dart:async';
        import 'dart:typed_data';
        import 'dart:math' as math;
        import 'package:path/path.dart';
        import 'package:path_provider/path_provider.dart';

        class CustomImageCanvas extends StatefulWidget {
          CustomImageCanvas({Key key, this.title}) : super(key: key);

          final String title;

          @override
          _CustomImageCanvasState createState() => _CustomImageCanvasState();
        }

        class _CustomImageCanvasState extends State<CustomImageCanvas> {
          ui.Image image;
          bool isImageloaded = false;
          void initState() {
            super.initState();
            init();
          }

          Future<Null> init() async {
            final ByteData data = await rootBundle.load('assets/image.jpeg');
            image = await loadImage(Uint8List.view(data.buffer));
          }

          Future<ui.Image> loadImage(List<int> img) async {
            final Completer<ui.Image> completer = Completer();
            ui.decodeImageFromList(img, (ui.Image img) {
              setState(() {
                isImageloaded = true;
              });
              return completer.complete(img);
            });
            return completer.future;
          }

          Widget _buildImage() {
            if (this.isImageloaded) {
              return CustomPaint(
                painter: PngImagePainter(image: image),
              );
            } else {
              return Center(child: Text('loading'));
            }
          }

          @override
          Widget build(BuildContext context) {
            return Scaffold(
                appBar: AppBar(
                  title: Text(widget.title),
                ),
                body: Container(
                  child: _buildImage(),
                ));
          }
        }

        class PngImagePainter extends CustomPainter {
          PngImagePainter({
            this.image,
          });

          ui.Image image;

          @override
          void paint(Canvas canvas, Size size) {
            _drawCanvas(size, canvas);
            _saveCanvas(size);
          }

          Canvas _drawCanvas(Size size, Canvas canvas) {
            final center = Offset(150, 50);
            final radius = math.min(size.width, size.height) / 8;

            // The circle should be paint before or it will be hidden by the path
            Paint paintCircle = Paint()..color = Colors.black;
            Paint paintBorder = Paint()
              ..color = Colors.white
              ..strokeWidth = size.width / 36
              ..style = PaintingStyle.stroke;
            canvas.drawCircle(center, radius, paintCircle);
            canvas.drawCircle(center, radius, paintBorder);

            double drawImageWidth = 0;
            var drawImageHeight = -size.height * 0.8;

            Path path = Path()
              ..addOval(Rect.fromLTWH(drawImageWidth, drawImageHeight,
                  image.width.toDouble(), image.height.toDouble()));

            canvas.clipPath(path);

            canvas.drawImage(image, Offset(drawImageWidth, drawImageHeight), Paint());
            return canvas;
          }

          _saveCanvas(Size size) async {
            var pictureRecorder = ui.PictureRecorder();
            var canvas = Canvas(pictureRecorder);
            var paint = Paint();
            paint.isAntiAlias = true;

            _drawCanvas(size, canvas);

            var pic = pictureRecorder.endRecording();
            ui.Image img = await pic.toImage(image.width, image.height);
            var byteData = await img.toByteData(format: ui.ImageByteFormat.png);
            var buffer = byteData.buffer.asUint8List();

            // var response = await get(imgUrl);
            var documentDirectory = await getApplicationDocumentsDirectory();
            File file = File(join(documentDirectory.path,
                '${DateTime.now().toUtc().toIso8601String()}.png'));
            file.writeAsBytesSync(buffer);

            print(file.path);
          }

          @override
          bool shouldRepaint(CustomPainter oldDelegate) {
            return false;
          }
        }



回答3:


You can use the simple_image_crop package.

See my answer on a similar question here-



来源:https://stackoverflow.com/questions/59434412/how-to-crop-circularor-square-or-hexagon-area-from-canvas-in-flutter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!