将两个图像的差异绘制到画布

创造者或可能不是

我试图在Flutter中画出Image我必须拥有的2 s之差,Canvas而我真正的意思是我只想画出与众不同的东西(您可以在下面看到我希望看到的东西)。
它需要同步发生,即在paint通话中!

在此答案中,两个图像称为imageAimageB

canvas.drawImage(
  imageA,
  offset,
  Paint(),
);
canvas.drawImage(
  imageB,
  offset,
  Paint()
    ..blendMode = BlendMode.difference,
);

可视化

imageA并分别imageB绘制。

Difference between imageA and imageB. You can see what I expect to see left and what I actually get using the code above right.
The gray/white background color in the left image is supposed to be transparent, i.e. alpha should equal zero where the two images are the same. Additionally, the black shadow around the red square in the expected image is an artifact and not what I want in my app.

Problem

I am not saying that the expected image is what I expect to get from BlendMode.difference, but I want to know how I can get the expected output, i.e. how I achieve only drawing what is different between two images.
This means that I want to only render pixels from imageB that are different from imageA and otherwise nothing, i.e. alpha value 0.

Explanation

I will try to explain it a bit more clearly again:

  • If the color is the same, draw transparent pixel (remove source pixel).

  • If the color is different, draw destination pixel.

Nicolas Caous

Currently flutter does not support what you are trying to do. Based on my research, flutter handles canvas paint on the native level. You can see this in action from this snippet:

  /// Fills the canvas with the given [Paint].
  ///
  /// To fill the canvas with a solid color and blend mode, consider
  /// [drawColor] instead.
  void drawPaint(Paint paint) {
    assert(paint != null);
    _drawPaint(paint._objects, paint._data);
  }
  void _drawPaint(List<dynamic> paintObjects, ByteData paintData) native 'Canvas_drawPaint';

This is from the canvas implementation on the latest version of flutter (1.9.2). Any pixel manipulation that you can do without async code must be done utilizing flutter BlendMode or ImageFilter which lacks personalized masks support.

The only way to do what you intend to do is to actually implement native code, which I don't really think you want to do. I spent the last 6 hours trying to figure out if there wasn't anything out of the official flutter API docs that would do what you want it to do, but the thing is, most of things in flutter are just intended to be async.

If you are going to venture into implementing this natively, why don't you ask to be implemented as a feature in the official flutter github? I mean, so much work, don't let it be wasted.

Just because I didn't wanted to leave empty handed, I have written precisely what you wanted with the image lib but using async:

enter image description here

import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:image/image.dart' as im;

import 'package:flutter/material.dart';

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MyApp();
  }
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ByteBuffer imgBytes;
  double canvasHeight = 500;
  double canvasWidth = 300;

  ui.PictureRecorder recorder1;
  Canvas canvas1;

  ui.PictureRecorder recorder2;
  Canvas canvas2;

  ui.Picture picture1;
  ui.Picture picture2;

  @override
  void initState() {
    // Canvas1
    recorder1 = ui.PictureRecorder();
    canvas1 = Canvas(recorder1,
        Rect.fromPoints(Offset(0.0, 0.0), Offset(canvasWidth, canvasHeight)));

    // Draw red background
    var paint = Paint();
    paint.style = PaintingStyle.fill;
    paint.color = Colors.red;

    canvas1.drawRect(Offset(0, 0) & Size(canvasWidth, canvasHeight), paint);

    // Draw black square
    paint = Paint();
    paint.style = PaintingStyle.fill;
    paint.color = Colors.black;

    canvas1.drawRect(
        Offset(canvasWidth * 0.5 / 4, canvasHeight / 2) &
            Size(canvasHeight / 8, canvasHeight / 8),
        paint);

    picture1 = recorder1.endRecording();

    // Canvas2
    recorder2 = ui.PictureRecorder();
    canvas2 = Canvas(recorder2,
        Rect.fromPoints(Offset(0.0, 0.0), Offset(canvasWidth, canvasHeight)));

    // Draw red background
    paint = Paint();
    paint.style = PaintingStyle.fill;
    paint.color = Colors.red;

    canvas2.drawRect(Offset(0, 0) & Size(canvasWidth, canvasHeight), paint);

    // Draw blue square
    paint = Paint();
    paint.style = PaintingStyle.fill;
    paint.color = Colors.blue;

    canvas2.drawRect(
        Offset(canvasWidth * 2.5 / 4, canvasHeight / 2) &
            Size(canvasHeight / 8, canvasHeight / 8),
        paint);

    picture2 = recorder2.endRecording();

    (() async {
      ui.Image img1 =
          await picture1.toImage(canvasWidth.toInt(), canvasHeight.toInt());
      ByteData byteData1 =
          await img1.toByteData(format: ui.ImageByteFormat.png);
      im.Image decodedPng1 = im.decodePng(byteData1.buffer.asUint8List());

      ui.Image img2 =
          await picture2.toImage(canvasWidth.toInt(), canvasHeight.toInt());
      ByteData byteData2 =
          await img2.toByteData(format: ui.ImageByteFormat.png);
      im.Image decodedPng2 = im.decodePng(byteData2.buffer.asUint8List());

      for (int i = 0; i < canvasHeight; i += 1) {
        for (int j = 0; j < canvasWidth; j += 1) {
          int pixel1 = decodedPng1.getPixel(j, i);
          int r1 = pixel1 & 0xff;
          int g1 = (pixel1 >> 8) & 0xff;
          int b1 = (pixel1 >> 16) & 0xff;
          int a1 = (pixel1 >> 24) & 0xff;

          int pixel2 = decodedPng2.getPixel(j, i);
          int r2 = pixel2 & 0xff;
          int g2 = (pixel2 >> 8) & 0xff;
          int b2 = (pixel2 >> 16) & 0xff;
          int a2 = (pixel2 >> 24) & 0xff;

          if (r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2) {
            // Draw black transparent
            decodedPng2.setPixel(j, i, 0);
          } else {
            // Leave as is
          }
        }
      }

      setState(() {
        imgBytes = Uint8List.fromList(im.encodePng(decodedPng2)).buffer;
      });
    })();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dummy'),
        ),
        body: imgBytes != null
            ? Center(
                child: Image.memory(
                  Uint8List.view(imgBytes),
                  width: canvasWidth,
                  height: canvasHeight,
                ),
              )
            : Container(),
      ),
    );
  }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法将两个项目绘制到 Jframe

