How to implement Flutter CustomPainter to render accurately over an Image?

1

I am new to flutter I was Implementing drawing over photo app by using Custom Painter I can successfully paint over the image but unfortunately the point of Canvas don't match with that of What I have drawn in the previous screen.

Here is the Gist for the code the files,
https://gist.github.com/ahsanalidev/5665f47d3393c23193881c7e32b2061f

merge_image.dart is where I am having a problem. paperwidget.dart and papaerpainter.dart is where I add offsets in the list. I have searched the StackOverflow I did found many solutions for drawing in Canvas and showing it with CustomPainter but none for saving those offsets with Picture recorder, any help is greatly appreciated. Thanks in advance.

Code for drawing on image

class MergedImage extends StatefulWidget {
  MergedImage({Key key, this.image, this.points, this.color}) : super(key: key);
  final File image;
  final List<PointsData> points;
  final Color color;

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

class _MergedImageState extends State<MergedImage> {
  //ImageInfo so that I can get the Size of the picture on which i want to render custom painter
  ImageInfo myimageinfo;

  //The variable where i will save my converted image
  ui.Image myuiImage;

  //Saving my size
  Size size;

  //Convert File Image to ui.Image
  Future<ui.Image> converttoImage() {
    Uint8List imageBytes = widget.image.readAsBytesSync();
    final Completer<ui.Image> completer = new Completer();
    ui.decodeImageFromList(imageBytes, (ui.Image img) {
      return completer.complete(img);
    });
    return completer.future;
  }

  //Method for getting the dimensons of the image
  Future<ImageInfo> getImageDimensions() {
    Completer<ImageInfo> completer = Completer();
    FileImage(widget.image)
        .resolve(new ImageConfiguration())
        .addListener(ImageStreamListener((ImageInfo info, bool _) {
      completer.complete(info);
    }));
    return completer.future;
  }



  //Method that will paint the image 
  Future<ByteData> getPaintedImage() async {
    final Completer<ByteData> completer = Completer();
    final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
    final Canvas canvas = Canvas(pictureRecorder);
    await Future.wait([converttoImage(), getImageDimensions()]).then((val) {
      myimageinfo = val[1];
      myuiImage = val[0];
      Paint paint = Paint()
        ..color = widget.color ?? Color(0xFFFFFFFF)
        ..strokeCap = StrokeCap.round
        ..strokeWidth = 5.0;
      Rect rect = Offset(0, 0) &
          Size((myimageinfo.image.width).toDouble(),
              myimageinfo.image.height.toDouble());
      paintImage(
          canvas: canvas, image: myuiImage, rect: rect, fit: BoxFit.cover);

      //  canvas.drawImage(myuiImage, Offset(0, 0), paint);

      for (int i = 0; i < widget.points.length - 1; i++) {
        if (widget.points[i] != null && widget.points[i + 1] != null) {
          paint.color = widget.points[i].pen.color;
          canvas.drawLine(
              Offset(widget.points[i].offset.dx, widget.points[i].offset.dy),
              Offset(widget.points[i + 1].offset.dx,
                  widget.points[i + 1].offset.dy),
              paint);
        }
      }

      size = Size((myimageinfo.image.width).toDouble(),
          myimageinfo.image.height.toDouble());
    });

    final ui.Image image = await pictureRecorder
        .endRecording()
        .toImage(myimageinfo.image.width, myimageinfo.image.height);

    final ByteData byteData =
        await image.toByteData(format: ui.ImageByteFormat.png);
    completer.complete(byteData);
    return completer.future;
  }

  void showDelayedImageDialog() {
    (getPaintedImage()).then((result) {
      myImage = result;

      showPreviewDialog(myImage.buffer.asUint8List());
    });
  }

  ByteData myImage = ByteData(10);

  void showPreviewDialog(Uint8List image) {
    showDialog(
      context: context,
      builder: (ctx) => GestureDetector(
        onTap: () => Navigator.pop(context),
        child: Container(
          color: Colors.grey.withOpacity(0.5),
          child: Center(
            child: Container(
              child: Image.memory(image),
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: RaisedButton(
        onPressed: () async {
          showDelayedImageDialog();
        },
      )),
    );
  }
}

user-interface
flutter
asked on Stack Overflow Mar 29, 2020 by Syed Ahsan Ali • edited Mar 30, 2020 by Syed Ahsan Ali

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0