如何从UIImagePickerController中镜像显示UIImage图片

18

我正试图弄清楚是否有办法镜像一张图片。举个例子,拍摄某人的脸部照片并将其剪成两半,显示每一侧反转后的脸部。在CGAffineTransform函数中貌似没有任何可以达成此要求的技巧。请各位图形专家帮忙!!!

6个回答

42

这里的基本“技巧”是使用关于X或Y轴的缩放变换,因子为-1。例如,您可以使用此方法创建“水平轴翻转”的变换:

CGAffineTransform transform = CGAffineTransformScale(transform, -1, 1);

你可以在UIImageView上设置transform属性来翻转分配的图像,或者将它与另一个变换串联起来以进行更复杂的效果。要获得你描述的确切效果,你可能需要编写一些自定义绘图代码将原始图像绘制到上下文中,然后将翻转的一半覆盖在其上面。在Core Graphics中,这相对简单。


6
您可以使用CGAffineTransformMakeScale,即picker.cameraViewTransform = CGAffineTransformMakeScale(-1,1)来实现此操作。 - khunshan
1
太棒了!我使用了 myImageView.transform = CGAffineTransformMakeScale(-1, 1); - chris P

19

如果您只计划支持4.0版本以上

UIImageOrientation flippedOrientation = UIImageOrientationUpMirrored;
switch (image.imageOrientation) {
  case UIImageOrientationUp: break;
  case UIImageOrientationDown: flippedOrientation = UIImageOrientationDownMirrored; break;
  // ...
}
UIImage * flippedImage = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:flippedOrientation];

12

你可能会想,为什么要费心去处理冗长的switch语句呢?

? UIImage *flip = [UIImage imageWithCGImage:image.CGImage   
?                                     scale:image.scale
?                               orientation:(image.imageOrientation + 4) % 8];

如果您查看枚举,您会发现模算术可以解决此问题:
typedef NS_ENUM(NSInteger, UIImageOrientation) {
    UIImageOrientationUp,            // default orientation
    UIImageOrientationDown,          // 180 deg rotation
    UIImageOrientationLeft,          // 90 deg CCW
    UIImageOrientationRight,         // 90 deg CW
    UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
    UIImageOrientationDownMirrored,  // horizontal flip
    UIImageOrientationLeftMirrored,  // vertical flip
    UIImageOrientationRightMirrored, // vertical flip
};

但是这段代码过于巧妙。你应该编写一个带有明确 switch 语句的函数。例如:
UIImageOrientation mirroredImageOrientation(UIImageOrientation orientation) {
    switch(orientation) {
        case UIImageOrientationUp: return UIImageOrientationUpMirrored;
        case UIImageOrientationDown: return UIImageOrientationDownMirrored;
        case UIImageOrientationLeft: return UIImageOrientationLeftMirrored;
        case UIImageOrientationRight: return UIImageOrientationRightMirrored;
        case UIImageOrientationUpMirrored: return UIImageOrientationUp;
        case UIImageOrientationDownMirrored: return UIImageOrientationDown;
        case UIImageOrientationLeftMirrored: return UIImageOrientationLeft;
        case UIImageOrientationRightMirrored: return UIImageOrientationRight;
        default: return orientation;
    }
}

像这样使用函数:

UIImage *flip = [UIImage imageWithCGImage:image.CGImage   
                                    scale:image.scale
                              orientation:mirroredImageOrientation(image.imageOrientation)];

我已经添加了问号来表示可疑的、有异味的代码。类似于编程实践


1
实际上,即使你的答案看起来不错,也并非在所有情况下都是正确的。例如,如果你想进行水平翻转,但图像方向是向右的,你必须使用LeftMirrored,因为RightMirrored会导致垂直翻转。 - Tancrede Chazallet
从非镜像到镜像会水平镜像图像,从您坐在座位上的角度来看。 (您正确地指出,从图像本身的角度来看,它将根据枚举中的注释翻转。)如果面朝正确方向(头顶朝图像顶部),则从非镜像到镜像的所有变换都会水平翻转该面(即沿垂直轴)。UIImageOrientation文档:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/#//apple_ref/c/tdef/UIImageOrientation。 - sabalaba
我修改了我的答案,建议使用显式的 switch 语句。谁知道以后会发生什么事情呢?也许 Apple 会改变枚举的排序方式,这样模数算术版本就变成不正确的了。 - sabalaba

5

只需要使用以下方法即可:

UIImage(assetIdentifier: .myIcon)?.withHorizontallyFlippedOrientation()

5

以上回答均未涉及到问题的一半镜像而非整个图像翻转的部分。混合这些解决方案将导致以下示例函数,您可以将其用作UIImage + Mirroring等类别:

(UIImage *) horizontalMirror {
    UIImageOrientation flippedOrientation = UIImageOrientationUpMirrored;
    switch (self.imageOrientation) {
        case UIImageOrientationUp: break;
        case UIImageOrientationDown: flippedOrientation = UIImageOrientationDownMirrored; break;
    }
    UIImage * flippedImage = [UIImage imageWithCGImage:self.CGImage scale:1.0 orientation:flippedOrientation];

    CGImageRef inImage = self.CGImage;
    CGContextRef ctx = CGBitmapContextCreate(NULL,
                                             CGImageGetWidth(inImage),
                                             CGImageGetHeight(inImage),
                                             CGImageGetBitsPerComponent(inImage),
                                             CGImageGetBytesPerRow(inImage),
                                             CGImageGetColorSpace(inImage),
                                             CGImageGetBitmapInfo(inImage)
                                             );
    CGRect cropRect = CGRectMake(flippedImage.size.width/2, 0, flippedImage.size.width/2, flippedImage.size.height);
    CGImageRef TheOtherHalf = CGImageCreateWithImageInRect(flippedImage.CGImage, cropRect);
    CGContextDrawImage(ctx, CGRectMake(0, 0, CGImageGetWidth(inImage), CGImageGetHeight(inImage)), inImage);

    CGAffineTransform transform = CGAffineTransformMakeTranslation(flippedImage.size.width, 0.0);
    transform = CGAffineTransformScale(transform, -1.0, 1.0);
    CGContextConcatCTM(ctx, transform);

    CGContextDrawImage(ctx, cropRect, TheOtherHalf);

    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
    CGContextRelease(ctx);
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);

    return finalImage;
}

0

您可以使用以下代码来适用于Swift 4.0

 func didTakePicture(_ real_image: UIImage) {
   //suppose real_image = :)
 var flipped_image = UIImage(CGImage: real_image.CGImage!, scale: real_image.scale, orientation: .leftMirrored)
  // flipped_image is  (:
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接