views:

8320

answers:

2

I have a UIImage that is UIImageOrientationUp (portrait) that I would like to rotate counter-clockwise by 90 degrees (to landscape). I don't want to use a CGAffineTransform. I want the pixels of the UIImage to actually shift position. I am using a block of code (shown below) originally intended to resize a UIImage to do this. I set a target size as the current size of the UIImage but I get an error (Error): CGBitmapContextCreate: invalid data bytes/row: should be at least 1708 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedLast. (I don't get an error whenever I provide a SMALLER size as the target size BTW). Can any of you show me how to just ROTATE my UIImage 90 degrees CCW using just core graphics functions while preserving the current size?

-(UIImage*)reverseImageByScalingToSize:(CGSize)targetSize:(UIImage*)anImage
{
    UIImage* sourceImage = anImage; 
    CGFloat targetWidth = targetSize.height;
    CGFloat targetHeight = targetSize.width;

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
     bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
     bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {


     bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }       


    if (sourceImage.imageOrientation == UIImageOrientationRight) {
     CGContextRotateCTM (bitmap, radians(90));
     CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationLeft) {
     CGContextRotateCTM (bitmap, radians(-90));
     CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
     // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
     CGContextRotateCTM (bitmap, radians(90));
     CGContextTranslateCTM (bitmap, 0, -targetHeight);
    }

    CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}
+7  A: 

What about something like:

UIImage* rotate(UIImage* src, UIImageOrientation orientation)
{
    UIGraphicsBeginImageContext(src.size);

    CGContextRef context(UIGraphicsGetCurrentContext());

    if (orientation == UIImageOrientationRight) {
        CGContextRotateCTM (context, radians(90));
    } else if (orientation == UIImageOrientationLeft) {
        CGContextRotateCTM (context, radians(-90));
    } else if (orientation == UIImageOrientationDown) {
        // NOTHING
    } else if (orientation == UIImageOrientationUp) {
        CGContextRotateCTM (context, radians(90));
    }

    [src drawAtPoint:CGPointMake(0, 0)];

    return UIGraphicsGetImageFromCurrentImageContext();
}
fbrereto
Thanks. I tried it and nothing changed with the image though.. You said I might need to do some extra stuff, right? Could you elaborate?
RexOnRoids
My comment was that drawAtPoint may have to be called after the call to set the proper RotateCTM. Try moving drawAtPoint to just before UIGraphicsGetImageFromCurrentImageContext
fbrereto
how do i use this method on iphone
Rahul Vyas
radians shows error something like thisUndefined symbols: "_radians", referenced from:
Rahul Vyas
Radians is a function written by the original poster; it shouldn't be too hard to write on your own.
fbrereto
static inline double radians (double degrees) {return degrees * M_PI/180;}
Grouchal
This would not work on a background thread. UIGraphicsGetCurrentContext() is not thread-safe and should only be called on the main (UI) thread.
Chris R. Donnelly
A: 

http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/ has some code snippets to help deal with UIImages - the private helper method in UIImage+resize.m accepts a transform to allow rotation, so you'd just need to expose that as a public interface.

JosephH