You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现图片添加自定义文字并合并为单文件的技术问询

如何实现让用户在图片上添加标题,并将标题与图片文件整合为带文字的单个图片文件

参考UI效果

支持用户自定义标题的位置、字号、字体及颜色,最终生成带标题的合并图片

已完成的开发进度

Future<void> uploadImageWithCaption(Color color,double dx,double dy,String caption,double fontSize,String fontFamily) async {
  //  print("caption : $caption");

    // Load the image
     final image2 = img.decodeImage(File(image!.path).readAsBytesSync())!;

    // Add text to the image

    img.drawString(image2,caption,font: img.arial48 ,x: 700 ,y: 1400,color:img.ColorRgb8(color.red,color.green,color.blue));

    // Save the image with caption
    final newImageFile = File('${image!.path}_with_caption.jpg');
    newImageFile.writeAsBytesSync(img.encodeJpg(image2));

    await uploadStoryImage('image', XFile(newImageFile.path));
}

当前问题

  • 无法自定义文字在图片上的位置(当前硬编码了x:700,y:1400)
  • 无法自定义字号(当前固定用arial48字体)
  • 无法自定义字体(当前固定用arial48)
  • 寻求实现该功能的最优方案

改进方案:实现全自定义功能

1. 自定义文字位置

直接用传入的dx和dy替换硬编码坐标,同时添加边界判断避免文字超出图片范围:

// 确保坐标不超出图片边界,预留文字宽度/高度避免截断
final int x = dx.clamp(0, image2.width).toInt();
final int y = dy.clamp(0, image2.height).toInt();
img.drawString(image2, caption, font: selectedFont, x: x, y: y, color: img.ColorRgb8(color.red, color.green, color.blue));

2. 自定义字号与字体

image库默认字体是固定字号的,要实现动态字号和自定义字体,需加载外部字体文件生成对应字号的字体对象:

步骤1:配置字体资源

将.ttf字体文件放在项目assets/fonts目录下,在pubspec.yaml中声明:

flutter:
  assets:
    - assets/fonts/

步骤2:加载并生成指定字号的字体

// 加载自定义字体文件
final fontBytes = await rootBundle.load('assets/fonts/$fontFamily.ttf');
final ttfFont = img.TtfFont.fromBytes(fontBytes.buffer.asUint8List());
// 生成对应字号的字体对象
final selectedFont = ttfFont.renderGlyphs(fontSize);

3. 完整改进代码

import 'package:flutter/services.dart' show rootBundle;

Future<void> uploadImageWithCaption(Color color, double dx, double dy, String caption, double fontSize, String fontFamily) async {
  // 加载图片
  final imageBytes = File(image!.path).readAsBytesSync();
  final image2 = img.decodeImage(imageBytes)!;

  // 加载自定义字体并生成指定字号的字体
  final fontBytes = await rootBundle.load('assets/fonts/$fontFamily.ttf');
  final ttfFont = img.TtfFont.fromBytes(fontBytes.buffer.asUint8List());
  final selectedFont = ttfFont.renderGlyphs(fontSize);

  // 处理文字位置,避免超出图片边界
  final int x = dx.clamp(0, image2.width - selectedFont.maxWidth).toInt();
  final int y = dy.clamp(0, image2.height - selectedFont.maxHeight).toInt();

  // 绘制文字到图片
  img.drawString(
    image2,
    caption,
    font: selectedFont,
    x: x,
    y: y,
    color: img.ColorRgb8(color.red, color.green, color.blue),
  );

  // 保存合并后的图片
  final newImageFile = File('${image!.path}_with_caption.jpg');
  newImageFile.writeAsBytesSync(img.encodeJpg(image2));

  await uploadStoryImage('image', XFile(newImageFile.path));
}

最优实现思路

  1. 前端预览优化:用Flutter的Stack组件叠加图片和文本组件实现实时预览,用户调整参数时无需反复生成图片,仅在确认后执行图片合并操作,提升交互流畅度。
  2. 字体预加载:对常用字体提前预加载,减少每次处理时的字体加载耗时;同时设置默认字体,避免用户未选择字体时出错。
  3. 错误处理:添加try-catch块处理图片加载失败、字体文件不存在、坐标越界等异常,提升功能稳定性。
  4. 性能优化:图片处理操作放在异步线程执行,避免阻塞UI线程。

内容的提问来源于stack exchange,提问作者Abdelrahman Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 15:56:14