使用 swift 将图像转换为 A4 尺寸的 pdf

问题描述 投票:0回答:2

我想将 UIImage 数组转换为 pdf 文件。 PDF 文件页面尺寸应为 A4。我尝试使用 PDFKIT 但结果不合适。

我想要的:

  1. A4页面尺寸
  2. 图像应在页面上居中并缩放(数组图像尺寸不相同)

我尝试过的:

    func makePDF(images: [UIImage])-> PDFDocument? {
    let pdfDoc = PDFDocument()
    
    for (index,image) in images.enumerated() {
        let resizedImage = resizeImage(image: image, targetSize: PDFPageSize.A4)
        guard let cgImage = resizedImage?.cgImage else { return pdfDoc }
        let uiimage = UIImage(cgImage: cgImage, scale: image.scale, orientation: .up)
        if let pdfPage = PDFPage(image: uiimage) {
            let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
            pdfPage.setBounds(page, for: PDFDisplayBox.mediaBox)
            pdfDoc.insert(pdfPage, at: index)
        }
        
    }
    return pdfDoc
}

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
    let size = image.size
    let widthRatio  = targetSize.width  / size.width
    let heightRatio = targetSize.height / size.height
    var newSize: CGSize
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
    }
    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

我的输出是:

  1. 图片缺失
  2. 图像已裁剪
  3. 不在中心位置

我的输出

我的愿望输出是:

我的愿望输出

我该怎么做?

ios swift ios-pdfkit
2个回答
3
投票

首先你必须明白为什么你会看到你所看到的东西,这在某种程度上解释了这一点:

PDFKit PDFView coordinate system add UIImage to PDF Center iOS Swift

由于 PDF 的来源位于左下角,因此当您添加内容时,它将被添加到页面底部,这就是为什么您的图像位于底部。

您可能需要执行以下操作来解决此问题:

  1. 您的
    graphics context
    应该是PDF页面的大小,而不是图像
  2. 将图像置于图形上下文的中心
  3. 将此图像添加到您的 pdf 页面

以下是我将对您的调整大小功能进行的修改:

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
    let size = image.size
    let widthRatio  = targetSize.width  / size.width
    let heightRatio = targetSize.height / size.height
    var newSize: CGSize
    
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
    }
    
    // Calculate the centerX and centerY
    let centerX = (targetSize.width - newSize.width) / 2.0
    let centerY = (targetSize.height - newSize.height) / 2.0
    
    // The rect of the image should be based on the center calculations
    let rect = CGRect(x: centerX,
                      y: centerY,
                      width: newSize.width,
                      height: newSize.height)
    
    // The graphics context should be created with the page dimensions
    UIGraphicsBeginImageContextWithOptions(targetSize, false, 1.0)
    
    // The rest remains the same
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

我相信您会获得以 PDF 页面为中心的图像的所需输出:

UIImage added to PDFPage PDFKit centered iOS Swift

Insert UIImage in PDF using PDFKit centered iOS Swift

更新

要改变生成图像的质量,请尝试使用

scale
函数的
UIGraphicsBeginImageContextWithOptions
参数。

您可以通过

2.0
将比例增加到 2 倍,或者通过
0
使用设备的分辨率。

UIGraphicsBeginImageContextWithOptions(targetSize, false, 0.0)


0
投票

下面是一种几乎完全符合您所描述的方法。它保存一个 pdf 文件,其中包含 CGImages 数组中的 a4 页。每个图像都位于其顶部的新页面上,并以始终适合页面宽度的方式进行缩放。您只需要调整传递给绘制方法的坐标的计算即可使各种比例的图像正确居中。

func savePDF(images: [CGImage], fileUrl: URL) -> Bool {
    let pdfData = NSMutableData()
    let a4pageSize = CGSize(width: 5953, height: 8419) // a4 at 720 dpi
    let marginSize = CGSize(width: 200, height: 200)
    let boxSize = CGSize(width: a4pageSize.width - marginSize.width * 2, height: a4pageSize.height - marginSize.height * 2)
    guard let consumer = CGDataConsumer(data: pdfData) else {
        return false
    }
    var mediaBox = CGRect(origin: .zero, size: a4pageSize)
    guard let pdfContext = CGContext(consumer: consumer, mediaBox: &mediaBox, nil) else {
        return false
    }
    for image in images {
        pdfContext.beginPage(mediaBox: &mediaBox)
        let imageSize = CGSize(width: image.width, height: image.height)
        let scale = boxSize.width / imageSize.width
        pdfContext.draw(image, in: CGRect(x: marginSize.width, y: a4pageSize.height - marginSize.height - imageSize.height * scale, width: imageSize.width * scale, height: imageSize.height * scale), byTiling: false)
        pdfContext.endPage()
    }
    pdfContext.closePDF()
    do {
        try pdfData.write(to: fileUrl)
    } catch {
        return false
    }
    return true
}
© www.soinside.com 2019 - 2024. All rights reserved.