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

Flutter中使用printing包转换PDF为PNG时页面边距丢失问题

Flutter PDF转PNG丢失页面边距的解决方法

我在Flutter应用中用pdf库生成带边距的PDF,使用printing包将PDF转成PNG图片时,发现生成的图片丢失了原PDF设置的页面边距。

对比效果:

  • 原PDF截图:PDF截图
  • 转换后的PNG:printing包生成的图片

原转换代码

var pageNo = 0;
await for (var page in Printing.raster(widget.pdf, dpi: 100)) {
  pageNo++;
  final image = await page.toPng();
  await File('/storage/emulated/0/Download/Invoice-${widget.invoiceNo}-page$pageNo.png')
              .writeAsBytes(image);
}

生成PDF的PageTheme代码

pw.PageTheme(
      margin: const pw.EdgeInsets.all(40),
      theme: pw.ThemeData(defaultTextStyle: pw.TextStyle(font: font)),
      pageFormat: PdfPageFormat.a4.copyWith(
        marginRight: 40,
        marginLeft: 40,
        marginBottom: 40,
        marginTop: 40,
      ),
      buildBackground: (_) => pw.FullPage(
        ignoreMargins: false,
        child: pw.Container(color: PdfColors.white),
      ),
    )

解决办法

printing包的Printing.raster方法默认只渲染PDF的内容区域(即去掉边距后的部分),要保留边距,可通过以下两种方式处理:

方法1:使用fullPage参数(推荐)

调用Printing.raster时添加fullPage: true参数,强制渲染整个PDF页面(包含边距):

var pageNo = 0;
await for (var page in Printing.raster(widget.pdf, dpi: 100, fullPage: true)) {
  pageNo++;
  final image = await page.toPng();
  await File('/storage/emulated/0/Download/Invoice-${widget.invoiceNo}-page$pageNo.png')
              .writeAsBytes(image);
}

方法2:手动为图片添加边距

若fullPage参数不生效,可借助image库手动为生成的PNG添加对应边距:

  1. 先在pubspec.yaml添加依赖:
dependencies:
  image: ^4.0.17
  1. 修改转换代码:
import 'package:image/image.dart' as img;

var pageNo = 0;
await for (var page in Printing.raster(widget.pdf, dpi: 100)) {
  pageNo++;
  final image = await page.toPng();
  // 解析原图片
  final srcImg = img.decodePng(image)!;
  // 换算边距对应的像素值(40pt = 40 * dpi/72)
  final marginPx = (40 * 100 / 72).round();
  // 创建带边距的新画布
  final newImg = img.Image(
    width: srcImg.width + marginPx * 2,
    height: srcImg.height + marginPx * 2,
  );
  // 填充和PDF一致的白色背景
  img.fill(newImg, img.getColor(255, 255, 255));
  // 将原图片绘制到新画布的边距内侧
  img.copyInto(
    newImg,
    srcImg,
    dstX: marginPx,
    dstY: marginPx,
  );
  // 编码为PNG并保存
  final newPng = img.encodePng(newImg);
  await File('/storage/emulated/0/Download/Invoice-${widget.invoiceNo}-page$pageNo.png')
              .writeAsBytes(newPng);
}

说明

方法1利用printing包原生参数实现完整页面渲染,操作最简单;方法2适合自定义边距样式或旧版本printing包不支持fullPage参数的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:43:29