flutter图片添加水印

flutter为图片右下角添加上水印
在这里插入图片描述

//制造字符串水印图片
  _makeStrMarkImage(String str, double fontSize) async {
    final picRecorder = ui.PictureRecorder();
    final paragraphBuilder = ui.ParagraphBuilder(
      ui.ParagraphStyle(
        textAlign: TextAlign.left,
        fontSize: fontSize,
      ),
    );
    paragraphBuilder.pushStyle(ui.TextStyle(
      fontSize: fontSize,
      color: Colors.white,
      shadows: <Shadow>[
        Shadow(
          color: Color(0xFFF4F4F4).withAlpha(25),
          blurRadius: 1.0,
          offset: Offset(-3, 0),
        ),
        Shadow(
          color: Color(0xFFF4F4F4).withAlpha(25),
          blurRadius: 3.0,
          offset: Offset(-3, -3),
        ),
      ],
    ));
    paragraphBuilder.addText(str);
    final paragraph = paragraphBuilder.build()
      ..layout(ui.ParagraphConstraints(
        width: fontSize * 10.0,
      ));
    final lineMetrics = paragraph.computeLineMetrics();
    double width = 0;
    lineMetrics.forEach((element) {
      if (element.width > width) {
        width = element.width;
      }
    });
    final cvs = Canvas(
      picRecorder,
      Rect.fromLTRB(0, 0, width, paragraph.height,),
    );
    cvs.drawParagraph(paragraph, Offset(0, 0));
    final pic = picRecorder.endRecording();
    final waterMark = await pic.toImage(
      width.toInt(),
      paragraph.height.toInt(),
    );
    return waterMark;
  }

  //确定水印位置、大小,并将水印添加到原图
  _makeImageMark(img.Image image, String markStr,img.Image imageLogo,[bool isLeft = true]) async {
    final imgHeight = image.height;
    final imgWidth = image.width;
    final ratio = imgWidth / 375.0;
    final fontSize = ratio * 24.0 ~/ 2.0;
    final edgeSize = ratio * 8.0 ~/ 2.0;
    final waterMarkImage = await _makeStrMarkImage(markStr, fontSize.toDouble());
    final waterMarkBytes = await waterMarkImage.toByteData(format: ui.ImageByteFormat.rawRgba);
    final waterMarkImg = img.Image.fromBytes(
      waterMarkImage.width,
      waterMarkImage.height,
      Uint8List.sublistView(waterMarkBytes),
    );
    final resizedImage = img.copyResize(imageLogo,width: edgeSize * 6,height: edgeSize * 3);

    int dstX;
    int dstY = imgHeight - waterMarkImg.height - edgeSize;
    if (isLeft) {
      dstX = edgeSize;
    } else {
      dstX = imgWidth - edgeSize - waterMarkImg.width;
    }

    img.copyInto(
      image,
      waterMarkImg,
      dstX: dstX,
      dstY: dstY,
    );

    img.copyInto(
      image,
      resizedImage,
      dstX: dstX - (edgeSize * 7),
      dstY: dstY + edgeSize,
    );
  }

 getDecodeImage(Uint8List uInt8List){
    Completer<img.Image> completer = new Completer<img.Image>();
    img.Image originImage = img.decodeImage(uInt8List);
    completer.complete(originImage);
    return completer.future;
  }

  /*
  * 图片左、右下脚添加图片+文字水印
  * */
  Future<String> addWatermarkToImage(Uint8List uInt8List,{Uint8List markUInt8List,String markUserName}) async {
    File targetFile;
    if (uInt8List != null) {
      final markLogo = await getDecodeImage(markUInt8List);
      final originImage = await getDecodeImage(uInt8List);

      final Directory _directory = await getTemporaryDirectory();
      final Directory _imageDirectory = await new Directory('${_directory.path}/image/').create(recursive: true);
      String _targetPath = _imageDirectory.path;
      await _makeImageMark(
          originImage,
          markUserName==null?''
          :'@$markUserName',
          markLogo, false);

      final bytes = img.writeJpg(originImage);
      targetFile = File('${_targetPath}watermark${DateTime.now().millisecondsSinceEpoch}.jpg');
      targetFile.writeAsBytesSync(bytes);
      print('====targetFilePath=${targetFile.path}');
    }
    return Future.value(targetFile.path);
  }

