3

I am working on developing an app that uses CloudKit to store and retrieve image files as CKAsset objects. Normally, this works great and I love CloudKit's small learning curve. Periodically though, I have this peculiar issue where an image is being stored either totally upside-down, or 90º to the left or to the right. Here is an example of an image that was stored improperly:

Example of my MacBook curiously rotated 90º to the left

I took that picture with my iPhone 5s, in portrait orientation (I didn't save the original image to my device, as I only intended to save it in the cloud or else I'd post the original here too. I figured since it's a MacBook Pro sitting at a table you could figure out the original intended orientation of the picture). Anyways, I have this problem not only with images fresh from the camera, but also with an image chosen from my photo library.

Here is the code I use to store the image via CloudKit:

let newRecord:CKRecord = CKRecord(recordType: "ImageProject")
let imageData:NSData = UIImagePNGRepresentation(game.referenceImage)!
let path = self.documentsDirectoryPath.stringByAppendingPathComponent(self.imageDirectoryName)
imageURL = NSURL(fileURLWithPath: path)
imageData.writeToURL(imageURL, atomically: true)
UIImagePNGRepresentation(game.referenceImage)!.writeToFile(path, atomically: true)
let imageFile:CKAsset?  = CKAsset(fileURL: NSURL(fileURLWithPath: path))

newRecord.setValue(imageFile, forKey: "referenceImage")

    // Save the record into the public database
    if let database = self.publicDatabase {

      database.saveRecord(newRecord, completionHandler: { (record:CKRecord?, error:NSError?) in

            // Check if there was an error
            if error != nil {
                NSLog((error?.localizedDescription)!)
            }
            else {
                // There wasn't an error
                dispatch_async(dispatch_get_main_queue()) {

                        if let savedRecord = record {
                            print("Image Successfully Saved")
                        }
                }
            }
        })
      }

Here the game is just an NSObject I have created called SavedGame, that just stores variables, specifically for this case the referenceImage as a UIImage. I'm pretty sure that my retrieval process is not the issue, because I noticed when I go to the CK Dashboard and download the image after it's been stored, it's rotated there as well. Just in case, here is the code I use to retrieve the image:

// Initialize the database and start the query
..........
for record in returnedRecords {
    if let retrievedImage = record.objectForKey("referenceImage") as! CKAsset? {
         let newGame:SavedGame = SavedGame()                  
         if let data = NSData(contentsOfURL: retrievedImage.fileURL) {
              newGame.referenceImage =  UIImage(data: data)!
         }
     }
}

Could anybody give me some sort of guidance as to where I might be making a mistake? This problem is not consistent at all, it's very strange. I would estimate it happens maybe 5-10% of the time. I don't know if its a CK issue, or a problem with my code. Any help would be greatly appreciated. Thanks in advance!

tktsubota
  • 9,371
  • 3
  • 32
  • 40
Pierce
  • 3,148
  • 16
  • 38
  • 1
    Looks like orientation information is missing, probably use UIImageJPEGRepresentation() but not UIImagePNGRepresentation. – Allen Mar 13 '16 at 17:43
  • Could you give me an example of how I store the orientation info? I know how to do the JPEGRep, but not how to explicitly tell the asset what orientation. I don't want to have to do any CGAffineTransformations, and I assume that wouldn't be necessary. – Pierce Mar 13 '16 at 18:01
  • It depends how do you get an image. If it from iPhone camera or jpeg with exif, I believe you can find many ways to get their orientation. If an image from somewhere, ex download from internet. I suggest don't change it to PNG, at least jpg itself could keep its original exif information. – Allen Mar 13 '16 at 18:07
  • Thanks for the response Allen. My app would only get an image from the iPhone camera, or the phones photo library. So if I change my code to use JPEGRepresentation, will that automatically specify the original image orientation in the imageData? – Pierce Mar 13 '16 at 18:20
  • Yeah, I think so. If using JPEGRepresentation, it will include its exif information in the imageData also. You are welcome :) – Allen Mar 13 '16 at 19:47
  • As an update: nearly 24 hours later, I have tried using the JPEG Representation approximately 20 times and so far so good! I appreciate the help, if anything changes I'll post an update. Thank you for the help! It's amazing to me that was all it took :) – Pierce Mar 14 '16 at 18:56

1 Answers1

1

This code works for me for png files. I got this from this SO question. It's posted way down the discussion so I'm reproducing it here.

extension UIImage {
    func fixOrientation() -> UIImage {
        if self.imageOrientation == UIImageOrientation.up {
            return self
        }
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        if let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            return normalizedImage
        } else {
            return self
        }
    }
}

Usage:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()
Community
  • 1
  • 1
ICL1901
  • 7,632
  • 14
  • 90
  • 138