How to Rotate a UIImage 90 degrees?

前端 未结 19 843
天涯浪人
天涯浪人 2020-11-22 08:45

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

相关标签:
19条回答
  • 2020-11-22 09:08

    A thread safe rotation function is the following (it works much better):

    -(UIImage*)imageByRotatingImage:(UIImage*)initImage fromImageOrientation:(UIImageOrientation)orientation
    {
    CGImageRef imgRef = initImage.CGImage;
    
    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = orientation;
    switch(orient) {
    
        case UIImageOrientationUp: //EXIF = 1
            return initImage;
            break;
    
        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;
    
        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
    
        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;
    
        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
    
        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
    
        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
    
        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
    
        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
    
    }
    // Create the bitmap context
    CGContextRef    context = NULL;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;
    
    // Declare the number of bytes per row. Each pixel in the bitmap in this
    // example is represented by 4 bytes; 8 bits each of red, green, blue, and
    // alpha.
    bitmapBytesPerRow   = (bounds.size.width * 4);
    bitmapByteCount     = (bitmapBytesPerRow * bounds.size.height);
    bitmapData = malloc( bitmapByteCount );
    if (bitmapData == NULL)
    {
        return nil;
    }
    
    // Create the bitmap context. We want pre-multiplied ARGB, 8-bits
    // per component. Regardless of what the source image format is
    // (CMYK, Grayscale, and so on) it will be converted over to the format
    // specified here by CGBitmapContextCreate.
    CGColorSpaceRef colorspace = CGImageGetColorSpace(imgRef);
    context = CGBitmapContextCreate (bitmapData,bounds.size.width,bounds.size.height,8,bitmapBytesPerRow,
                                     colorspace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
    
    if (context == NULL)
        // error creating context
        return nil;
    
    CGContextScaleCTM(context, -1.0, -1.0);
    CGContextTranslateCTM(context, -bounds.size.width, -bounds.size.height);
    
    CGContextConcatCTM(context, transform);
    
    // Draw the image to the bitmap context. Once we draw, the memory
    // allocated for the context for rendering will then contain the
    // raw image data in the specified color space.
    CGContextDrawImage(context, CGRectMake(0,0,width, height), imgRef);
    
    CGImageRef imgRef2 = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    free(bitmapData);
    UIImage * image = [UIImage imageWithCGImage:imgRef2 scale:initImage.scale orientation:UIImageOrientationUp];
    CGImageRelease(imgRef2);
    return image;
    }
    
    0 讨论(0)
  • 2020-11-22 09:11

    I believe the easiest way (and thread safe too) is to do:

    //assume that the image is loaded in landscape mode from disk
    UIImage * landscapeImage = [UIImage imageNamed:imgname];
    UIImage * portraitImage = [[UIImage alloc] initWithCGImage: landscapeImage.CGImage
                                                         scale: 1.0
                                                   orientation: UIImageOrientationRight];
    

    Note: As Brainware said this only modifies the orientation data of the image - the pixel data is untouched. For some applications, this may not be enough.

    Or in Swift:

    guard
        let landscapeImage = UIImage(named: "imgname"),
        let landscapeCGImage = landscapeImage.cgImage
    else { return }
    let portraitImage = UIImage(cgImage: landscapeCGImage, scale: landscapeImage.scale, orientation: .right)
    
    0 讨论(0)
  • 2020-11-22 09:15

    I try this code, it works, and took from http://www.catamount.com/blog/1015/uiimage-extensions-for-cutting-scaling-and-rotating-uiimages/

    + (UIImage *)rotateImage:(UIImage*)src byRadian:(CGFloat)radian
    {
        // calculate the size of the rotated view's containing box for our drawing space
        UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0, src.size.width, src.size.height)];
        CGAffineTransform t = CGAffineTransformMakeRotation(radian);
        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 so we will rotate and scale around the center.
        CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
    
        //   // Rotate the image context
        CGContextRotateCTM(bitmap, radian);
    
        // Now, draw the rotated/scaled image into the context
        CGContextScaleCTM(bitmap, 1.0, -1.0);
        CGContextDrawImage(bitmap, CGRectMake(-src.size.width / 2, -src.size.height / 2, src.size.width, src.size.height), [src CGImage]);
    
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
    }
    
    0 讨论(0)
  • 2020-11-22 09:15

    "tint uiimage grayscale" appears to be the appropriate Google-Fu for this one

    straight away I get:

    https://discussions.apple.com/message/8104516?messageID=8104516&#8104516

    https://discussions.apple.com/thread/2751445?start=0&tstart=0

    How would I tint an image programmatically on the iPhone?

    0 讨论(0)
  • 2020-11-22 09:16

    I had trouble with ll of the above, including the approved answer. I converted Hardy's category back into a method since all i wanted was to rotate an image. Here's the code and usage:

    - (UIImage *)imageRotatedByDegrees:(UIImage*)oldImage deg:(CGFloat)degrees{
    // calculate the size of the rotated view's containing box for our drawing space
    UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,oldImage.size.width, oldImage.size.height)];
    CGAffineTransform t = CGAffineTransformMakeRotation(degrees * M_PI / 180);
    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 so we will rotate and scale around the center.
    CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
    
    //   // Rotate the image context
    CGContextRotateCTM(bitmap, (degrees * M_PI / 180));
    
    // Now, draw the rotated/scaled image into the context
    CGContextScaleCTM(bitmap, 1.0, -1.0);
    CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]);
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
    }
    

    And the usage:

    UIImage *image2 = [self imageRotatedByDegrees:image deg:90];
    

    Thanks Hardy!

    0 讨论(0)
  • 2020-11-22 09:16

    If you want to add a photo rotate button that'll keep rotating the photo in 90 degree increments, here you go. (finalImage is a UIImage that's already been created elsewhere.)

    - (void)rotatePhoto {
        UIImage *rotatedImage;
    
        if (finalImage.imageOrientation == UIImageOrientationRight)
            rotatedImage = [[UIImage alloc] initWithCGImage: finalImage.CGImage
                                                  scale: 1.0
                                            orientation: UIImageOrientationDown];
        else if (finalImage.imageOrientation == UIImageOrientationDown)
            rotatedImage = [[UIImage alloc] initWithCGImage: finalImage.CGImage
                                                  scale: 1.0
                                            orientation: UIImageOrientationLeft];
        else if (finalImage.imageOrientation == UIImageOrientationLeft)
            rotatedImage = [[UIImage alloc] initWithCGImage: finalImage.CGImage
                                                  scale: 1.0
                                            orientation: UIImageOrientationUp];
        else
            rotatedImage = [[UIImage alloc] initWithCGImage: finalImage.CGImage
                                                         scale: 1.0
                                                   orientation: UIImageOrientationRight];
        finalImage = rotatedImage;
    }
    
    0 讨论(0)
提交回复
热议问题