旋转一个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)