कैसे एक UIImage 90 डिग्री घुमाएँ?


177

मेरे पास एक UIImageऐसा UIImageOrientationUpचित्र (चित्र) है जिसे मैं 90 डिग्री तक (परिदृश्य में) काउंटर-क्लॉकवाइज घुमाना चाहूंगा। मैं एक का उपयोग नहीं करना चाहता CGAffineTransform। मैं चाहता हूं कि पिक्सल्स UIImageवास्तव में पोजिशन शिफ्ट हों। मैं कोड के एक ब्लॉक का उपयोग कर रहा हूं (नीचे दिखाया गया है) मूल रूप UIImageसे ऐसा करने के लिए इसका उद्देश्य है। मैंने वर्तमान आकार के रूप में एक लक्ष्य आकार निर्धारित किया है UIImageलेकिन मुझे एक त्रुटि मिलती है:

(त्रुटि): CGBitmapContextCreate: अमान्य डेटा बाइट्स / पंक्ति: 8 पूर्णांक बिट्स / घटक, 3 घटकों, kCGImageAlphaPremultipliedLast के लिए कम से कम 1708 होना चाहिए।

(जब भी मैं लक्ष्य आकार BTW के रूप में एक छोटे आकार प्रदान करता हूं तो मुझे कोई त्रुटि नहीं मिलती है)। मैं UIImageवर्तमान आकार को संरक्षित करते हुए सिर्फ कोर ग्राफिक्स फ़ंक्शंस का उपयोग करके अपनी 90 डिग्री CCW कैसे प्राप्त कर सकता हूं ?

-(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; 
}

मुझे एक और उपयोगी लिंक मिला .. आशा है कि यह कुछ मदद करता है .. mobiledevelopertips.com/user-interface/…
दिलीप राजकुमार

समाधान .......... stackoverflow.com/questions/5427656/...
fattie

मेरा मुद्दा यह है कि अमेज़ॅन एस 3 पर अपलोड की जा रही तस्वीरें घुमाई गई थीं। इस समाधान ने नेत्रहीन और अपलोड पर समस्या को हल किया।
क्रिसिलिक

stackoverflow.com/questions/30701578/… हे नीलम इसे देखने के बाद मैं हटा
दूंगा

जवाबों:


89

क्या कुछ के बारे में की तरह:

static inline double radians (double degrees) {return degrees * M_PI/180;}
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)];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

1
मेरी टिप्पणी थी कि उचित RotateCTM सेट करने के लिए आह्वान के बाद drawAtPoint को कॉल करना पड़ सकता है। UIGraphicsGetImageFromCurrentImageContext
fbrereto

4
यह पृष्ठभूमि थ्रेड पर काम नहीं करेगा। UIGraphicsGetCurrentContext () थ्रेड-सुरक्षित नहीं है और केवल मुख्य (UI) थ्रेड पर कॉल किया जाना चाहिए।
क्रिस आर। डोनेली

1
CGContextRotateCTM () को अंतिम कॉल को संभवतः 180 से घूमना चाहिए, न कि 90 से। वास्तव में,… को संभवतः 180 से घुमाना चाहिए, और… शायद ऊपर नहीं घूमना चाहिए।
इवान वुज़िका

5
IOS 4 और बाद में, आप अपने ऐप के किसी भी धागे से UIGraphicsGetCurrentContext फ़ंक्शन को कॉल कर सकते हैं।
बेंटफोर्ड

3
CGContextTranslateCTM (ctx, चौड़ाई / 2, ऊंचाई / 2) से पहले और बाद में रिवर्स करने की आवश्यकता है।
ग्लेन मेनार्ड

411

मेरा मानना ​​है कि सबसे आसान तरीका (और धागा सुरक्षित भी है):

//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];

नोट: जैसा कि ब्रेनवेयर ने कहा कि यह केवल छवि के उन्मुखीकरण डेटा को संशोधित करता है - पिक्सेल डेटा अछूता है। कुछ अनुप्रयोगों के लिए, यह पर्याप्त नहीं हो सकता है।

या स्विफ्ट में:

