2

This one is weird...

Background: My iPad app supports both landscape orientations, no portrait. It takes pictures with a UIImagePickerController. After taking the pictures, I display them as little thumbnails in a UICollectionView.

First, I noticed that when taking the pictures in landscape right orientation, everything worked fine. However, when I took the pictures in landscape left orientation, and applied the obtained image to my cell's image view, it displays upside down.

After searching a bit, I found this answer and it fixed my problem. Basically, the pictures taken in landscape left orientation get their imageOrientation property set to .Down. I used this code (switch statement):

extension MyViewController : UIImagePickerControllerDelegate
{
    func imagePickerController(picker: UIImagePickerController,
        didFinishPickingMediaWithInfo info: [String : AnyObject]
        )
    {

        var image:UIImage!

        if (info[UIImagePickerControllerEditedImage] as? Bool) == true {
            image = info[UIImagePickerControllerEditedImage] as? UIImage
        }
        else {
            image = info[UIImagePickerControllerOriginalImage] as? UIImage
        }

        if image == nil {    
            return 
        }

        switch image.imageOrientation {

        case .Up, .UpMirrored:
            break

        default:
            image = UIImage(CGImage: image.CGImage!, scale: 1.0, orientation: UIImageOrientation.Up)
        }

So far, so good.

Next, I thought perhaps I'm better off storing an additional, resized version of the original image that is closer in size to the actual thumbnail, to reduce the memory pressure when displaying several thumbnails: Here, I'm assuming UIImage stores the original (large) image, regardless of how it is resized to fit in the view's bounds.

So, I used this code to generate a thumbnail:

    UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
    image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
    let thumbnailImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

Now, the same that was happening again happens with the thumbnail: When taken on landscape left, it displays upside down (even though the resizing was based on the already orientation-corrected image). In addition, the same orientation fix will not work: logging the thumbnail's imageOrientation property shows that it is already set to ".Up":

switch thumbnailImage.imageOrientation {
    case .Up, .UpMirrored:
        print("Thumb orientation is UP")
        // > THIS CASE ALWAYS RUNS
        break

    default:
        print("Thumb orientation is NOT UP")
        // > THIS CASE NEVER RUNS             
    }

The resizing code above can not be inherently wrong, because it works in one device orientation (landscape right)! What's going on?

Perhaps I should forcibly flip the thumbnail vertically only when I fix the orientation of the original image? But this sounds like a hack.

I don't understand why, after copying the original image with a new orientation (.Down fixed to .Up), it displays upright, but a resized copy of that fixed image does not (despite inheriting the .Up orientation).

Community
  • 1
  • 1
Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189

1 Answers1

0

Okay, found a workaround: Create the thumbnail first, then fix (if necessary) the original image and the thumbnail's orientation (by copying them):

// Create thumbnail:

UIGraphicsBeginImageContextWithOptions(CGSizeMake(94, 76), true, 0.0)

image.drawInRect(CGRectMake(0, 0, 94, 76))

var thumbnailImage = UIGraphicsGetImageFromCurrentImageContext()

UIGraphicsEndImageContext()


// Fix orientation:

switch image.imageOrientation {
case .Up, .UpMirrored:
    break

default:
    image = UIImage(CGImage: image.CGImage!, scale: 1.0, orientation: UIImageOrientation.Up)
}


let imageData = UIImagePNGRepresentation(image)


switch thumbnailImage.imageOrientation {
case .Up, .UpMirrored:
    break

default:
    thumbnailImage = UIImage(CGImage: thumbnailImage.CGImage!, scale: 1.0, orientation: UIImageOrientation.Up)
}

// (...use both images...)

Still, like before, the thumbnail re-orienting case is never executed (thumbnail orientation always equals .Up from the beginning).

I really don't understand what's going on here, but perhaps some image data is being referenced somewhere instead of being copied, and that causes inconsistencies. I must be missing some detail in the specification...

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189