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

Swift PDFKit:如何在单个PDFPage中绘制多张图片?

在单个PDFPage中绘制多张图片的解决方案

核心思路

放弃PDFPage(image:)的初始化方式,手动创建空白PDFPage并通过其CGContext自定义绘制多张图片,完全控制图片的位置、尺寸和布局。

实现步骤(Swift示例)

  1. 创建空白PDF文档与页面
  2. 获取页面的绘图上下文
  3. 计算图片的布局参数(位置、尺寸)
  4. 在上下文中绘制所有图片(保持比例)
  5. 保存最终PDF

完整代码示例

import PDFKit
import UIKit // 若为macOS则替换为AppKit

// 辅助函数:计算图片在容器内的适配矩形(保持比例)
func aspectFitRect(for imageSize: CGSize, in containerRect: CGRect) -> CGRect {
    let scale = min(containerRect.width / imageSize.width, containerRect.height / imageSize.height)
    let scaledWidth = imageSize.width * scale
    let scaledHeight = imageSize.height * scale
    let x = containerRect.origin.x + (containerRect.width - scaledWidth) / 2
    let y = containerRect.origin.y + (containerRect.height - scaledHeight) / 2
    return CGRect(x: x, y: y, width: scaledWidth, height: scaledHeight)
}

// 1. 创建空白PDF文档
let pdfDocument = PDFDocument()

// 2. 创建指定尺寸的空白PDF页面(示例用A4尺寸)
let a4Size = CGSize(width: 595.28, height: 841.89)
let pdfPage = PDFPage(pageRect: CGRect(origin: .zero, size: a4Size))
pdfDocument.insert(pdfPage, at: 0)

// 3. 获取页面的绘图上下文
guard let context = pdfPage.context else {
    fatalError("无法获取PDF页面的绘图上下文")
}

// 替换为你的图片数组
let targetImages: [UIImage] = [
    UIImage(named: "img1")!,
    UIImage(named: "img2")!,
    UIImage(named: "img3")!
]

// 4. 定义布局参数(示例:3张图片横向均分,垂直居中,留边距)
let margin: CGFloat = 20
let totalAvailableWidth = a4Size.width - 2 * margin
let singleImageWidth = totalAvailableWidth / CGFloat(targetImages.count)
let singleImageHeight = singleImageWidth * 0.75 // 假设图片为4:3比例
let verticalCenterY = (a4Size.height - singleImageHeight) / 2

// 5. 开始绘图
context.beginPDFPage(nil)
context.saveGState()

// 适配坐标系统:iOS坐标系原点在左上角,PDF原点在左下角,需翻转
#if os(iOS)
context.translateBy(x: 0, y: a4Size.height)
context.scaleBy(x: 1.0, y: -1.0)
#endif

// 遍历绘制每张图片
for (index, image) in targetImages.enumerated() {
    let imageX = margin + CGFloat(index) * singleImageWidth
    let containerRect = CGRect(x: imageX, y: verticalCenterY, width: singleImageWidth, height: singleImageHeight)
    // 按比例绘制图片,避免拉伸
    let drawRect = aspectFitRect(for: image.size, in: containerRect)
    image.draw(in: drawRect)
}

context.restoreGState()
context.endPDFPage()

// 6. 保存PDF到本地文件(示例路径:文档目录)
let saveURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    .appendingPathComponent("multiImagePage.pdf")
pdfDocument.write(to: saveURL)

关键说明

  • 自定义布局:可以修改singleImageWidth、verticalCenterY等参数实现不同布局(如2x2网格、上下排列等)。
  • 坐标适配:macOS平台无需翻转坐标系(AppKit默认原点为左下角),代码中已通过条件编译区分。
  • 图片比例保护:aspectFitRect函数确保图片不会被拉伸变形,始终保持原始比例适配目标区域。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:05:25