guard
    let landscapeImage = UIImage(named: "imgname"),
    let landscapeCGImage = landscapeImage.cgImage
else { return }
let portraitImage = UIImage(cgImage: landscapeCGImage, scale: landscapeImage.scale, orientation: .right)

1
इसे और सामान्य बनाएं: UIImage * origImg = [UIImage imageNamed: @ "1.JPG"]; UIImage * फिक्स्ड = [UIImage imageWithCGImage: [OriginImg CGImage] स्केल: 1.0 ओरिएंटेशन: origImg.imageOrientation];
कलन SUN

13
यह वास्तव में छवि को घुमाता नहीं है। यह छवि की एक प्रति बनाता है और छवि की छवि के बिट्स सेट करता है। छवि की छवि की संपत्ति 0, 1, 2, या 3 के गुण हो जाती है। कुछ वर्ग इन झंडों को अनदेखा कर देते हैं जैसे कि UIActivityViewController। यदि आपको वास्तव में छवि को घुमाए जाने की आवश्यकता है, तो बेन ग्रोट का उत्तर देखें जिसमें हार्डी मैकिया का UIImage एक्सटेंशन है।
ब्रेनवेयर

पैमाने को 1.0 के रूप में रखना अगर आपके ऐप का उपयोग रेटिना और गैर-रेटिना दोनों स्क्रीन पर किया जाता है, तो आपको ओरिजिनल इमेज लेना होगा। इसे स्केल के रूप में पास करना होगा।
टेराडिल

2
जहाँ तक मैं बता सकता हूँ iOS10 में काम करना बंद कर दिया है।
नेलर

let img = UIImage(cgImage: myImage!.cgImage!, scale: UIScreen.main.scale, orientation: .right)
अलेक्जेंड्रे जी

110

कटिंग-स्केलिंग-एंड-रोटिंग-यूइमेज : हार्डी मैकिया का सरल और भयानक कोड देखें

बस कॉल करना

UIImage *rotatedImage = [originalImage imageRotatedByDegrees:90.0];

धन्यवाद हार्डी मैकिया!

हैडर:

  • (UIImage *) imageAtRect: (CGRect) रेक्ट;
  • (UIImage *) imageByScalingProportivelyToMinimumSize: (CGSize) targetSize;
  • (UIImage *) imageByScalingProporticallyToSize: (CGSize) targetSize;
  • (UIImage *) imageByScalingToSize: (CGSize) targetSize;
  • (UIImage *) imageRotatedByRadians: (CGFloat) रेडियन;
  • (UIImage *) imageRotatedByDegrees: (CGFloat) डिग्री;

चूंकि लिंक मर सकता है, यहाँ पूरा कोड है

//
//  UIImage-Extensions.h
//
//  Created by Hardy Macia on 7/1/09.
//  Copyright 2009 Catamount Software. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface UIImage (CS_Extensions)
- (UIImage *)imageAtRect:(CGRect)rect;
- (UIImage *)imageByScalingProportionallyToMinimumSize:(CGSize)targetSize;
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize;
- (UIImage *)imageByScalingToSize:(CGSize)targetSize;
- (UIImage *)imageRotatedByRadians:(CGFloat)radians;
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;

@end;

//
//  UIImage-Extensions.m
//
//  Created by Hardy Macia on 7/1/09.
//  Copyright 2009 Catamount Software. All rights reserved.
//

#import "UIImage-Extensions.h"

CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180/M_PI;};

@implementation UIImage (CS_Extensions)

-(UIImage *)imageAtRect:(CGRect)rect
{

   CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect);
   UIImage* subImage = [UIImage imageWithCGImage: imageRef];
   CGImageRelease(imageRef);

   return subImage;

}

