旋转一个CGImage

我有一个从UIImagePickerController获得的UIImage。 当我从- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info方法接收图像时,我将其直接放入UIImageView中进行预览,并为用户提供保存或放弃图像的选项。

预览屏幕

当用户select保存选项时,应用程序获取图像的png数据并将其保存到文档目录中。 但是,在两种可能的设备方向之一(仅风景)下发生的情况是,图像被倒置(更具体地说,应该是旋转180度)。 所以当我在图库中加载图像时,它会颠倒。

(请参阅图库中的左下图)

看左下图

我已经这样做了,从UIImagePickerController的UIImage中的原始图像数据不旋转,相反,方向​​存储为对象的属性,只适用于显示时。 所以我试图旋转使用我在网上find的一些代码与UIImage相关联的CGImage。 但它似乎完全没有影响的形象。 我使用的代码如下:

 - (void)rotateImage:(UIImage*)image byRadians:(CGFloat)rads { // calculate the size of the rotated view's containing box for our drawing space UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,image.size.width, image.size.height)]; CGAffineTransform t = CGAffineTransformMakeRotation(rads); 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 you want to rotate and scale around the center. CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2); // Rotate the image context CGContextRotateCTM(bitmap, rads); // Now, draw the rotated/scaled image into the context CGContextScaleCTM(bitmap, 1.0, -1.0); CGContextDrawImage(bitmap, CGRectMake(image.size.width / 2, image.size.height / 2, image.size.width, image.size.height), [image CGImage]); image = UIGraphicsGetImageFromCurrentImageContext(); image = [UIImage imageWithCGImage:image.CGImage scale:1.0 orientation:UIImageOrientationDown]; UIGraphicsEndImageContext(); } 

我想知道为什么这个代码不工作,因为我在网上find的每一段代码做这个图像旋转似乎不起作用。

 -(UIImage*) rotate:(UIImage*) src andOrientation:(UIImageOrientation)orientation { UIGraphicsBeginImageContext(src.size); CGContextRef context=(UIGraphicsGetCurrentContext()); if (orientation == UIImageOrientationRight) { CGContextRotateCTM (context, 90/180*M_PI) ; } else if (orientation == UIImageOrientationLeft) { CGContextRotateCTM (context, -90/180*M_PI); } else if (orientation == UIImageOrientationDown) { // NOTHING } else if (orientation == UIImageOrientationUp) { CGContextRotateCTM (context, 90/180*M_PI); } [src drawAtPoint:CGPointMake(0, 0)]; UIImage *img=UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return img; } 

使用这个..它工作完美! 只要确保在从UIImagePicker中选取图像时使用此function:

例:

 UIImage *image; image = [self rotate:image andOrientation:image.imageOrientation]; 

确保在从文档目录中选取照片的地方使用此function。

旋转和镜像UIImage CGImage备份数据 – Swift

我最近想纠正由CGImage支持的UIImage以匹配所需的方向,而不是依靠API来尊重UIImageOrientation参数。

 func createMatchingBackingDataWithImage(imageRef: CGImage?, orienation: UIImageOrientation) -> CGImage? { var orientedImage: CGImage? if let imageRef = imageRef { let originalWidth = imageRef.width let originalHeight = imageRef.height let bitsPerComponent = imageRef.bitsPerComponent let bytesPerRow = imageRef.bytesPerRow let bitmapInfo = imageRef.bitmapInfo guard let colorSpace = imageRef.colorSpace else { return nil } var degreesToRotate: Double var swapWidthHeight: Bool var mirrored: Bool switch orienation { case .up: degreesToRotate = 0.0 swapWidthHeight = false mirrored = false break case .upMirrored: degreesToRotate = 0.0 swapWidthHeight = false mirrored = true break case .right: degreesToRotate = 90.0 swapWidthHeight = true mirrored = false break case .rightMirrored: degreesToRotate = 90.0 swapWidthHeight = true mirrored = true break case .down: degreesToRotate = 180.0 swapWidthHeight = false mirrored = false break case .downMirrored: degreesToRotate = 180.0 swapWidthHeight = false mirrored = true break case .left: degreesToRotate = -90.0 swapWidthHeight = true mirrored = false break case .leftMirrored: degreesToRotate = -90.0 swapWidthHeight = true mirrored = true break } let radians = degreesToRotate * Double.pi / 180.0 var width: Int var height: Int if swapWidthHeight { width = originalHeight height = originalWidth } else { width = originalWidth height = originalHeight } let contextRef = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) contextRef?.translateBy(x: CGFloat(width) / 2.0, y: CGFloat(height) / 2.0) if mirrored { contextRef?.scaleBy(x: -1.0, y: 1.0) } contextRef?.rotate(by: CGFloat(radians)) if swapWidthHeight { contextRef?.translateBy(x: -CGFloat(height) / 2.0, y: -CGFloat(width) / 2.0) } else { contextRef?.translateBy(x: -CGFloat(width) / 2.0, y: -CGFloat(height) / 2.0) } contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(originalWidth), height: CGFloat(originalHeight))) orientedImage = contextRef?.makeImage() } return orientedImage } 

