Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flutter canvas 如何获取clip后的图片 #15

Open
jindada opened this issue Apr 13, 2019 · 0 comments
Open

flutter canvas 如何获取clip后的图片 #15

jindada opened this issue Apr 13, 2019 · 0 comments

Comments

@jindada
Copy link
Owner

jindada commented Apr 13, 2019

Step.1 Canvas转换为图片

首先,你要了解flutter如何将canvas转换成图片,这里有一个非常好的例子分享给大家flutter_canvas_to_image,这里简单讲解一下思路:

1.首先创建一个 ui.PictureRecorder(记录仪), 然后作为载体创建一个canvas对象

// 创建一个记录仪
final recorder = new ui.PictureRecorder();
final canvas = new Canvas(
    recorder,
    new Rect.fromPoints(
        new Offset(0.0, 0.0), new Offset(200.0, 200.0)));

2.在canvas上进行绘制

final stroke = new Paint()
  ..color = Colors.grey
  ..style = PaintingStyle.stroke;

canvas.drawRect(
    new Rect.fromLTWH(0.0, 0.0, 200.0, 200.0), stroke);

final paint = new Paint()
  ..color = color
  ..style = PaintingStyle.fill;

canvas.drawCircle(
    new Offset(
      widget.rd.nextDouble() * 200.0,
      widget.rd.nextDouble() * 200.0,
    ),
    20.0,
    paint);
  1. 转换和显示
// 关闭记录仪
final picture = recorder.endRecording();
final img = picture.toImage(200, 200);
final pngBytes = await img.toByteData(format: new ui.EncodingFormat.png());
// 显示图片
new Image.memory(new Uint8List.view(imgBytes.buffer));

Step.2 Canvas截取

当我们懂得如何将canvas转为图片之后,我们简单看下canvas clip的代码(这并不是本文主要讲述的内容,所以不做详细说明),我们以canvas.clipPath截取图片为例

// 绘制一个三角形的path
Path _path = Path()
      ..moveTo(100, 50)
      ..lineTo(50, 150)
      ..lineTo(150, 150)
      ..lineTo(100, 50);

canvas.clipPath(_path);

canvasClip.drawImageRect(
      _image, // ui.Image
      Rect.fromLTWH(0, 0, _image.width.toDouble(), _image.height.toDouble()),, 
      Rect.fromLTWH(0, 0, 200, 200), // 画布Rect
      Paint()
    );

image

Step.3 获取截取之后的图形

我们已经将图片截取了,这个时候获取的图片大小是200*200的,但是我们只想要那个三角形怎么办那?思路如下:

  1. 获取path围成的矩形

  2. 将这个矩形移到画布的左上角

  3. 转成目标大小的图片

思路有了,我们看实际解决办法,首先针对第一点,flutter Path 为我们提供了一个现成的方法 getBounds(), 看下官网的描述

getBounds() → Rect
Computes the bounding rectangle for this path. 

然后看下第二点,我们可以将之前生成的图片通过位移画在一个新的canvas的左上角,第三步在Step.1 已经充分get了,看下代码:

// 获取Path围成的矩形
Rect _bounds = _path.getBounds();
// 上一步生成的图片
ui.Image img = await picture.toImage(200, 200);
// 新建一个新的记录仪和canvas
final recorder2 = ui.PictureRecorder();
final canvasClip = Canvas(recorder2, Rect.fromLTWH(0, 0, size.width, size.height));

canvasClip.drawImageRect(
      img,
      _bound, // _bound 中已经包含左上角的offset,可以直接拿过来用
      Rect.fromLTWH(0, 0, _bound.width, _bound.height),
      Paint()
 );
// 停止录制 生成image
final picture2 = recorder2.endRecording();
ui.Image img2 = await picture2.toImage(size.width.toInt(), size.height.toInt());

final pngBytes = await img2.toByteData(format: ui.ImageByteFormat.png);

image
看起来没什么变化?我们可以打印下输出
image
very nice,大佬们如果有更好的方法麻烦告诉下,非常感谢

Step.4 献上完整代码

import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:myapp/utils/image.dart';
import 'package:flutter/material.dart';

void main() => runApp(App());

const kCanvasSize = 200.0;

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ImageGenerator(),
      ),
      debugShowCheckedModeBanner: false,
    );
  }
}

class ImageGenerator extends StatefulWidget {
  @override
  _ImageGeneratorState createState() => _ImageGeneratorState();
}

class _ImageGeneratorState extends State<ImageGenerator> {
  ByteData imgBytes;
  ui.Image _image;

  @override
  void initState() {
    super.initState();
    loadImage('assets/images/face.jpg').then((image) {
      setState(() {
        _image = image;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(12.0),
            child: RaisedButton(
                child: Text('Generate image'), onPressed: generateImage),
          ),
          imgBytes != null
              ? Container(
                  child: Image.memory(
                  Uint8List.view(imgBytes.buffer),
                  width: kCanvasSize,
                  height: kCanvasSize,
                ))
              : Container()
        ],
      ),
    );
  }

  void generateImage() async {
    final recorder = ui.PictureRecorder();
    final canvas = Canvas(recorder,
        Rect.fromPoints(Offset(0.0, 0.0), Offset(kCanvasSize, kCanvasSize)));

    final stroke = new Paint()
      ..color = Colors.grey
      ..style = PaintingStyle.stroke;

    canvas.drawRect(Rect.fromLTWH(0.0, 0.0, kCanvasSize, kCanvasSize), stroke);

    Path _path = Path()
      ..moveTo(100, 50)
      ..lineTo(50, 150)
      ..lineTo(150, 150)
      ..lineTo(100, 50);

    canvas.clipPath(_path);
    Rect _bound = _path.getBounds();

    canvas.drawImageRect(
        _image,
        Rect.fromLTWH(0, 0, _image.width.toDouble(), _image.height.toDouble()),
        Rect.fromLTWH(0, 0, 200, 200),
        Paint());

    final picture = recorder.endRecording();
    ui.Image img = await picture.toImage(200, 200);

    print('img的尺寸: $img');

    final recorder2 = ui.PictureRecorder();
    final canvasClip =
        Canvas(recorder2, Rect.fromLTWH(0, 0, _bound.width, _bound.height));

    canvasClip.drawImageRect(
        img, _bound, Rect.fromLTWH(0, 0, _bound.width, _bound.height), Paint());

    final picture2 = recorder2.endRecording();
    ui.Image img2 =
        await picture2.toImage(_bound.width.toInt(), _bound.height.toInt());

    print('img2的尺寸: $img2');

    final pngBytes = await img2.toByteData(format: ui.ImageByteFormat.png);

    setState(() {
      imgBytes = pngBytes;
    });
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant