[SOLVED] Converting images to A4 size pdf using swift

Issue

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)

Answered By – Shawn Frank

Answer Checked By – Pedro (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.