Robert Brax Robert Brax - 1 month ago 12
iOS Question

Losing image orientation while converting an image to CGImage

I'm facing an image orientation issue when cropping a square portion of an image out of a rectangular original image. When image is in landscape, it's fine. But when it is in portrait, it seems that the image orientation is not preserved, which result in an image with wrong orientation AND bad crop:

func cropImage(cropRectangleCoordinates: CGRect) {

let croppedImage = originalImage

let finalCroppedImage : CGImageRef = CGImageCreateWithImageInRect(croppedImage.CGImage, cropRectangleCoordinates)

finalImage = UIImage(CGImage: finalCroppedImage)!


}


I think the problem is with
croppedImage.CGImage
. Here the image gets converted to
CGImage
, but it seems not to preserve the orientation.
It's easy to preserve orientation by using
UIImage
only, but to make the crop, image needs to be temporarily
CGImage
and this is the problem. Even if I reorient the image when converting back to
UIImage
, it might be in the correct orientation but the damage is already done when cropping
CGImage
.

This is a swift question, so please answer in swift, as the solution can be different in Objective-C.

Answer

I found a solution.... time will tell if it's robust enough, but it seems to work in all situations. That was a vicious bug to fix.

So the problem is that UIImage, in some case only, lose it's orientation when converted to CGImage. It affects portraits image, that are automatically put in landscape mode. So image that are landscape by default are not affected. But where the bug is vicious is that it doesn't affect ALL portrait images !! Also imageorientation value won't help for some image. Those problematic images are images that user has in it's library that he got from email, messages, or saved from the web, so not taken with a camera. These images possibly don't have orientation information, and thus in some case, an image in portrait.... REMAINS in portrait when converted to CGImage. I really got stuck on that until I realized that some of my image in my device library were saved from messages or emails.

So the only reliable way I found to guess which image will be reoriented, is to create both version of a given image: UIImage, and CGImage, and compare their height value. If they are equal, then the CGImage version will not be rotated and you could work with it as expected. But if they height are different, you can be sure that the CGImage conversion from CGImageCreateWithImageInRect will landscapize the image. In this case only, I swap the x/y coordinate of origin, that I pass as rectangle coordinate to crop and it treats those special images correctly.

That was a long post, but the main idea is to compare CGImage height to UIImage width, and if they are different, expect origin point to be inverted.

Comments