调用

//图片添加水印
  addWatermarkToImages(BuildContext context) async{
    waterImages.clear();
    if(addWaterMark && state.selectImageList.length>0){
      ByteData byteData;
      for (int i = 0; i < state.selectImageList.length; i++) {
        Asset asset = state.selectImageList[i];
        //File类型图片时
       // File file = state.selectImageList[i];
        byteData = await asset.getByteData();
       //File类型图片时
        //Uint8List uint8ListData = file.readAsBytesSync();
        String watermarkImagePath =
        await Utils().addWatermarkToImage(byteData.buffer.asUint8List(),
            markUInt8List: watermarkUint8List,markUserName: userInfo.user.nickname);
        if(watermarkImagePath != null && watermarkImagePath.isNotEmpty){
          waterImages.add(watermarkImagePath);
          print('==waterImages length=$i=${waterImages.length}');
        }
      }
      //发布
      submit(context);
      update();
    }
  }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Flutter中给图片水印的步骤如下: 1. 将图片加载到内存中,可以使用`ImageProvider`或`File`类来加载。 2. 创建一个新的画布,并将原始图片绘制到画布上。 3. 在画布上绘制水印,可以使用`TextPainter`类来绘制文字水印,或使用`ImageProvider`类来加载图片水印。 4. 将绘制完水印的画布保存为新的图片文件。 下面是一个简单的示例代码: ```dart import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import 'package:image/image.dart' as img; class WatermarkImage extends StatefulWidget { final String imagePath; final String watermarkText; WatermarkImage({required this.imagePath, required this.watermarkText}); @override _WatermarkImageState createState() => _WatermarkImageState(); } class _WatermarkImageState extends State<WatermarkImage> { late String _watermarkImagePath; @override void initState() { super.initState(); _addWatermarkToImage(); } Future<void> _addWatermarkToImage() async { final directory = await getTemporaryDirectory(); final imageFile = File(widget.imagePath); final image = img.decodeImage(imageFile.readAsBytesSync())!; final watermark = img.Image.fromBytes( 100, 50, img.encodePng(img.copyResize( img.decodeImage( (await rootBundle.load('assets/images/watermark.png')).buffer.asUint8List(), )!, width: 100, height: 50, )), ); final textPainter = TextPainter( text: TextSpan( text: widget.watermarkText, style: TextStyle( fontSize: 20, color: Colors.white, ), ), textDirection: TextDirection.ltr, )..layout(); final canvas = img.Canvas(image); canvas.drawImage(watermark, 0, 0); canvas.drawImage( img.copyResize( img.Image.fromBytes( textPainter.width.toInt(), textPainter.height.toInt(), img.encodePng( (await textPainter.toPicture().toImage(textPainter.width.toInt(), textPainter.height.toInt())) .toByteData(format: img.PixelFormat.rgba8888)! .buffer .asUint8List(), ), ), width: 100, height: 50, ), image.width - 100, image.height - 50, ); final watermarkImageFile = File('${directory.path}/watermark_${DateTime.now().millisecondsSinceEpoch}.jpg'); watermarkImageFile.writeAsBytesSync(img.encodeJpg(image)); setState(() { _watermarkImagePath = watermarkImageFile.path; }); } @override Widget build(BuildContext context) { return _watermarkImagePath != null ? Image.file( File(_watermarkImagePath), fit: BoxFit.cover, ) : Container(); } } ``` 这个示例代码将加载指定路径的图片文件,并在右下角添加一个水印图标和文字水印。最终生成的带有水印的新图片文件将保存在应用程序的临时目录中。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值