Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 567
null0pointer Avatar asked May 11 '12 03:05

null0pointer


2 Answers

-(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.

like image 113
Dream.In.Code Avatar answered Oct 22 '22 18:10

Dream.In.Code


Rotate and Mirror UIImage CGImage Backing Data - Swift

I recently wanted to correct a UIImage backed by a CGImage to match the desired orientation rather than rely on APIs to respect the UIImageOrientation parameter.

func createMatchingBackingDataWithImage(imageRef: CGImage?, orienation: UIImageOrientation) -> CGImage?
{
    var orientedImage: CGImage?

    if let imageRef = imageRef {
        let originalWidth = imageRef.width
        let originalHeight = imageRef.height
        let bitsPerComponent = imageRef.bitsPerComponent
        let bytesPerRow = imageRef.bytesPerRow

        let bitmapInfo = imageRef.bitmapInfo

        guard let colorSpace = imageRef.colorSpace else {
            return nil
        }

        var degreesToRotate: Double
        var swapWidthHeight: Bool
        var mirrored: Bool
        switch orienation {
        case .up:
            degreesToRotate = 0.0
            swapWidthHeight = false
            mirrored = false
            break
        case .upMirrored:
            degreesToRotate = 0.0
            swapWidthHeight = false
            mirrored = true
            break
        case .right:
            degreesToRotate = 90.0
            swapWidthHeight = true
            mirrored = false
            break
        case .rightMirrored:
            degreesToRotate = 90.0
            swapWidthHeight = true
            mirrored = true
            break
        case .down:
            degreesToRotate = 180.0
            swapWidthHeight = false
            mirrored = false
            break
        case .downMirrored:
            degreesToRotate = 180.0
            swapWidthHeight = false
            mirrored = true
            break
        case .left:
            degreesToRotate = -90.0
            swapWidthHeight = true
            mirrored = false
            break
        case .leftMirrored:
            degreesToRotate = -90.0
            swapWidthHeight = true
            mirrored = true
            break
        }
        let radians = degreesToRotate * Double.pi / 180.0

        var width: Int
        var height: Int
        if swapWidthHeight {
            width = originalHeight
            height = originalWidth
        } else {
            width = originalWidth
            height = originalHeight
        }

        let contextRef = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
        contextRef?.translateBy(x: CGFloat(width) / 2.0, y: CGFloat(height) / 2.0)
        if mirrored {
            contextRef?.scaleBy(x: -1.0, y: 1.0)
        }
        contextRef?.rotate(by: CGFloat(radians))
        if swapWidthHeight {
            contextRef?.translateBy(x: -CGFloat(height) / 2.0, y: -CGFloat(width) / 2.0)
        } else {
            contextRef?.translateBy(x: -CGFloat(width) / 2.0, y: -CGFloat(height) / 2.0)
        }
        contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(originalWidth), height: CGFloat(originalHeight)))
        orientedImage = contextRef?.makeImage()
    }

    return orientedImage
}
like image 36
Cameron Lowell Palmer Avatar answered Oct 22 '22 20:10

Cameron Lowell Palmer