skip to Main Content

I’m perplexed. My app allows the user to takes photos with the camera/photo album, then at the end of the app those photos are printed into a PDF (using PDFKit). I’ve tried NUMEROUS ways to resize the photos so that the PDF is not so large (8mb for ~13 photos). I can’t get it working, however!

Here’s one solution I tried:

func resizeImage(image: UIImage) -> UIImage {
        
        if image.size.height >= 1024 && image.size.width >= 1024 {
            UIGraphicsBeginImageContext(CGSize(width: 1024, height: 1024))
            image.draw(in: CGRect(x: 0, y: 0, width: 1024, height: 1024))
            
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            return newImage!
        }
        else if image.size.height >= 1024 && image.size.width < 1024 {
            UIGraphicsBeginImageContext(CGSize(width: image.size.width, height: 1024))
            image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: 1024))
            
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            return newImage!
        }
        else if image.size.width >= 1024 && image.size.height < 1024 {
            UIGraphicsBeginImageContext(CGSize(width: 1024, height: image.size.height))
            image.draw(in: CGRect(x: 0, y: 0, width: 1024, height: image.size.height))
            
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            return newImage!
        }
        else {
            return image
        }
        
    }

And I call it like this:

let theResizedImage = resizeImage(image: image)

This works… sorta. It resizes the image to about a quarter of what it was before (still not great… but better). Here’s the issue though: when I draw "theResizedImage" to the PDF…

theResizedImage.draw(in: photoRect)

…the PDF file ends up being TWICE as large as before!! How?!?!?! I don’t understand how in the world an image that is resized is all-of-a-sudden two-times larger than it was in its original form as soon as it is drawn onto the PDF.

Someone please help me out with this. If you’ve got a better way to do it that allows for the image to be resized even further, then fantastic! I’m not sure if you’re familiar with a software called pdfFactoryPro (on PC), but it will resize a HUGE (like 40 something mb) file into one that’s like… 3 mb. I need these images resized big time. I need them to keep that small size when printed to the PDF, so that the PDF is small. The other option would be if you know some way to resize the PDF itself, like pdfFactoryPro does.

PLEASE explain your answers thoroughly and with code, or a link to a tutorial. I’m a beginner… if you couldn’t tell.

NOTE: Kindly make sure your code response is set up in a way that passes an image to the function… not a URL. As I stated earlier, I’m resizing photos that the user took with the camera, accessed from within the app (imagePickerController).

Thanks!

EDIT: I found out through a lot of Googling that even though you resize the image using UIImageJPEGRepresentation, when you print the image to the PDF, the RAW image is printed instead of the compressed image.

Someone named "Michael McNabb" posted this solution, but it is really out-dated, due to being in 2013:

NSData *jpegData = UIImageJPEGRepresentation(sourceImage, 0.75);
CGDataProviderRef dp = CGDataProviderCreateWithCFData((__bridge CFDataRef)jpegData);
CGImageRef cgImage = CGImageCreateWithJPEGDataProvider(dp, NULL, true, kCGRenderingIntentDefault);
[[UIImage imageWithCGImage:cgImage] drawInRect:drawRect];

Can someone please translate this to Swift 5 for me? It may be the solution to my question.

2

Answers


  1. Chosen as BEST ANSWER

    Turns out it's not just one task to resize images for printing to a PDF. It's two tasks.

    The first task is resizing the photo. For example, if you don't want your picture more than 1MB, then you resize your photo to 1024x1024. If you'd prefer the pixel quality be able to be even lower, then you can change it based on your needs.

    Resizing example:

    func resizeImage(image: UIImage) -> UIImage {
            let maxSize = CGFloat(768)
            
            if image.size.height >= maxSize && image.size.width >= maxSize {
                UIGraphicsBeginImageContext(CGSize(width: maxSize, height: maxSize))
                image.draw(in: CGRect(x: 0, y: 0, width: maxSize, height: maxSize))
                
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                
                return newImage!
            }
            else if image.size.height >= maxSize && image.size.width < maxSize {
                UIGraphicsBeginImageContext(CGSize(width: image.size.width, height: maxSize))
                image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: maxSize))
                
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                
                return newImage!
            }
            else if image.size.width >= maxSize && image.size.height < maxSize {
                UIGraphicsBeginImageContext(CGSize(width: maxSize, height: image.size.height))
                image.draw(in: CGRect(x: 0, y: 0, width: maxSize, height: image.size.height))
                
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                
                return newImage!
            }
            else {
                return image
            }
            
        }
    

    Disclaimer: I learned this code from another person on StackOverflow. I don't remember his name, but credits to him.

    Second, you then compress the resized image. I don't fully understand compression, but I set mine to something really low haha – do as you will.

    Compression example:

    func draw(image: UIImage, in rect: CGRect) {
            guard let oldImageData = image.jpegData(compressionQuality: 1) else {
                return
            }
            print("The size of the oldImage, before compression, is: (oldImageData.count)")
            guard let jpegData = image.jpegData(compressionQuality: 0.05),
                  let dataProvider = CGDataProvider(data: jpegData as CFData),
                  let cgImage = CGImage(jpegDataProviderSource: dataProvider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else {
                return
            }
            let newImage = UIImage(cgImage: cgImage)
            print("The size of the newImage printed on the pdf is: (jpegData.count)")
            newImage.draw(in: rect)
        }
    

    Disclaimer: I learned this code from someone named Michael McNabb. Credit goes to him.

    I went ahead and drew the image to the PDF at the end of that function. These two things combined took my PDF from being about 24MB or so to about 570 KB.


  2. func draw(image: UIImage, in rect: CGRect) {
        guard let jpegData = image.jpegData(compressionQuality: 0.75),
              let dataProvider = CGDataProvider(data: jpegData as CFData),
              let cgImage = CGImage(jpegDataProviderSource: dataProvider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else {
            return
        }
        UIImage(cgImage: cgImage).draw(in: rect)
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search