-3

I created a new file UIImage+compress.swift and it's in the same directory as my PhotoController.swift. I was looking for ways to compress a image before storing it and I found the following link that explains the process: How to compress of reduce the size of an image before uploading to Parse as PFFile? (Swift)

I've tried to directly call UIImageJPEGRepresentation for the image but that doesn't get me anywhere. Tried making the extension method public hoping that'd solve the problem but that didn't work out either. I tried to look for similar questions in stackOverflow but they are different in that none explains why the method is not usable.

This is the code for extension method:

import UIKit

extension UIImage {
enum JPEGQuality: CGFloat {
    case lowest  = 0
    case low     = 0.25
    case medium  = 0.5
    case high    = 0.75
    case highest = 1
}

/// Returns the data for the specified image in JPEG format.
/// If the image object’s underlying image data has been purged, calling this function forces that data to be reloaded into memory.
/// - returns: A data object containing the JPEG data, or nil if there was a problem generating the data. This function may return nil if the image has no data or if the underlying CGImageRef contains data in an unsupported bitmap format.
func jpeg(_ jpegQuality: JPEGQuality) -> Data? {
    return UIImageJPEGRepresentation(self, jpegQuality.rawValue)
}

}

This is the code for PhotoController where I try to call the extension method:

class PhotoController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

... ...

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    let mediaType = info[UIImagePickerControllerMediaType] as! NSString



    if mediaType.isEqual(to: kUTTypeImage as String) {
        let image = info[UIImagePickerControllerOriginalImage] as! UIImage

        var res = image.jpeg(.lowest) as! UIImage

        if (newMedia == true) {
            UIImageWriteToSavedPhotosAlbum(res,
                                           self,
                                           #selector(PhotoController.image(image:didFinishSavingWithError:contextInfo:)),
                                           nil)
            }
        }
        self.dismiss(animated: true, completion: nil)
    }

}

I keep getting the error: Value of type 'UIImage' has no member 'compress'.

Also, how do I print the image size to make sure that it's indeed compressed?

shiv
  • 165
  • 1
  • 20

5 Answers5

1

Here's how to make your Swift file part of the target, so that other code can see it.

First, click the project, edit that app target, and find the Build Phases. Open the Compile Sources section.

enter image description here

Click the Plus button at the bottom left. Find your file and choose it. (If you don't see it listed, choose Add Other and find it.)

enter image description here

matt
  • 515,959
  • 87
  • 875
  • 1,141
0

May be a compiler glitch , but don't assign the response to the same object UIImage as it's of type Data

 let res = image.compress(.lowest)
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
0

The method is called jpeg(_:), not compress:

let imageData = image.jpeg(.lowest)

Since the return value is optional, you might want to check:

guard let imageData = image.jpeg(.lowest) else { return }

To get the size in bytes, simply see imageData.count.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
0

Where is the method 'compressed' declared in your extension?? according to your setup, you need to do this...

image.jpeg(.medium)
MXNMike
  • 173
  • 11
0

I still don't know why the extension method doesn't work in a separate file. I tried @RajeshKumar R's suggestion and the extension works while it's still in the PhotoController.swift file.

After using the .jpeg function with lowest setting, the image size shrunk from 14 MB to 14 MB.

 Image size: 13671.8408203125
 Compressed image size: 7796.853515625 

Here's how to make the code work.

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    let mediaType = info[UIImagePickerControllerMediaType] as! NSString



    if mediaType.isEqual(to: kUTTypeImage as String) {
        let image = info[UIImagePickerControllerOriginalImage] as! UIImage
        printImageSize(image: image)

        var imageData = image.jpeg(.lowest)

        let imageCompressed = UIImage(data: imageData!)
        printImageSize(image: imageCompressed!)

        if (newMedia == true) {
            UIImageWriteToSavedPhotosAlbum(imageCompressed!,
                                           self,
                                           #selector(PhotoController.image(image:didFinishSavingWithError:contextInfo:)),
                                           nil)
        }
    }
    self.dismiss(animated: true, completion: nil)
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
shiv
  • 165
  • 1
  • 20
  • "I still don't know why the extension method doesn't work in a separate file". You were told what to do: make sure _UIImage+compress.swift_ is part of the app target. It seems that you didn't do that. – matt May 10 '19 at 20:19
  • @matt "I don't see target membership on my file options – Shivansh Suhane 1 hour ago" Not sure why is that. I'm still working on fixing that – shiv May 10 '19 at 20:28
  • You might not see it but that's still the right answer to your original problem. – matt May 10 '19 at 20:58
  • OK, I gave an answer with foolproof instructions. – matt May 10 '19 at 21:15