Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cropping an Image in portrait on iOS 7 results in incorrect orientation

I've got the following function, previous to iOS 7 & XCode 5 it worked as expected. The function takes an image and a cropSize. The image is the one to be cropped to a specified size, which is defined by CGSize cropSize. The purpose of the function is to crop the image to a certain size and then return the cropped image.

    - (UIImage *) cropImage:(UIImage *)originalImage cropSize:(CGSize)cropSize
{


    //calculate scale factor to go between cropframe and original image
    float SF = originalImage.size.width / cropSize.width;

    //find the centre x,y coordinates of image
    float centreX = originalImage.size.width / 2;
    float centreY = originalImage.size.height / 2;

    //calculate crop parameters
    float cropX = centreX - ((cropSize.width / 2) * SF);
    float cropY = centreY - ((cropSize.height / 2) * SF);

    CGRect cropRect = CGRectMake(cropX, cropY, (cropSize.width *SF), (cropSize.height * SF));

    CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], cropRect);


    //keep orientation if landscape
    UIImage *newImage;

    if (originalImage.size.width > originalImage.size.height || originalImage.size.width == originalImage.size.height) {
        newImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:originalImage.imageOrientation];
    }
    else
    {
        newImage = [UIImage imageWithCGImage:imageRef];
    }

    CGImageRelease(imageRef);

    //Now want to scale down cropped image!
    //want to multiply frames by 2 to get retina resolution
    CGRect scaledImgRect = CGRectMake(0, 0, (cropSize.width * 2), (cropSize.height * 2));

    UIGraphicsBeginImageContextWithOptions(scaledImgRect.size, NO, [UIScreen mainScreen].scale);

    [newImage drawInRect:scaledImgRect];

    UIImage *scaledNewImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return scaledNewImage;

}

The problem is that it all works fine in with a UIImage that is passed in that is in landscape orientation, the image is cropped as expected, however if the image passed in was taken in portrait, then the resulting image (the cropped result in scaledNewImage) is rotated 90 degrees on its side, which I don't want.

It is as if the portrait image is being worked on as if it's in landscape - and so the function cropped what should be a portrait orientated image in landscape instead of portrait.
This isn't so apparent if the crop area is square, however if the area to be cropped is a landscape rectangle then it's cropping it along the length of the portrait rather than the width. Hope I'm making sense!

This issue didn't occur prior to iOS 7 & XCode 5.. so I'm not sure exactly what's changed. Any help appreciated, thanks.

like image 895
SMSidat Avatar asked Dec 04 '22 09:12

SMSidat


1 Answers

Solved this issue with the help of an answer here: https://stackoverflow.com/a/14712184/521653

- (UIImage *) cropImage:(UIImage *)originalImage cropSize:(CGSize)cropSize
{
    NSLog(@"original image orientation:%d",originalImage.imageOrientation);

    //calculate scale factor to go between cropframe and original image
    float SF = originalImage.size.width / cropSize.width;

    //find the centre x,y coordinates of image
    float centreX = originalImage.size.width / 2;
    float centreY = originalImage.size.height / 2;

    //calculate crop parameters
    float cropX = centreX - ((cropSize.width / 2) * SF);
    float cropY = centreY - ((cropSize.height / 2) * SF);

    CGRect cropRect = CGRectMake(cropX, cropY, (cropSize.width *SF), (cropSize.height * SF));

    CGAffineTransform rectTransform;
    switch (originalImage.imageOrientation)
    {
        case UIImageOrientationLeft:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(M_PI_2), 0, -originalImage.size.height);
            break;
        case UIImageOrientationRight:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(-M_PI_2), -originalImage.size.width, 0);
            break;
        case UIImageOrientationDown:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(-M_PI), -originalImage.size.width, -originalImage.size.height);
            break;
        default:
            rectTransform = CGAffineTransformIdentity;
    };
    rectTransform = CGAffineTransformScale(rectTransform, originalImage.scale, originalImage.scale);

    CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], CGRectApplyAffineTransform(cropRect, rectTransform));
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:originalImage.scale orientation:originalImage.imageOrientation];
    CGImageRelease(imageRef);
    //return result;

    //Now want to scale down cropped image!
    //want to multiply frames by 2 to get retina resolution
    CGRect scaledImgRect = CGRectMake(0, 0, (cropSize.width * 2), (cropSize.height * 2));

    UIGraphicsBeginImageContextWithOptions(scaledImgRect.size, NO, [UIScreen mainScreen].scale);

    [result drawInRect:scaledImgRect];

    UIImage *scaledNewImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return scaledNewImage;

}

That's the updated method there. I implemented the code from the answer linked into my method and it solves the issues. Strange that I didn't have these before iOS 7!

like image 120
SMSidat Avatar answered Mar 15 '23 22:03

SMSidat