- (UIImage *)imageByScalingProportionallyToMinimumSize:(CGSize)targetSize {

   UIImage *sourceImage = self;
   UIImage *newImage = nil;

   CGSize imageSize = sourceImage.size;
   CGFloat width = imageSize.width;
   CGFloat height = imageSize.height;

   CGFloat targetWidth = targetSize.width;
   CGFloat targetHeight = targetSize.height;

   CGFloat scaleFactor = 0.0;
   CGFloat scaledWidth = targetWidth;
   CGFloat scaledHeight = targetHeight;

   CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

   if (CGSizeEqualToSize(imageSize, targetSize) == NO) {

      CGFloat widthFactor = targetWidth / width;
      CGFloat heightFactor = targetHeight / height;

      if (widthFactor > heightFactor) 
         scaleFactor = widthFactor;
      else
         scaleFactor = heightFactor;

      scaledWidth  = width * scaleFactor;
      scaledHeight = height * scaleFactor;

      // center the image

      if (widthFactor > heightFactor) {
         thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
      } else if (widthFactor < heightFactor) {
         thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
      }
   }


   // this is actually the interesting part:

   UIGraphicsBeginImageContext(targetSize);

   CGRect thumbnailRect = CGRectZero;
   thumbnailRect.origin = thumbnailPoint;
   thumbnailRect.size.width  = scaledWidth;
   thumbnailRect.size.height = scaledHeight;

   [sourceImage drawInRect:thumbnailRect];

   newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   if(newImage == nil) NSLog(@"could not scale image");


   return newImage ;
}


- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize {

   UIImage *sourceImage = self;
   UIImage *newImage = nil;

   CGSize imageSize = sourceImage.size;
   CGFloat width = imageSize.width;
   CGFloat height = imageSize.height;

   CGFloat targetWidth = targetSize.width;
   CGFloat targetHeight = targetSize.height;

   CGFloat scaleFactor = 0.0;
   CGFloat scaledWidth = targetWidth;
   CGFloat scaledHeight = targetHeight;

   CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

   if (CGSizeEqualToSize(imageSize, targetSize) == NO) {

      CGFloat widthFactor = targetWidth / width;
      CGFloat heightFactor = targetHeight / height;

      if (widthFactor < heightFactor) 
         scaleFactor = widthFactor;
      else
         scaleFactor = heightFactor;

      scaledWidth  = width * scaleFactor;
      scaledHeight = height * scaleFactor;

      // center the image

      if (widthFactor < heightFactor) {
         thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
      } else if (widthFactor > heightFactor) {
         thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
      }
   }


   // this is actually the interesting part:

   UIGraphicsBeginImageContext(targetSize);

   CGRect thumbnailRect = CGRectZero;
   thumbnailRect.origin = thumbnailPoint;
   thumbnailRect.size.width  = scaledWidth;
   thumbnailRect.size.height = scaledHeight;

   [sourceImage drawInRect:thumbnailRect];

   newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   if(newImage == nil) NSLog(@"could not scale image");


   return newImage ;
}


- (UIImage *)imageByScalingToSize:(CGSize)targetSize {

   UIImage *sourceImage = self;
   UIImage *newImage = nil;

   //   CGSize imageSize = sourceImage.size;
   //   CGFloat width = imageSize.width;
   //   CGFloat height = imageSize.height;

   CGFloat targetWidth = targetSize.width;
   CGFloat targetHeight = targetSize.height;

   //   CGFloat scaleFactor = 0.0;
   CGFloat scaledWidth = targetWidth;
   CGFloat scaledHeight = targetHeight;

   CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

   // this is actually the interesting part:

   UIGraphicsBeginImageContext(targetSize);

   CGRect thumbnailRect = CGRectZero;
   thumbnailRect.origin = thumbnailPoint;
   thumbnailRect.size.width  = scaledWidth;
   thumbnailRect.size.height = scaledHeight;

   [sourceImage drawInRect:thumbnailRect];

   newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   if(newImage == nil) NSLog(@"could not scale image");


   return newImage ;
}


- (UIImage *)imageRotatedByRadians:(CGFloat)radians
{
   return [self imageRotatedByDegrees:RadiansToDegrees(radians)];
}

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

   // 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, DegreesToRadians(degrees));

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

   UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();
   return newImage;

}

@end;

... लिंक मर गया। पूर्ण कोड को शामिल करने के लिए +1
ग्रेग

31

जैसा कि यह अजीब लगता है, निम्नलिखित कोड ने मेरे लिए समस्या हल की:

+ (UIImage*)unrotateImage:(UIImage*)image {
    CGSize size = image.size;
    UIGraphicsBeginImageContext(size);
    [image drawInRect:CGRectMake(0,0,size.width ,size.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

8
यह काम करता है क्योंकि एक बार जब आप छवि बनाते हैं तो इमेज ओरिएंटेशन संरक्षित नहीं होता है।
मर्क्यूरियल सेप

हां, यह एक छवि से उपयोगी हटाने का अभिविन्यास होगा
शिहाब

समारोह नाम removeOrientationProperty किया जाना चाहिए था
शिहाब

29

एक धागा सुरक्षित रोटेशन फ़ंक्शन निम्नलिखित है (यह बहुत बेहतर काम करता है):

-(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;
}

आपके कोड के साथ एक समस्या है ... यह छवि के चारों ओर एक अजीब सफेद फ्रेम जोड़ता है UIImageOrientationDown
२०:०

1
आप नहीं चाहते हैं कि CGColorSpaceRelease (colorpace) पर कॉल करें, देखें stackoverflow.com/questions/5269815/…
सेठ स्पिट्जर

उस रिलीज़ के बारे में हाँ क्षमा करें
द ग्रेटस्टॉरर

18

मुझे उपरोक्त उत्तर के साथ परेशानी हुई, जिसमें स्वीकृत उत्तर भी शामिल है। मैंने हार्डी की श्रेणी को एक विधि में बदल दिया क्योंकि मैं चाहता था कि मैं एक छवि को घुमाऊं। यहाँ कोड और उपयोग है:

- (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;
}

और उपयोग:

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

धन्यवाद हार्डी!


16

90 डिग्री (घड़ी की दिशा / विरोधी घड़ी की दिशा) द्वारा छवि घुमाएँ

फंक्शन कॉल -

 UIImage *rotatedImage = [self rotateImage:originalImage clockwise:YES];

कार्यान्वयन:

- (UIImage*)rotateImage:(UIImage*)sourceImage clockwise:(BOOL)clockwise
  {
    CGSize size = sourceImage.size;
    UIGraphicsBeginImageContext(CGSizeMake(size.height, size.width));
    [[UIImage imageWithCGImage:[sourceImage CGImage]
                         scale:1.0
                   orientation:clockwise ? UIImageOrientationRight : UIImageOrientationLeft]
                   drawInRect:CGRectMake(0,0,size.height ,size.width)];

   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
  }

इससे छवि का आकार बढ़ता है
शशिकांत मोरे

5

यदि आप एक फोटो रोटेट बटन जोड़ना चाहते हैं जो 90 डिग्री वेतन वृद्धि में फोटो को घुमाता रहेगा, तो आप यहाँ जाएँ। ( finalImageएक UIImage है जो पहले से ही कहीं और बनाया गया है।)

- (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;
}

5

सरल। बस छवि अभिविन्यास ध्वज बदलें।

UIImage *oldImage = [UIImage imageNamed:@"whatever.jpg"];
UIImageOrientation newOrientation;
switch (oldImage.imageOrientation) {
    case UIImageOrientationUp:
        newOrientation = UIImageOrientationLandscapeLeft;
        break;
    case UIImageOrientationLandscapeLeft:
        newOrientation = UIImageOrientationDown;
        break;
    case UIImageOrientationDown:
        newOrientation = UIImageOrientationLandscapeRight;
        break;
    case UIImageOrientationLandscapeRight:
        newOrientation = UIImageOrientationUp;
        break;
    // you can also handle mirrored orientations similarly ...
}
UIImage *rotatedImage = [UIImage imageWithCGImage:oldImage.CGImage scale:1.0f orientation:newOrientation];

5

यहां UIImage के लिए एक स्विफ्ट एक्सटेंशन है जो किसी भी मनमाने कोण से छवि को घुमाता है। इसे इस तरह उपयोग करें let rotatedImage = image.rotated(byDegrees: degree):। मैंने अन्य उत्तरों में से एक में ऑब्जेक्टिव-सी कोड का उपयोग किया और कुछ पंक्तियों को हटा दिया, जिन्हें हमने गलत (घुमाया हुआ बॉक्स सामान) किया और इसे UIImage के लिए एक्सटेंशन में बदल दिया।

extension UIImage {

func rotate(byDegrees degree: Double) -> UIImage {
    let radians = CGFloat(degree*M_PI)/180.0 as CGFloat
    let rotatedSize = self.size
    let scale = UIScreen.mainScreen().scale
    UIGraphicsBeginImageContextWithOptions(rotatedSize, false, scale)
    let bitmap = UIGraphicsGetCurrentContext()
    CGContextTranslateCTM(bitmap, rotatedSize.width / 2, rotatedSize.height / 2);
    CGContextRotateCTM(bitmap, radians);
    CGContextScaleCTM(bitmap, 1.0, -1.0);
    CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2 , self.size.width, self.size.height), self.CGImage );
    let newImage = UIGraphicsGetImageFromCurrentImageContext()

    return newImage
}
}

बहुत अच्छा काम करता है! मैंने इसे थोड़ा बदल दिया ताकि मैं चौड़ाई और ऊँचाई को स्वैप कर सकूँ: func रोटेट (byDegrees डिग्री: Double, toSize: CGSize? = Nil) -> UIImage {let rotatedSize = toSize? self.size
एडविन

1
यह छवि को ठीक से सेट नहीं करता है। आप एक घुमाई गई छवि के साथ समाप्त होते हैं जो मूल सीमा से अधिक बहती है।
डेविन बी

इसके लिए बहुत - बहुत धन्यवाद। कमाल है कि मैंने आज इस पर कितना समय बिताया है।
क्रिस एचएच

5

स्विफ्ट 3 UIImage एक्सटेंशन:

func fixOrientation() -> UIImage {

    // No-op if the orientation is already correct
    if ( self.imageOrientation == .up ) {
        return self;
    }

    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    var transform: CGAffineTransform = .identity

    if ( self.imageOrientation == .down || self.imageOrientation == .downMirrored ) {
        transform = transform.translatedBy(x: self.size.width, y: self.size.height)
        transform = transform.rotated(by: .pi)
    }

    if ( self.imageOrientation == .left || self.imageOrientation == .leftMirrored ) {
        transform = transform.translatedBy(x: self.size.width, y: 0)
        transform = transform.rotated(by: .pi/2)
    }

    if ( self.imageOrientation == .right || self.imageOrientation == .rightMirrored ) {
        transform = transform.translatedBy(x: 0, y: self.size.height);
        transform = transform.rotated(by: -.pi/2);
    }

    if ( self.imageOrientation == .upMirrored || self.imageOrientation == .downMirrored ) {
        transform = transform.translatedBy(x: self.size.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)
    }

    if ( self.imageOrientation == .leftMirrored || self.imageOrientation == .rightMirrored ) {
        transform = transform.translatedBy(x: self.size.height, y: 0);
        transform = transform.scaledBy(x: -1, y: 1);
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    let ctx: CGContext = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height),
                                   bitsPerComponent: self.cgImage!.bitsPerComponent, bytesPerRow: 0,
                                   space: self.cgImage!.colorSpace!,
                                   bitmapInfo: self.cgImage!.bitmapInfo.rawValue)!;

    ctx.concatenate(transform)

    if ( self.imageOrientation == .left ||
        self.imageOrientation == .leftMirrored ||
        self.imageOrientation == .right ||
        self.imageOrientation == .rightMirrored ) {
        ctx.draw(self.cgImage!, in: CGRect(x: 0.0,y: 0.0,width: self.size.height,height: self.size.width))
    } else {
        ctx.draw(self.cgImage!, in: CGRect(x: 0.0,y: 0.0,width: self.size.width,height: self.size.height))
    }

    // And now we just create a new UIImage from the drawing context and return it
    return UIImage(cgImage: ctx.makeImage()!)
}

3

RawMean के उत्तर का स्विफ्ट 4.2 संस्करण :

extension UIImage {

func rotated(byDegrees degree: Double) -> UIImage {
    let radians = CGFloat(degree * .pi) / 180.0 as CGFloat
    let rotatedSize = self.size
    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(rotatedSize, false, scale)
    let bitmap = UIGraphicsGetCurrentContext()
    bitmap?.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)
    bitmap?.rotate(by: radians)
    bitmap?.scaleBy(x: 1.0, y: -1.0)
    bitmap?.draw(
        self.cgImage!,
        in: CGRect.init(x: -self.size.width / 2, y: -self.size.height / 2 , width: self.size.width, height: self.size.height))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext() // this is needed
    return newImage!
}

}