来自分类Dev

如何裁剪两个图像的差异?

来自分类Dev

如何裁剪两个图像的差异?

来自分类Dev

与skimage并排绘制两个图像

来自分类Dev

如何比较两个不同的图像,通过tcp发送差异,然后将差异与客户端上的图像合并?

来自分类Dev

在tkinter画布上的两个点之间绘制弧线

来自分类Dev

通过在画布上单击两个点来绘制矩形

来自分类Dev

如何在两个单元格之间的画布线上动态绘制图像

来自分类Dev

使用回调将图像绘制到画布的Javascript

来自分类Dev

绘制两个datetime64 [ns]之间的差异

来自分类Dev

R:计算并绘制两个密度国家之间的差异

来自分类Dev

绘制两个datetime64 [ns]之间的差异

来自分类Dev

Matlab_绘制两个图之间的差异

来自分类Dev

ggplot:将两个变量绘制到一个面中

来自分类Dev

将两个Dirs之间的差异复制到新目录中?

来自分类Dev

在画布上加载两个图像(Java)

来自分类Dev

将图像绘制到画布上会为每个绘制的新图像返回InvalidStateError,然后成功

来自分类Dev

比较两个图像/图片,并标记差异

来自分类Dev

CV-提取两个图像之间的差异

来自分类Dev

比较两个图像/图片,并标记差异

来自分类Dev

将鼠标滚轮绑定到两个画布,但只有一个有效

来自分类Dev

将Dockerfile分成两个图像

来自分类Dev

在MATLAB中在两个图像之间绘制匹配点

来自分类Dev

在两个图像之间绘制和更新线

来自分类Dev

在python中并排绘制两个图像

来自分类Dev

在两个图像之间绘制和更新线

来自分类Dev

Python:在图像上绘制两个区域

来自分类Dev

在图像上绘制之前如何合并两个文本

来自分类Dev

用图像而非颜色填充对象(将图像绘制到画布上)

Related 相关文章

  1. 1

    无法将两个项目绘制到 Jframe

  2. 2

    如何裁剪两个图像的差异?

  3. 3

    如何裁剪两个图像的差异?

  4. 4

    与skimage并排绘制两个图像

  5. 5

    如何比较两个不同的图像,通过tcp发送差异,然后将差异与客户端上的图像合并?

  6. 6

    在tkinter画布上的两个点之间绘制弧线

  7. 7

    通过在画布上单击两个点来绘制矩形

  8. 8

    如何在两个单元格之间的画布线上动态绘制图像

  9. 9

    使用回调将图像绘制到画布的Javascript

  10. 10

    绘制两个datetime64 [ns]之间的差异

  11. 11

    R:计算并绘制两个密度国家之间的差异

  12. 12

    绘制两个datetime64 [ns]之间的差异

  13. 13

    Matlab_绘制两个图之间的差异

  14. 14

    ggplot:将两个变量绘制到一个面中

  15. 15

    将两个Dirs之间的差异复制到新目录中?

  16. 16

    在画布上加载两个图像(Java)

  17. 17

    将图像绘制到画布上会为每个绘制的新图像返回InvalidStateError,然后成功

  18. 18

    比较两个图像/图片,并标记差异

  19. 19

    CV-提取两个图像之间的差异

  20. 20

    比较两个图像/图片,并标记差异

  21. 21

    将鼠标滚轮绑定到两个画布,但只有一个有效

  22. 22

    将Dockerfile分成两个图像

  23. 23

    在MATLAB中在两个图像之间绘制匹配点

  24. 24

    在两个图像之间绘制和更新线

  25. 25

    在python中并排绘制两个图像

  26. 26

    在两个图像之间绘制和更新线

  27. 27

    Python:在图像上绘制两个区域

  28. 28

    在图像上绘制之前如何合并两个文本

  29. 29

    用图像而非颜色填充对象(将图像绘制到画布上)

热门标签

归档