4

I use the following code to scale my UIImagePickerController.

    CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 71.0); //This slots the preview exactly in the middle of the screen by moving it down 71 points
    self.imagePicker.cameraViewTransform = translate;
    CGAffineTransform scale = CGAffineTransformScale(translate, 1.333333, 1.333333);
    self.imagePicker.cameraViewTransform = scale;

Then I take the picture and present it in a UIImageView

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    [picker dismissViewControllerAnimated:NO completion:NULL];

    _imageTaken = nil;
    _imageTaken = [info objectForKey:UIImagePickerControllerEditedImage];
    if(_imageTaken==nil)
    {
        _imageTaken = [info objectForKey:UIImagePickerControllerOriginalImage];
    }
    if(_imageTaken==nil)
    {
        _imageTaken = [info objectForKey:UIImagePickerControllerCropRect];
    }

    [_imageTakenView setContentMode:UIViewContentModeScaleAspectFill];

    if (_selfie) {
        UIImage * flippedImage = [UIImage imageWithCGImage:_imageTaken.CGImage scale:_imageTaken.scale orientation:UIImageOrientationLeftMirrored];
        _imageTaken = flippedImage;
    }

    _imageTakenView.image = _imageTaken;
}

Everything is good so far. Then I send the image up to my database by converting it to NSData

    _imageData = [[NSData alloc] init];
    _imageData = UIImageJPEGRepresentation(_image, .1);

When I load the data back from the server and present it in another UIImageView of the same size I do set the same aspect ratio:

    [_imageViewToShow setContentMode:UIViewContentModeScaleAspectFill];

but the image looks distored (squished horizontally). Any ideas as to why this might be?

Convert UIImage to NSData & Save

_imageData = UIImageJPEGRepresentation(_image, .1);
PFFile *imageFile = [PFFile fileWithName:@"image.png" data:_imageData];
newMessage[@"image"] = imageFile;

Problem:

When I redownload the data, the UIImage appears squished. When I look at the image on my database, it seems fine. Not sure why this is happening...

Before and After Images:

enter image description here

enter image description here

Apollo
  • 8,874
  • 32
  • 104
  • 192
  • Are you setting a transform on the image view? Title mentions it, but the example code only shows a transform on the image picker. – Austin May 20 '14 at 20:48
  • @Austin I'm setting the transform on the image picker. Sorry – Apollo May 21 '14 at 00:46
  • Is your server saving all of the JPEG's metadata properly? Sounds like the either the `imageOrientation` property wasn't stored, or the image height / width were swapped. – Austin May 21 '14 at 13:36
  • @Austin I think that's very possible now that I'm looking at the images on my server. How would I rotate them/why do you think the height / width were swapped? – Apollo May 21 '14 at 14:30
  • I wouldn't know specifically why they wouldn't be saved. I just know that `UIImageJPEGRepresentation()` stores rotation as metadata, rather than rotating the image data itself. – Austin May 21 '14 at 14:44
  • @Austin I think you must be right. I realized I neglected to include part of my image handling when my UIImagePicker returns. Would you mind taking a peek? – Apollo May 22 '14 at 05:34
  • You're loading the image with `[UIImage imageWithData:]`, right? – Austin May 22 '14 at 13:34
  • @Austin yes that's correct. then I set it with _imageView.image = myImage; – Apollo May 22 '14 at 21:02
  • Unfortunately, I can't see anything wrong in what you're doing. I'd have to think it was something on the server. – Austin May 22 '14 at 21:12
  • @Austin No problem. Thanks for taking a look. – Apollo May 22 '14 at 21:27
  • @Austin I've attached before and after images, as well as edited the question with information about how I save a retrieve the images to Parse.com – Apollo May 22 '14 at 21:36

1 Answers1

5

Try normalizing the image's orientation before uploading.This will allow the image to work properly even if the metadata is lost

Here is a category to do that:

UIImage+OrientationFix.h

@interface UIImage (OrientationFix)

- (UIImage*)imageByNormalizingOrientation;

@end

UIImage+OrientationFix.m

@implementation UIImage (OrientationFix)

- (UIImage*)imageByNormalizingOrientation {
    if (self.imageOrientation == UIImageOrientationUp)
        return self;

    CGSize size = self.size;
    UIGraphicsBeginImageContextWithOptions(size, NO, self.scale);
    [self drawInRect:(CGRect){{0, 0}, size}];
    UIImage* normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return normalizedImage;
}

@end

You will just have to call:

_imageTaken = [flippedImage normalizedImage];
Jack
  • 16,677
  • 8
  • 47
  • 51
  • Wow. That actually worked. Can you explain what's going on here? And obviously, thank you so much. – Apollo May 22 '14 at 21:47
  • 1
    Basically, images not only store the pixels, but also need to store information on the orientation. Your `UIImage`, as you created it, has `UIImageOrientationLeftMirrored`. `UIImageView` displays it properly using this information. However, when you convert to JPEG, they have their own way of storing the rotation information. You can see http://stackoverflow.com/questions/5125323/problem-setting-exif-data-for-an-image on more details. But this fix basically makes the orientation "UP" so that no one will have issues displaying it. – Jack May 22 '14 at 21:52
  • 1
    Awesome. Thanks Jack. I'll award you the bounty once it's allowed. – Apollo May 22 '14 at 21:58