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:
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:
My Desire Output is:
How Can I do this?
First you have to understand why you see what you see, and this explains that to some extent:
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:
graphics context
should be the size of the PDF page, not the imageHere 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:
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)