【问题标题】:Flutter - How to tint an image's black color only, without touching transparent or white part?Flutter - 如何仅将图像的黑色着色,而不接触透明或白色部分?
【发布时间】:2021-01-10 03:24:51
【问题描述】:

对于像下面这样的图像,它有一些我想要保持白色的白色部分,我想要保持不变的透明背景,以及我想要动态着色的黑色部分,例如绿色、红色等。

在 iOS 中,我可以使用如下混合方法获得效果:

UIGraphicsBeginImageContextWithOptions(size, false, scale)
draw(in: rect)
color.set()
UIRectFillUsingBlendMode(rect, .screen)
draw(in: rect, blendMode: .destinationIn, alpha: color.alpha())

但我一直无法找到在 Flutter 中为其着色的方法 - 非常感谢帮助!

【问题讨论】:

    标签: image flutter tint


    【解决方案1】:

    首先需要安装Image

    导入包

    import 'package:image/image.dart' as Img;
    

    然后使用下面的代码来改变图片的背景颜色

    Future<Uint8List> changeBackgroundOfImage(
          {@required Uint8List bytes,
          @required List<int> removeColorRGB,
          @required List<int> addColorRGB}) async {
        Img.Image image = Img.decodeImage(bytes);
        Img.Image newImage = await _customeColor(
            src: image, removeColorRGB: removeColorRGB, addColorRGB: addColorRGB);
        var newPng = Img.encodePng(newImage);
        return newPng;
      }
    
    Future<Img.Image> _customeColor(
          {Img.Image src, List<int> removeColorRGB, List<int> addColorRGB}) async {
        var pixels = src.getBytes();
        for (int i = 0, len = pixels.length; i < len; i += 4) {
          if (pixels[i] == removeColorRGB[0] &&
              pixels[i + 1] == removeColorRGB[1] &&
              pixels[i + 2] == removeColorRGB[2]) {
            pixels[i] = addColorRGB[0];
            pixels[i + 1] = addColorRGB[1];
            pixels[i + 2] = addColorRGB[2];
          }
        }
    
        return src;
      }
    

    注意:上面的函数需要三个参数,第一个是图像字节,第二个和第三个是removeColorRGB,addColorRGB是一个RGB值的List,见下面的代码行

    Uint8List newbyte = await changeBackgroundOfImage(
    bytes: bytes, removeColorRGB: [0, 0, 0], addColorRGB: [66, 245, 120]);
    

    完整代码:

    import 'package:image/image.dart' as Img;
    
    class BlendMode extends StatelessWidget {
      static Future<Uint8List> changeBackgroundOfImage(
          {@required Uint8List bytes,
          @required List<int> removeColorRGB,
          @required List<int> addColorRGB}) async {
        Img.Image image = Img.decodeImage(bytes);
        Img.Image newImage = await _customeColor(
            src: image, removeColorRGB: removeColorRGB, addColorRGB: addColorRGB);
        var newPng = Img.encodePng(newImage);
        return newPng;
      }
    
      static Future<Img.Image> _customeColor(
          {Img.Image src, List<int> removeColorRGB, List<int> addColorRGB}) async {
        var pixels = src.getBytes();
        for (int i = 0, len = pixels.length; i < len; i += 4) {
          if (pixels[i] == removeColorRGB[0] &&
              pixels[i + 1] == removeColorRGB[1] &&
              pixels[i + 2] == removeColorRGB[2]) {
            pixels[i] = addColorRGB[0];
            pixels[i + 1] = addColorRGB[1];
            pixels[i + 2] = addColorRGB[2];
          }
        }
    
        return src;
      }
      
      convertImage() async {
        ByteData imageData1 = await rootBundle.load("assets/images/Vgv5e.png");
        Uint8List bytes = imageData1.buffer.asUint8List();
    
        Uint8List newbyte = await AppUtils.changeBackgroundOfImage(
        bytes: bytes, removeColorRGB: [0, 0, 0], addColorRGB: [66, 245, 120]);
    
        return newbyte;
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Container(
            child: FutureBuilder(
                future: convertImage(),
                builder: (context, snapshot) => Image.memory(snapshot.data)),
          ),
        );
      }
    }
    

    重要提示:重要的是您的图片背景必须是一种颜色,这意味着背景不应采用阴影或渐变来完全去除背景颜色

    【讨论】:

    • 感谢分享!差不多了,有 2 个问题: 1. 如果你放大图像并仔细观察它的白色边框,你可以看到它周围的一些灰色像素,这是通常的渲染模糊效果 - 在 iOS 上,这部分也被新颜色替换了,但是在这里只替换了确切的黑色(例如,我尝试做一个像素差异绝对值
    猜你喜欢
    • 2023-03-07
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    • 2013-01-13
    • 2020-03-03
    • 1970-01-01
    相关资源
    最近更新 更多