गुब्बारे एक छवि का वजन। Im मेरी परीक्षा: BEOTORE ROTATION ============================== चौड़ाई 3024.0 ऊँचाई 3024.0 आकार 4952213 बाइट्स ======= ========================================================================== ===== चौड़ाई 3024.0 ऊंचाई 3024.0 आकार 35191195 बाइट्स ================================
19

2

मैं इस कोड की कोशिश करता हूं, यह काम करता है, और 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;
}

2

हार्डी मैकिया कोड पर आधारित अन्य उत्तरों में मामूली बदलाव। UIViewघुमाए गए चित्र की सीमा आयत की गणना करने के लिए बस एक संपूर्ण ऑब्जेक्ट बनाने की आवश्यकता नहीं है । बस छवि आयत का उपयोग कर एक बारी बारी से परिवर्तन लागू करें CGRectApplyAffineTransform

static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;}
static CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180/M_PI;}


- (CGSize)rotatedImageSize:(CGFloat)degrees
{
    CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
    CGRect originalImageRect = CGRectMake(0, 0, self.size.width, self.size.height);
    CGRect rotatedImageRect = CGRectApplyAffineTransform(originalImageRect, t);
    CGSize rotatedSize = rotatedImageRect.size;

    return rotatedSize;
}

- (UIImage*)imageRotatedByDegrees:(CGFloat)degrees
{
    // calculate the size of the rotated view's containing box for our drawing space
    CGSize rotatedSize = [self rotatedImageSize:degrees];

    // 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, DegreesToRadians(degrees));

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

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}


