objective-ciosuiimagecgimage

Rotating a CGImage


I have a UIImage that I'm getting from a UIImagePickerController. When I receive the image from the - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info method I put it straight into a UIImageView for preview and give the user the option to either save or discard the image.

The preview screen

When the user selects the save option the application get the png data for the image and saves it to it's documents directory. But what happens under one of the 2 possible device orientations (landscape only) is that the image is saved upside down (more specifically, rotated 180 degrees from what it should be). So when I load the image in the gallery it appears upside down.

(See the bottom left image in the gallery)

See the bottom left image

I have worked this out to be that the raw image data in the UIImage from the UIImagePickerController is not rotated, rather, the orientation is stored as a property on the object and only applied when displaying. So I'm trying to rotate the CGImage associated with the UIImage using some code I found online. But it appears to have absolutely no affect on the image. The code I'm using follows:

- (void)rotateImage:(UIImage*)image byRadians:(CGFloat)rads
{   
    // calculate the size of the rotated view's containing box for our drawing space 
    UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,image.size.width, image.size.height)];
    CGAffineTransform t = CGAffineTransformMakeRotation(rads);
    rotatedViewBox.transform = t;
    CGSize rotatedSize = rotatedViewBox.frame.size;

    // Create the bitmap context
    UIGraphicsBeginImageContext(rotatedSize);
    CGContextRef bitmap = UIGraphicsGetCurrentContext();

    // Move the origin to the middle of the image you want to rotate and scale around the center. 
    CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2); 

    // Rotate the image context
    CGContextRotateCTM(bitmap, rads);

    // Now, draw the rotated/scaled image into the context
    CGContextScaleCTM(bitmap, 1.0, -1.0);
    CGContextDrawImage(bitmap, CGRectMake(image.size.width / 2, image.size.height / 2, image.size.width, image.size.height), [image CGImage]);

    image = UIGraphicsGetImageFromCurrentImageContext();
    image = [UIImage imageWithCGImage:image.CGImage scale:1.0 orientation:UIImageOrientationDown];
    UIGraphicsEndImageContext();
}

I would like to know why this code isn't working, since every piece of code I find online to do this image rotation appears to not work.


Solution

  • -(UIImage*) rotate:(UIImage*) src andOrientation:(UIImageOrientation)orientation
    {
        UIGraphicsBeginImageContext(src.size);
    
        CGContextRef context=(UIGraphicsGetCurrentContext());
    
        if (orientation == UIImageOrientationRight) {
            CGContextRotateCTM (context, 90/180*M_PI) ;
        } else if (orientation == UIImageOrientationLeft) {
            CGContextRotateCTM (context, -90/180*M_PI);
        } else if (orientation == UIImageOrientationDown) {
            // NOTHING
        } else if (orientation == UIImageOrientationUp) {
            CGContextRotateCTM (context, 90/180*M_PI);
        }
    
        [src drawAtPoint:CGPointMake(0, 0)];
        UIImage *img=UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return img;
    
    }
    

    use this one .. it works perfect ! Just make sure you use this function when you are picking images from UIImagePicker:

    example:

    UIImage *image;
    image = [self rotate:image andOrientation:image.imageOrientation];
    

    Make sure to use this function in place where you pick photos from documents directory.