我得到了你的问题。你必须使用CGContextTranslateCTM(context, -rotatedSize.width/2, -rotatedSize.height/2); 以及在绘制旋转ViewBox.frame.origin.x,rotateViewBox.frame.origin.y中设置矩形的原点。 使用这个代码。

 UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,image.size.width, image.size.height)]; CGAffineTransform t = CGAffineTransformMakeRotation(0.3); rotatedViewBox.transform = t; CGSize rotatedSize = rotatedViewBox.frame.size; UIGraphicsBeginImageContext(rotatedSize); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, rotatedSize.width/2, rotatedSize.height/2); CGContextRotateCTM (context, 0.3); CGContextScaleCTM(context, 1, -1); CGContextTranslateCTM(context, -rotatedSize.width/2, -rotatedSize.height/2); CGContextDrawImage(context, CGRectMake(-rotatedViewBox.frame.origin.x, -rotatedViewBox.frame.origin.y, image.size.width, image.size.height), [image CGImage]); UIImage *nn = UIGraphicsGetImageFromCurrentImageContext(); NSLog(@"size is %f, %f",nn.size.width,nn.size.height); UIGraphicsEndImageContext(); UIImageWriteToSavedPhotosAlbum(nn, nil,nil,nil); 

Swift 3版本的Cameron Lowell Palmer回答 :

 func createMatchingBackingDataWithImage(imageRef: CGImage?, orienation: UIImageOrientation) -> CGImage? { var orientedImage: CGImage? if let imageRef = imageRef { let originalWidth = imageRef.width let originalHeight = imageRef.height let bitsPerComponent = imageRef.bitsPerComponent let bytesPerRow = imageRef.bytesPerRow let colorSpace = imageRef.colorSpace let bitmapInfo = imageRef.bitmapInfo var degreesToRotate: Double var swapWidthHeight: Bool var mirrored: Bool switch orienation { case .up: degreesToRotate = 0.0 swapWidthHeight = false mirrored = false break case .upMirrored: degreesToRotate = 0.0 swapWidthHeight = false mirrored = true break case .right: degreesToRotate = 90.0 swapWidthHeight = true mirrored = false break case .rightMirrored: degreesToRotate = 90.0 swapWidthHeight = true mirrored = true break case .down: degreesToRotate = 180.0 swapWidthHeight = false mirrored = false break case .downMirrored: degreesToRotate = 180.0 swapWidthHeight = false mirrored = true break case .left: degreesToRotate = -90.0 swapWidthHeight = true mirrored = false break case .leftMirrored: degreesToRotate = -90.0 swapWidthHeight = true mirrored = true break } let radians = degreesToRotate * Double.pi / 180 var width: Int var height: Int if swapWidthHeight { width = originalHeight height = originalWidth } else { width = originalWidth height = originalHeight } if let contextRef = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace!, bitmapInfo: bitmapInfo.rawValue) { contextRef.translateBy(x: CGFloat(width) / 2.0, y: CGFloat(height) / 2.0) if mirrored { contextRef.scaleBy(x: -1.0, y: 1.0) } contextRef.rotate(by: CGFloat(radians)) if swapWidthHeight { contextRef.translateBy(x: -CGFloat(height) / 2.0, y: -CGFloat(width) / 2.0) } else { contextRef.translateBy(x: -CGFloat(width) / 2.0, y: -CGFloat(height) / 2.0) } contextRef.draw(imageRef, in: CGRect(x: 0, y: 0, width: originalWidth, height: originalHeight)) orientedImage = contextRef.makeImage() } } return orientedImage } 

用法:

 let newCgImage = createMatchingBackingDataWithImage(imageRef: cgImageRef, orienation: .left)