0

मुझे इसका सरल लालित्य पसंद है Peter Sarnowski, लेकिन यह समस्याएँ पैदा कर सकता है जब आप EXIFमेटाडेटा और जैसे पर भरोसा नहीं कर सकते । उन स्थितियों में जहां आपको वास्तविक छवि डेटा को घुमाने की आवश्यकता होती है , मैं कुछ इस तरह की सिफारिश करूंगा:

- (UIImage *)rotateImage:(UIImage *) img
{
    CGSize imgSize = [img size];
    UIGraphicsBeginImageContext(imgSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextRotateCTM(context, M_PI_2);
    CGContextTranslateCTM(context, 0, -640);
    [img drawInRect:CGRectMake(0, 0, imgSize.height, imgSize.width)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

उपरोक्त कोड एक छवि लेता है जिसका अभिविन्यास है Landscape(यह याद नहीं है कि यह है Landscape Leftया नहीं Landscape Right) और इसे घुमाता है Portrait। यह एक उदाहरण है जिसे आपकी आवश्यकताओं के लिए संशोधित किया जा सकता है।

आपको जिन प्रमुख तर्कों के साथ खेलना होगा वे हैं CGContextRotateCTM(context, M_PI_2)जहां आप तय करते हैं कि आप कितना घूमना चाहते हैं, लेकिन फिर आपको यह सुनिश्चित करना होगा कि चित्र अभी भी स्क्रीन पर उपयोग कर रहा हैCGContextTranslateCTM(context, 0, -640) । यह अंतिम हिस्सा यह सुनिश्चित करने के लिए काफी महत्वपूर्ण है कि आप छवि को देखते हैं और रिक्त स्क्रीन को नहीं।

अधिक जानकारी के लिए स्रोत की जाँच करें ।


2
टूटी हुई कड़ी के लिए डाउनवोट और -640 मैजिक नंबर का कोई स्पष्टीकरण नहीं। तय होने पर उल्टा होगा।
नैट

0

resize-a-uiimage-a-right-way ने कुछ मुद्दों के बारे में बताया कि ऐसा करने के लिए कई कोड नमूने हैं, और UIImages से निपटने में मदद करने के लिए कुछ कोड स्निपेट्स हैं - UIImage + res.m.m में निजी सहायक विधि अनुमति देने के लिए एक परिवर्तन स्वीकार करती है रोटेशन, तो आपको बस उसे एक सार्वजनिक इंटरफ़ेस के रूप में उजागर करना होगा।

// Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size
// The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation
// If the new size is not integral, it will be rounded up
- (UIImage *)resizedImage:(CGSize)newSize
                transform:(CGAffineTransform)transform
           drawTransposed:(BOOL)transpose
     interpolationQuality:(CGInterpolationQuality)quality {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
    CGImageRef imageRef = self.CGImage;

    // Build a context that's the same dimensions as the new size
    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                                newRect.size.width,
                                                newRect.size.height,
                                                CGImageGetBitsPerComponent(imageRef),
                                                0,
                                                CGImageGetColorSpace(imageRef),
                                                CGImageGetBitmapInfo(imageRef));

    // Rotate and/or flip the image if required by its orientation
    CGContextConcatCTM(bitmap, transform);

    // Set the quality level to use when rescaling
    CGContextSetInterpolationQuality(bitmap, quality);

    // Draw into the context; this scales the image
    CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);

    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    // Clean up
    CGContextRelease(bitmap);
    CGImageRelease(newImageRef);

    return newImage;
}

यह उस फ़ाइल का लाइसेंस है:

// Created by Trevor Harmon on 8/5/09.
// Free for personal or commercial use, with or without modification.
// No warranty is expressed or implied.

0

एक बहुत ही कुशल UIImage श्रेणी है जिसका नाम NYXImagesKit है। यह vDSP, CoreImage और vImage का उपयोग जितनी जल्दी हो सके करने के लिए करता है। इसमें एक UIImage + घूर्णन श्रेणी है जिसने मेरा दिन बचाया :)

