iosmemorycrashuiimageuiimagejpegrepresentation

ios UIImageJPEGRepresentation() with large image crash


I am developing an iOS app with xcode 9 and iPhone SE.

I get an large photo which is a 19MB JPEG picture with NSData format from iPhone album.

Then I need to fix this photo orientation, so I have to convert this photo from NSData to UIImage. Then I need to revert this UIImage to NSData(less than 20MB).

When I try to use UIImageJPEGRepresentation() and the device memory shot up to 1.2G and crash.

When I try to user UIImagePNGRepresentation(), the result NSData object is larger than 20MB.

I have no idea how to do this. Can anyone help? thanks!


Solution

  • I imagine a 19MB jpeg uncompressed will take up a huge amount of space. I'm not surprised your device memory goes up so much. Jpegs store an orientation attribute in their properties data. To avoid having to uncompress the jpeg you can instead just edit the properties data to fix the orientation.

    You can edit properties as follows if imageData is your jpeg data. This uses the Swift Data object but you can jump between NSData and Data fairly easily

    // create an imagesourceref
    if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
    
        // get image properties
        var properties : NSMutableDictionary = [:]
        if let sourceProperties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) {
            properties = NSMutableDictionary(sourceProperties)
        }
    
        // set image orientation
        properties[kCGImagePropertyOrientation] = 4
    
        if let uti = CGImageSourceGetType(source) {
    
            // create a new data object and write the new image into it
            let destinationData = NSMutableData()
            if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
    
                // add the image contained in the image source to the destination, overidding the old metadata with our modified metadata
                CGImageDestinationAddImageFromSource(destination, source, 0, properties)
                if CGImageDestinationFinalize(destination) == false {
                    return nil
                }
                return destinationData as Data
            }
        }
    }
    

    The orientation value is as follows

    portrait = 6
    portraitupsidedown = 8
    landscape_volumebuttons_up = 3
    landscape_powerbutton_up = 1