使用CGContextDrawImage旋转图像

我怎样才能旋转CGContextDrawImage()在其中心绘制的图像?

drawRect:

  CGContextSaveGState(c); rect = CGRectOffset(rect, -rect.size.width / 2, -rect.size.height / 2); CGContextRotateCTM(c, angle); CGContextDrawImage(c, rect, doodad.CGImage); CGContextRotateCTM(c, -angle); CGContextTranslateCTM(c, pt.x, pt.y); prevRect = rect; CGContextRestoreGState(c); 

我在原点绘制图像,并在其中心旋转,然后转换到应绘制的位置。 不工作。

要记住关于坐标转换的事情 – 好的,要记住的事情之一是,你不是操纵对象,就像在graphics编辑器中的转换命令; 你正在操纵空间本身

想象一下,这个装置是通过一个鹅颈臂悬挂在桌子上的,并被固定在位置上。 坐标变换将桌子放在一边(翻译),并以一种或另一种方式(旋转),甚至挤压和拉伸(缩放)。

另一个要记住的坐标转换的事情是转换总是相对于原点。 想象一下,你的办公桌开始时的一个angular落(对应于你的视angular)直接位于你的视angular在屏幕上的angular落。 翻译移动桌子的angular落,桌子的其他部分,在屏幕下方以某种方式滑动。 转动转动桌子在那个angular落附近。

还有一件事:转型影响未来,而不是过去。 绘制一些东西,然后尝试转换它是行不通的,因为你不会改变你绘制的东西,你转换你要绘制的空间。 所以,我们需要移动桌子,然后才能将图像放在正确的位置。

(我提到了最后一部分,因为你有一些转换命令可以立即被你的CGContextRestoreGState调用所恢复,因为它们之间没有任何影响。

所以,让我们从图像的未旋转的矩形开始。

 CGRect imageRect = { pointWhereYouWantTheImageCentered, doodad.size }; 

现在, CGContextDrawImage需要一个矩形,但是,如你所知,它将从该矩形的左下angular绘制图像,而不是中心。 (因此整个练习。)

所以,这是你要做的。 最后,你要画出的图像不是在上面所示的那个点上,而是在零点 – 也就是在桌子的angular落。 (不是以angular落为中心,而是桌子angular落的图像angular落。)

这将如何工作? 这需要一些设置。 你将不得不移动你的桌子。

首先,您需要将桌子向上移动,直到桌子的原点位于所需的中心点:

 CGContextTranslateCTM(context, imageRect.origin.x, imageRect.origin.y); 

然后你做旋转(围绕原点angular落转动桌子):

 CGContextRotateCTM(context, angleInRadians); 

然后,将桌面向下移动,然后左右放置图像宽度和高度的一半:

 CGContextTranslateCTM(context, imageRect.size.width * -0.5, imageRect.size.height * -0.5); 

然后,最后,将图像放在桌子的angular落。

 CGContextDrawImage(context, (CGRect){ CGPointZero, imageRect.size }, [doodad CGImage]); 

在桌子移动的情况下,矩形的中心位于屏幕上您想要图像居中的位置,因此图像居中。

此function可以以弧度旋转angular度在现有图像上绘制图像。

Swift 3:

 extension UIImage { func putImage(image: UIImage, on rect: CGRect, angle: CGFloat = 0.0) -> UIImage{ let drawRect = CGRect(x: 0, y: 0, width: size.width, height: size.height) UIGraphicsBeginImageContextWithOptions(drawRect.size, false, 1.0) // Start drawing self self.draw(in: drawRect) // Drawing new image on top let context = UIGraphicsGetCurrentContext()! // Get the center of new image let center = CGPoint(x: rect.midX, y: rect.midY) // Set center of image as context action point, so rotation works right context.translateBy(x: center.x, y: center.y) context.saveGState() // Rotate the context context.rotate(by: angle) // Context origin is image's center. So should draw image on point on origin image.draw(in: CGRect(origin: CGPoint(x: -rect.size.width/2, y: -rect.size.height/2), size: rect.size), blendMode: .normal, alpha: 1.0) // Go back to context original state. context.restoreGState() // Get new image let newImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return newImage } } 

如果您需要创build并清空大小和颜色的图像,请使用:

 extension UIImage { convenience init?(size: CGSize, color: UIColor) { let rect = CGRect(origin: .zero, size: size) UIGraphicsBeginImageContextWithOptions(rect.size, true, 1.0) color.setFill() UIRectFill(rect) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() guard let cgImage = image?.cgImage else { return nil } self.init(cgImage: cgImage) } } 

您可以使用以下方法旋转图像。

 -(UIImage*)rotateImage:(UIImage*)img forAngle:(CGFloat)radian { UIView *rotatedViewBox = [[UIView alloc]initWithFrame:CGRectMake(0, 0, img.size.width, img.size.height)]; CGAffineTransform t = CGAffineTransformMakeRotation(radian); rotatedViewBox.transform = t; CGSize rotatedSize = rotatedViewBox.frame.size; UIGraphicsBeginImageContext(rotatedSize); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, rotatedSize.width, rotatedSize.height); CGContextRotateCTM(context, radian); CGContextScaleCTM(context, 1.0, -1.0); CGContextDrawImage(context, CGRectMake(-img.size.width, -img.size.height, img.size.width, img.size.height), img.CGImage); UIImage *returnImg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return returnImg; } 

如果你使用angular度,那么这里是将度数转换为弧度的macros

 #define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI) 

如果您最终绘制到屏幕上(而不是生成保存到文件的图像),则可以考虑不使用CGContext,而是将图像放入CALayer中,然后围绕其锚点旋转图层:

 [layer setValue:@(rotationInRadians) forKeyPath:@"transform.rotation.z"]; 

如果图像是自己生成的(而不是来自你的包的静态资源或用户提供的东西),你可以考虑把它放在图层之外,并设置它们的父/公共祖先层的sublayerTransform

 [layerContainingTheConstituentLayers setValue:@(rotationInRadians) forKeyPath:@"sublayerTransform.rotation.z"]; 

(有可能是用视图而不是图层来做到这一点,我是一个苹果电脑的家伙,所以我不知道UIView是非常深的。)