无法使用 PDFKit 添加图像并保存到 pdf 文件

Cannot add image and save to pdf file using PDFKit

我有一个 class 可以通过在 pdf 中插入图像来编辑 pdf,并使用插入的图像保存新的 pdf。

下面的代码是我通过创建自定义 PDFAnnotation 来实现场景的方式。我将类型指定为 .widget 而不是 .stamp 以避免在对角线上画黑线。

final private class PDFImageAnnotation: PDFAnnotation {

    var image: UIImage?

    convenience init(_ image: UIImage?, bounds: CGRect, properties: [AnyHashable: Any]?) {
        self.init(bounds: bounds, forType: PDFAnnotationSubtype.widget, withProperties: properties)
        self.image = image
    }

    override func draw(with box: PDFDisplayBox, in context: CGContext) {
        super.draw(with: box, in: context)

        // Drawing the image within the annotation's bounds.
        guard let cgImage = image?.cgImage else { return }
        context.draw(cgImage, in: bounds)
    }
}

下面是我如何显示 pdf 和 select 图像以保存为 pdf

private func setupPDF() {
    guard let url = url else { return }
    pdfView.document = PDFDocument(url: url)
    pdfView.autoScales = true
}

private func addImageAndSave(_ image: UIImage) {
    guard let page = pdfView.currentPage else { return }

    let pageBounds = page.bounds(for: .cropBox)
    let imageBounds = CGRect(x: pageBounds.midX, y: pageBounds.midY, width: image.size.width, height: image.size.height)
    let imageStamp = PDFImageAnnotation(image, bounds: imageBounds, properties: nil)
    imageStamp.shouldDisplay = true
    imageStamp.shouldPrint = true
    page.addAnnotation(imageStamp)

    // Save PDF with image
    let fileName = url.lastPathComponent
    let saveUrl = FileManager.default.temporaryDirectory.appendingPathComponent(fileName, isDirectory: false)
    pdfView.document?.write(to: saveUrl)
}

然而结果pdf文件如下

右栏的预览确实显示了图片,但是当在 Preview 应用程序或任何浏览器中打开 pdf 时,图片不存在。

如何让图片出现在最终的pdf文件中?

谢谢。

我还必须在 PDFPage 上绘制该图像,使它们出现在保存的 pdf 文件中

final private class ImagePDFPage: PDFPage {

    /// A flag indicates whether to draw image on a page
    /// 
    /// - Note: Set this to `true` before write pdf to file otherwise the image will not be appeared in pdf file
    var saveImageToPDF: Bool = false

    private var imageAnnotation: EkoPDFImageAnnotation? = nil


    func addImageAnnotation(_ annotation: EkoPDFImageAnnotation) {
        imageAnnotation = annotation
        addAnnotation(annotation)
    }

    func removeImageAnnotation() {
        guard let imageAnnotation = imageAnnotation else { return }
        self.imageAnnotation = nil
        removeAnnotation(imageAnnotation)
    }

    override func draw(with box: PDFDisplayBox, to context: CGContext) {
        super.draw(with: box, to: context)

        guard saveImageToPDF,
              let annotation = imageAnnotation,
              let cgImage = annotation.image?.cgImage else { return }
        context.draw(cgImage, in: annotation.bounds)
    }
}

并更新 PDFDocument.delegate 以告知将 ImagePDFPage 用作 pdf 页面的 class

extension PDFEditorViewController: PDFDocumentDelegate {
    func classForPage() -> AnyClass {
        return ImagePDFPage.self
    }
}

结果