5

I have an odd problem with captureStillImageAsynchronouslyFromConnection. If I save the image using jpegStillImageNSDataRepresentation while the video is mirrored, the image in the camera roll is rotated 90 degrees clockwise. However, if it's not mirrored, the orientation is fine. I'll post the code, anyone else have this problem/know of a fix?

Update: Just ran some tests, the heights and widths (640x480) are fine and reflect the device's orientation. When I Take a picture in portrait, it reports UIImageOrientationLeft and when mirrored, UIImageOrientationLeftMirrored.

Update 2: When I view the saved photo in the camera roll, the preview of the image has the right orientation, as does the image when you swipe between photos, but when the photo is fully loaded, it rotates 90 degrees. Could this be a camera roll problem? (I'm on 4.3.3)

- (void) captureImageAndSaveToCameraRoll
{
    AVCaptureConnection *stillImageConnection = [AVCamUtilities connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
    if ([stillImageConnection isVideoOrientationSupported])
        [stillImageConnection setVideoOrientation:[self orientation]];

    [[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:stillImageConnection
                                                         completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

                                                             ALAssetsLibraryWriteImageCompletionBlock completionBlock = ^(NSURL *assetURL, NSError *error) {
                                                                 if (error) {
                                                                     if ([[self delegate] respondsToSelector:@selector(captureManager:didFailWithError:)]) {
                                                                         [[self delegate] captureManager:self didFailWithError:error];
                                                                     }
                                                                 }
                                                             };

                                                             if (imageDataSampleBuffer != NULL) {
                                                                 NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
                                                                 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

                                                                 UIImage *image = [[UIImage alloc] initWithData:imageData];
                                                                 [library writeImageToSavedPhotosAlbum:[image CGImage]
                                                                                           orientation:(ALAssetOrientation)[image imageOrientation]
                                                                                       completionBlock:completionBlock];
                                                                 [image release];

                                                                 [library release];
                                                             }
                                                             else
                                                                 completionBlock(nil, error);

                                                             if ([[self delegate] respondsToSelector:@selector(captureManagerStillImageCaptured:)]) {
                                                                 [[self delegate] captureManagerStillImageCaptured:self];
                                                             }
                                                         }];
}
W Dyson
  • 4,604
  • 4
  • 40
  • 68
  • to debug this it might help if you output the image.size and imageOrientation in both modes, what values do you get? – mackross Jun 15 '11 at 01:58
  • Just ran some tests, the heights and widths (640x480) are fine and reflect the device's orientation. When I Take a picture in portrait, it reports UIImageOrientationLeft and when mirrored, UIImageOrientationLeftMirrored. – W Dyson Jun 15 '11 at 02:13

3 Answers3

2

I'm wondering if you the newly created image really has it's orientation set as you are assuming here:

[library writeImageToSavedPhotosAlbum:[image CGImage] orientation: (ALAssetOrientation) [image imageOrientation] completionBlock:completionBlock];

[image imageOrientation] in particular seems potentially the source of the problem, especially with the cast required...

you say you are seeing the image orientation somewhere, is it from [image imageOrientation] just after creating it with:

NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation: imageDataSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];

I'm wondering if you are assuming that this metadata is in the imageData returned from AVCaptureStillImageOutput jpegStillImageNSDataRepresentation: when that in fact only contains the image pixel data itself?

Dad
  • 6,388
  • 2
  • 28
  • 34
  • Note that it is [specifically documented](http://developer.apple.com/library/ios/documentation/AssetsLibrary/Reference/ALAssetsLibrary_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40009722-CH1-SW4) that the UIImageOrientation can be cast to ALAssetOrientation. – Anomie Jun 25 '11 at 18:26
  • ah, well, excellent! Is it getting the right value? As I said above, I'm wondering if the metadata is coming into the `imageData` and then is getting parsed and added to the `image`. Just trying to trace where the data starts and moves through the system since it doesn't seem to be getting where it needs to, if I understand your question. – Dad Jun 26 '11 at 23:07
0

According to some reports, the iPhone's photos application back in 2009 didn't support any of the mirrored orientations at all; it's certainly possible that they partially fixed this but still have bugs in some cases (I know, for example, that UIImageView doesn't handle contentStretch correctly in some cases). This should be easy enough to test: just load the sample images from that blog into the camera roll and see what happens.

Anomie
  • 92,546
  • 13
  • 126
  • 145
  • The code I'm using is a mix of AVCam 1.0 and 1.2 plus my own code. I guess this is the reason why you can't save a photo in AVCam 1.2? Stupid. Why do I have to save the photo as mirrored at all? All I want to do is save a photo of the mirrored video. – W Dyson Jun 19 '11 at 20:36
  • Is there a simple way to take a photo and flip it vertically before saving to the camera roll? – W Dyson Jun 19 '11 at 20:37
  • 1
    @WDyson: Sure, see http://stackoverflow.com/questions/5427656/ios-uiimagepickercontroller-result-image-orientation-after-upload/5427890#5427890 for a previous question along those exact lines. – Anomie Jun 20 '11 at 02:15
0

Create the category for UIImage described in iOS UIImagePickerController result image orientation after upload

Call this method on the image before saving it to your library.

Community
  • 1
  • 1
hundreth
  • 841
  • 4
  • 8
  • Curious thing. My images are now all rotated 180 degrees, upside down. – W Dyson Jun 20 '11 at 20:28
  • You will have to revise this to do what you want it to. Although the logic should be similar. – hundreth Jun 20 '11 at 20:48
  • 1
    I took the liberty of editing your answer to just link to my previous answer on image rotation, rather than copying it verbatim. -1 for the plagiarism, and for just copying your answer from the link I posted in a comment to my answer 14 hours earlier. – Anomie Jun 21 '11 at 18:48
  • I did not copy it from your answer, that code is all over the internet. I've used it in several of my projects. A bit egotistical to think your answer is the only possible place I could have come across it, no? – hundreth Jun 21 '11 at 20:05
  • 1
    Wow, people have copied my code all over the Internet? Nifty. – Anomie Jun 21 '11 at 23:29