【问题标题】:Flip UIImage Along Either Axis沿任一轴翻转 UIImage
【发布时间】:2011-09-21 16:02:45
【问题描述】:

我正在尝试创建一种沿 X 轴、Y 轴或两者翻转 UIImage 的方法。我一直在接近,但我的变换知识还不够好,无法一直到达那里。这是我到目前为止的代码:

- (UIImage *)flippedImageByAxis:(MVImageFlip)axis{
     UIGraphicsBeginImageContext(self.size);
     CGContextRef context = UIGraphicsGetCurrentContext();
     CGAffineTransform verticalFlip = CGAffineTransformMake(1, 0, 0, -1, 0, self.size.height);
     CGAffineTransform horizFlip = CGAffineTransformMake(-1.0, 0.0, 0.0, 1.0, self.size.width, 0.0);

     if(axis == MVImageFlipXAxis || axis == MVImageFlipXAxisAndYAxis)
         CGContextConcatCTM(context, horizFlip);
     if(axis == MVImageFlipYAxis || axis == MVImageFlipXAxisAndYAxis)
         CGContextConcatCTM(context, verticalFlip);

     CGContextDrawImage(context, CGRectMake(0.0, 0.0, self.size.width, self.size.height), [self CGImage]);

     UIImage *flipedImage = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

     return flipedImage;
 }

这会翻转图像但不正确。 Y 翻转的图像根本没有翻转,X 翻转的图像看起来像 XY 图像应该看起来的样子,而 XY 图像看起来像 Y 图像应该看起来的样子。组合变换并让它们正常工作让我头疼。

MVImageFlip 枚举只是您在代码中看到的三个。没什么特别的。

