iosswiftios-pdfkit

Converting images to A4 size pdf using swift


I want to convert a UIImage array to a pdf file. PDF file page size should be A4. I tried with PDFKIT but the result is not appropriate.

What I want:

  1. A4 page size
  2. Image should be centered and scaled on the page(Array Images dimension is not identical)

What I tried:

    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
}

My Output is:

  1. Image missing
  2. Image Cropped
  3. Not in Center position

My Output

My Desire Output is:

My Desire Output

How Can I do this?


Solution

  • First you have to understand why you see what you see, and this explains that to some extent:

    PDFKit PDFView coordinate system add UIImage to PDF Center iOS Swift

    Since the origin of the PDF is bottom left, when you add something, it will be added to the bottom of the page which is why your images are at the bottom.

    What you probably need to do to fix this is as follows:

    1. Your graphics context should be the size of the PDF page, not the image
    2. You center your image within the graphics context
    3. Add this image to your pdf page

    Here are the modifications I would make to your resize function:

    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
    }
    

    And I believe you will get the desired output of the images centered within the PDF pages:

    UIImage added to PDFPage PDFKit centered iOS Swift

    Insert UIImage in PDF using PDFKit centered iOS Swift

    Update

    To alter the quality of the image generated, try playing around with the scale parameter of the UIGraphicsBeginImageContextWithOptions function.

    You can pass 2.0 for increasing the scale to 2 times or pass 0 to use the device's resolution.

    UIGraphicsBeginImageContextWithOptions(targetSize, false, 0.0)