https://github.com/Nyx0uf/NYXImagesKit


0

स्विफ्ट के लिए: यहां UIImage के लिए एक सरल एक्सटेंशन दिया गया है:

//ImageRotation.swift

import UIKit

extension UIImage {  
    public func imageRotatedByDegrees(degrees: CGFloat, flip: Bool) -> UIImage {
        let radiansToDegrees: (CGFloat) -> CGFloat = {
            return $0 * (180.0 / CGFloat(M_PI))
        }
        let degreesToRadians: (CGFloat) -> CGFloat = {
            return $0 / 180.0 * CGFloat(M_PI)
        }

        // calculate the size of the rotated view's containing box for our drawing space
        let rotatedViewBox = UIView(frame: CGRect(origin: CGPointZero, size: size))
        let t = CGAffineTransformMakeRotation(degreesToRadians(degrees));
        rotatedViewBox.transform = t
        let rotatedSize = rotatedViewBox.frame.size

        // Create the bitmap context
        UIGraphicsBeginImageContext(rotatedSize)
        let 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.0, rotatedSize.height / 2.0);

        //   // Rotate the image context
        CGContextRotateCTM(bitmap, degreesToRadians(degrees));

        // Now, draw the rotated/scaled image into the context
        var yFlip: CGFloat

        if(flip){
            yFlip = CGFloat(-1.0)
        } else {
            yFlip = CGFloat(1.0)
        }

        CGContextScaleCTM(bitmap, yFlip, -1.0)
        CGContextDrawImage(bitmap, CGRectMake(-size.width / 2, -size.height / 2, size.width, size.height), CGImage)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }
}

( स्रोत )

इसके साथ प्रयोग करें:

rotatedPhoto = rotatedPhoto?.imageRotatedByDegrees(90, flip: false) 

पूर्व एक छवि को घुमाएगा और इसे फ्लिप करेगा यदि फ्लिप सही पर सेट है।


आप कृपया समझा सकते हैं कि थोड़ा?
G.Abhisek

2
यह किसी कारण के लिए पहलू अनुपात के साथ गड़बड़ लगता है
fwhenin
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.