【问题讨论】:

    标签: iphone cocoa-touch core-graphics


    【解决方案1】:

    如果您打算只显示图像而不保存它,您可能不想创建第二个 CGContext。只使用 UIImage 中已经加载的 CGImage 并像这样更改方向会更有效:

    - (UIImage *)flippedImageByFlippingAlongXAxis:(BOOL)flipOnX andAlongYAxis:(BOOL)flipOnY
    {
        UIImageOrientation currentOrientation = self.imageOrientation;
        UIImageOrientation newOrientation = currentOrientation;
    
        if (flipOnX == YES) {
            switch (newOrientation) {
                case UIImageOrientationUp:
                    newOrientation = UIImageOrientationUpMirrored;
                    break;
                case UIImageOrientationDown:
                    newOrientation = UIImageOrientationMirrored;
                    break;
                case UIImageOrientationUpMirrored:
                    newOrientation = UIImageOrientationUp;
                    break;
                case UIImageOrientationDownMirrored:
                    newOrientation = UIImageOrientationDown;
                    break;
                case UIImageOrientationLeft:
                    newOrientation = UIImageOrientationLeftMirrored;
                    break;
                case UIImageOrientationRight:
                    newOrientation = UIImageOrientationRightMirrored;
                    break;
                case UIImageOrientationLeftMirrored:
                    newOrientation = UIImageOrientationLeft;
                    break;
                case UIImageOrientationRightMirrored:
                    newOrientation = UIImageOrientationRight;
                    break;
            }
        }
    
        if (flipOnY == YES) {
            switch (newOrientation) {
                case UIImageOrientationUp:
                    newOrientation = UIImageOrientationDownMirrored;
                    break;
                case UIImageOrientationDown:
                    newOrientation = UIImageOrientationUpMirrored;
                    break;
                case UIImageOrientationUpMirrored:
                    newOrientation = UIImageOrientationDown;
                    break;
                case UIImageOrientationDownMirrored:
                    newOrientation = UIImageOrientationUp;
                    break;
                case UIImageOrientationLeft:
                    newOrientation = UIImageOrientationRightMirrored;
                    break;
                case UIImageOrientationRight:
                    newOrientation = UIImageOrientationLeftMirrored;
                    break;
                case UIImageOrientationLeftMirrored:
                    newOrientation = UIImageOrientationRight;
                    break;
                case UIImageOrientationRightMirrored:
                    newOrientation = UIImageOrientationLeft;
                    break;
            }
        }
    
        return [UIImage imageWithCGImage:self.CGImage scale:self.scale orientation:newOrientation];
    }
    

    当您启动一个新的 CGContext 并使用 CGContextDrawImage 进行翻转时,您正在分配另一块内存来以不同的顺序保存相同的字节。通过更改 UIImage 方向,您可以避免再次分配。使用相同的图像数据,只是以不同的方向绘制。

    【讨论】:

    • 这是旧的,但我想我会发表评论。实际上,我确实需要将图像保存在我的特定问题中。无论哪种方式,这都是很好的建议,如果图像仅用于显示,则效率更高。
    • 我喜欢这个答案,我喜欢重用 CGContext,因为我只显示图片。然而,就目前而言,它是不正确的。更改(以 Swift 表示法).Up.Down.LeftMirrored.RightMirrored 实际上是在进行 180 度旋转,因此每个开关中有 4 个案例没有进行反射。要在上面的示例中修复它,您只需确保对于每种情况,您始终添加或删除“镜像”。为了完整起见,我将迅速添加另一个答案
    • 修复了答案。
    【解决方案2】:

    Swift 3 版本:

    func flipV(im:UIImage)->UIImage {
            var newOrient:UIImageOrientation
            switch im.imageOrientation {
            case .up:
                newOrient = .downMirrored
            case .upMirrored:
                newOrient = .down
            case .down:
                newOrient = .upMirrored
            case .downMirrored:
                newOrient = .up
            case .left:
                newOrient = .leftMirrored
            case .leftMirrored:
                newOrient = .left
            case .right:
                newOrient = .rightMirrored
            case .rightMirrored:
                newOrient = .right
            }
            return UIImage(cgImage: im.cgImage!, scale: im.scale, orientation: newOrient)
        }
    
        func flipH(im:UIImage)->UIImage {
            var newOrient:UIImageOrientation
            switch im.imageOrientation {
            case .up:
                newOrient = .upMirrored
            case .upMirrored:
                newOrient = .up
            case .down:
                newOrient = .downMirrored
            case .downMirrored:
                newOrient = .down
            case .left:
                newOrient = .rightMirrored
            case .leftMirrored:
                newOrient = .right
            case .right:
                newOrient = .leftMirrored
            case .rightMirrored:
                newOrient = .left
            }
            return UIImage(cgImage: im.cgImage!, scale: im.scale, orientation: newOrient)
        }
    

    【讨论】:

    • 请不要提供纯代码答案。你应该详细说明你的方法。这有助于其他用户更好地了解您的解决方案。
    【解决方案3】:

    这只是@ultramiraculous 旧答案的略微固定和“更新到 Swift”版本。以防万一它对某人有帮助。

    垂直翻转(在 x 轴上的反射):

    func flipV(im:UIImage)->UIImage {
        var newOrient:UIImageOrientation
        switch im.imageOrientation {
        case .Up:
            newOrient = .DownMirrored
        case .UpMirrored:
            newOrient = .Down
        case .Down:
            newOrient = .UpMirrored
        case .DownMirrored:
            newOrient = .Up
        case .Left:
            newOrient = .LeftMirrored
        case .LeftMirrored:
            newOrient = .Left
        case .Right:
            newOrient = .RightMirrored
        case .RightMirrored:
            newOrient = .Right
        }
        return UIImage(CGImage: im.CGImage, scale: im.scale, orientation: newOrient)
    }
    

    水平翻转(在 y 轴上的反射)

    func flipH(im:UIImage)->UIImage {
        var newOrient:UIImageOrientation
        switch im.imageOrientation {
        case .Up:
            newOrient = .UpMirrored
        case .UpMirrored:
            newOrient = .Up
        case .Down:
            newOrient = .DownMirrored
        case .DownMirrored:
            newOrient = .Down
        case .Left:
            newOrient = .RightMirrored
        case .LeftMirrored:
            newOrient = .Right
        case .Right:
            newOrient = .LeftMirrored
        case .RightMirrored:
            newOrient = .Left
        }
        return UIImage(CGImage: im.CGImage, scale: im.scale, orientation: newOrient)
    }
    

    【讨论】:

      【解决方案4】:

      我终于能够弄清楚这一点。这是适用于可能需要它的任何其他人的代码。

      - (UIImage *)flippedImageByAxis:(MVImageFlip)axis{
          UIGraphicsBeginImageContext(self.size);
          CGContextRef context = UIGraphicsGetCurrentContext();
      
          if(axis == MVImageFlipXAxis){
              // Do nothing, X is flipped normally in a Core Graphics Context
          } else if(axis == MVImageFlipYAxis){
              // fix X axis
              CGContextTranslateCTM(context, 0, self.size.height);
              CGContextScaleCTM(context, 1.0f, -1.0f);
      
              // then flip Y axis
              CGContextTranslateCTM(context, self.size.width, 0);
              CGContextScaleCTM(context, -1.0f, 1.0f);
          } else if(axis == MVImageFlipXAxisAndYAxis){
              // just flip Y
              CGContextTranslateCTM(context, self.size.width, 0);
              CGContextScaleCTM(context, -1.0f, 1.0f);
          }
      
          CGContextDrawImage(context, CGRectMake(0.0, 0.0, self.size.width, self.size.height), [self CGImage]);
      
          UIImage *flipedImage = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
      
          return flipedImage;
      }
      

      【讨论】:

      • 我更喜欢这样的上下文中的图像比例:UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
      【解决方案5】:

      尝试以下方法:

      UIImage* myimage = [UIImage imageNamed: @"myimage.png"];
      myimage = [UIImage imageWithCGImage: myimage.CGImage scale: 1.0f orientation: UIImageOrientationUpMirrored];
      

      【讨论】:

      • 其实我之前发现过这个sn-p,先试了一下。它没有做任何事情,生成的 UIImages 与输入完全相同。我会再试一次以确定。
      • 刚刚又试了一次,还是不行。很奇怪。
      • 正确的参数是UIImageOrientationDownMirroredUIImageOrientationDown 来翻转图像。文档:here
      猜你喜欢
      • 2021-02-13
      • 2011-03-29
      • 1970-01-01
      • 2011-07-28
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      相关资源
      最近更新 更多