J'ai un UIImage
qui est UIImageOrientationUp
(portrait) que je voudrais faire pivoter dans le sens inverse des aiguilles d'une montre de 90 degrés (en paysage). Je ne veux pas utiliser de fichier CGAffineTransform
. Je veux que les pixels de la UIImage
position décalent réellement. J'utilise un bloc de code (illustré ci-dessous) destiné à l'origine à redimensionner un UIImage
pour ce faire. J'ai défini une taille cible comme taille actuelle du UIImage
mais j'obtiens une erreur:
(Erreur): CGBitmapContextCreate: octets / ligne de données non valides: doit être au moins 1708 pour 8 bits entiers / composant, 3 composants, kCGImageAlphaPremultipliedLast.
(Je n'obtiens pas d'erreur chaque fois que je fournis une taille PLUS PETITE que la taille cible BTW). Comment puis-je faire pivoter mon UIImage
90 degrés CCW en utilisant uniquement les fonctions graphiques de base tout en préservant la taille actuelle?
-(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;
}
la source
Réponses:
Et quelque chose comme:
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; }
la source
Je pense que le moyen le plus simple (et aussi sûr pour les threads) est de faire:
//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];
Remarque: comme Brainware l'a dit, cela ne modifie que les données d'orientation de l'image - les données de pixels ne sont pas modifiées. Pour certaines applications, cela peut ne pas être suffisant.
Ou dans Swift:
guard let landscapeImage = UIImage(named: "imgname"), let landscapeCGImage = landscapeImage.cgImage else { return } let portraitImage = UIImage(cgImage: landscapeCGImage, scale: landscapeImage.scale, orientation: .right)
la source
let img = UIImage(cgImage: myImage!.cgImage!, scale: UIScreen.main.scale, orientation: .right)
Découvrez le code simple et génial de Hardy Macia sur: Cutting-scaling-and-rotation-uiimages
Il suffit d'appeler
UIImage *rotatedImage = [originalImage imageRotatedByDegrees:90.0];
Merci Hardy Macia!
Entête:
Puisque le lien peut mourir, voici le code complet
// // 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;
la source
Aussi étrange que cela puisse paraître, le code suivant a résolu le problème pour moi:
+ (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; }
la source
Une fonction de rotation thread-safe est la suivante (elle fonctionne beaucoup mieux):
-(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; }
la source
UIImageOrientationDown
.J'ai eu des problèmes avec ll de ce qui précède, y compris la réponse approuvée. J'ai reconverti la catégorie de Hardy en une méthode car tout ce que je voulais était de faire pivoter une image. Voici le code et l'utilisation:
- (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; }
Et l'utilisation:
UIImage *image2 = [self imageRotatedByDegrees:image deg:90];
Merci Hardy!
la source
Faire pivoter l'image de 90 degrés (sens horaire / anti-horaire)
Appel de fonction -
UIImage *rotatedImage = [self rotateImage:originalImage clockwise:YES];
La mise en oeuvre:
- (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; }
la source
Voici une extension Swift de UIImage qui fait pivoter l'image selon n'importe quel angle arbitraire. Utilisez comme ceci:
let rotatedImage = image.rotated(byDegrees: degree)
. J'ai utilisé le code Objective-C dans l'une des autres réponses et supprimé quelques lignes que nous avons incorrectes (trucs de boîte tournés) et les ai transformées en une extension pour 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 } }
la source
Si vous souhaitez ajouter un bouton de rotation de la photo qui continuera à faire pivoter la photo par incréments de 90 degrés, c'est parti. (
finalImage
est une UIImage qui a déjà été créée ailleurs.)- (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; }
la source
Facile. Changez simplement le drapeau d'orientation de l'image.
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];
la source
Extension de Swift 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()!) }
la source
Version Swift 4.2 de la réponse de RawMean :
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! } }
la source
J'essaie ce code, cela fonctionne, et j'ai pris de 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; }
la source
Modification mineure des autres réponses basées sur le code de Hardy Macia. Il n'est pas nécessaire de créer un
UIView
objet entier simplement pour calculer le rectangle englobant de l'image pivotée. Appliquez simplement une transformation de rotation au rectangle de l'image à l'aide deCGRectApplyAffineTransform
.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; }
la source
"tint uiimage grayscale" semble être le Google-Fu approprié pour celui-ci
tout de suite je reçois:
https://discussions.apple.com/message/8104516?messageID=8104516ꩄ
https://discussions.apple.com/thread/2751445?start=0&tstart=0
Comment teinter une image par programmation sur l'iPhone?
la source
J'aime l'élégance simple de
Peter Sarnowski
la réponse de ', mais cela peut poser des problèmes lorsque vous ne pouvez pas vous fier auxEXIF
métadonnées et autres. Dans les situations où vous devez faire pivoter les données d'image réelles, je recommanderais quelque chose comme ceci:- (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; }
Le code ci-dessus prend une image dont l'orientation est
Landscape
(je ne me souviens pas si c'estLandscape Left
ouLandscape Right
) et la fait pivoter enPortrait
. C'est un exemple qui peut être modifié selon vos besoins.Les arguments clés avec
CGContextRotateCTM(context, M_PI_2)
lesquels vous auriez à jouer sont ceux où vous décidez de combien vous voulez faire pivoter, mais vous devez ensuite vous assurer que l'image dessine toujours à l'écran en utilisantCGContextTranslateCTM(context, 0, -640)
. Cette dernière partie est assez importante pour vous assurer de voir l'image et non un écran vide.Pour plus d'informations, consultez la source .
la source
resize-a-uiimage-the-right-way explique certains des problèmes rencontrés par de nombreux exemples de code pour ce faire, et contient des extraits de code pour aider à gérer UIImages - la méthode d'assistance privée dans UIImage + resize.m accepte une transformation pour permettre rotation, il vous suffit donc de l'exposer en tant qu'interface publique.
// 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; }
Voici la licence de ce fichier:
// Created by Trevor Harmon on 8/5/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied.
la source
Il existe une catégorie UIImage extrêmement efficace nommée NYXImagesKit. Il utilise vDSP, CoreImage et vImage pour être aussi rapide que possible. Il a une catégorie UIImage + Rotation qui m'a sauvé la journée :)
https://github.com/Nyx0uf/NYXImagesKit
la source
Pour Swift: Voici une simple extension de 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 } }
( Source )
Utilisez-le avec:
rotatedPhoto = rotatedPhoto?.imageRotatedByDegrees(90, flip: false)
Le premier fera pivoter une image et la retournera si flip est réglé sur true.
la source