【问题标题】:How Can I Rotate A UIImage and Image Data By 90 Degrees如何将 UIImage 和图像数据旋转 90 度
【发布时间】:2013-07-28 14:31:28
【问题描述】:

我有一个包含图像的 UIImageView。此时,用户可以单击将 UIImageView 中的图像保存到磁盘。

我想让用户可以点击旋转 UIImageView 并在视图中旋转 UImage 以便在保存图像时保持新的旋转。

此刻我有

- (IBAction)rotateImage:(id)sender {

float degrees = 90; //the value in degrees
self.imagePreview.transform = CGAffineTransformMakeRotation(degrees * M_PI/180);

}

有人能指出我保持当前旋转的正确方向吗?

谢谢

【问题讨论】:

  • 如果您希望在图像保存后继续旋转,您应该旋转 UIImage,而不是 UIImageView。
  • How to rotate UIImage的可能重复

标签: ios uiimageview uiimage


【解决方案1】:

我的旧应用中有这样的代码。但是这段代码可以简化,因为您无需将其旋转到非 90 度角。

Objective-C

@implementation UIImage (Rotation)

- (UIImage *)imageRotatedOnDegrees:(CGFloat)degrees
{
  // Follow ing code can only rotate images on 90, 180, 270.. degrees.
  CGFloat roundedDegrees = (CGFloat)(round(degrees / 90.0) * 90.0);
  BOOL sameOrientationType = ((NSInteger)roundedDegrees) % 180 == 0;
  CGFloat radians = M_PI * roundedDegrees / 180.0;
  CGSize newSize = sameOrientationType ? self.size : CGSizeMake(self.size.height, self.size.width);

  UIGraphicsBeginImageContext(newSize);
  CGContextRef ctx = UIGraphicsGetCurrentContext();
  CGImageRef cgImage = self.CGImage;
  if (ctx == NULL || cgImage == NULL) {
    UIGraphicsEndImageContext();
    return self;
  }

  CGContextTranslateCTM(ctx, newSize.width / 2.0, newSize.height / 2.0);
  CGContextRotateCTM(ctx, radians);
  CGContextScaleCTM(ctx, 1, -1);
  CGPoint origin = CGPointMake(-(self.size.width / 2.0), -(self.size.height / 2.0));
  CGRect rect = CGRectZero;
  rect.origin = origin;
  rect.size = self.size;
  CGContextDrawImage(ctx, rect, cgImage);
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return image ?: self;
}

@end

斯威夫特

extension UIImage {

  func imageRotated(on degrees: CGFloat) -> UIImage {
    // Following code can only rotate images on 90, 180, 270.. degrees.
    let degrees = round(degrees / 90) * 90
    let sameOrientationType = Int(degrees) % 180 == 0
    let radians = CGFloat.pi * degrees / CGFloat(180)
    let newSize = sameOrientationType ? size : CGSize(width: size.height, height: size.width)

    UIGraphicsBeginImageContext(newSize)
    defer {
      UIGraphicsEndImageContext()
    }

    guard let ctx = UIGraphicsGetCurrentContext(), let cgImage = cgImage else {
      return self
    }

    ctx.translateBy(x: newSize.width / 2, y: newSize.height / 2)
    ctx.rotate(by: radians)
    ctx.scaleBy(x: 1, y: -1)
    let origin = CGPoint(x: -(size.width / 2), y: -(size.height / 2))
    let rect = CGRect(origin: origin, size: size)
    ctx.draw(cgImage, in: rect)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    return image ?? self
  }

}

【讨论】:

  • 为什么要切换图像方向?
  • 对于 180 度,这会翻转图像。
  • @Nate 旋转 180 度(倒置)与翻转(正面背面)不同。
  • 看起来 Objective-C 代码在应用比例时存在问题。现在应该修复了。
【解决方案2】:

这将按任何给定的弧度旋转图像。

请注意,这也适用于 2x 和 3x 视网膜

- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees {
    CGFloat radians = DegreesToRadians(degrees);

    UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.size.width, self.size.height)];
    CGAffineTransform t = CGAffineTransformMakeRotation(radians);
    rotatedViewBox.transform = t;
    CGSize rotatedSize = rotatedViewBox.frame.size;

    UIGraphicsBeginImageContextWithOptions(rotatedSize, NO, [[UIScreen mainScreen] scale]);
    CGContextRef bitmap = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(bitmap, rotatedSize.width / 2, rotatedSize.height / 2);

    CGContextRotateCTM(bitmap, radians);

    CGContextScaleCTM(bitmap, 1.0, -1.0);
    CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2 , self.size.width, self.size.height), self.CGImage );

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

    return newImage;
}

【讨论】:

  • 这很好用,但是我用 CGFloat radians = degrees * (M_PI / 180.0); 替换了 CGFloat radians = DegreesToRadians(degrees); 以获得更多的“包含”解决方案
【解决方案3】:

在 Swift 4 中

imageView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi/2))

【讨论】:

    【解决方案4】:

    UIButton 的突出显示状态没有采用正常插入的旋转图像的正确方向。所以我不得不像@RyanG 显示的那样重新绘制图像。这是 Swift 2.2 的代码:

    extension UIImage
    {
        /// Rotate an image by any given radians.
        /// Works for 2x and 3x retina as well.
        func imageRotatedByDegrees(degrees: Double) -> UIImage
        {
            let radians = CGFloat(degrees * (M_PI / 180.0))
    
            let rotatedViewBox = UIView(frame: CGRect(origin: CGPointZero, size: self.size))
            let t: CGAffineTransform = CGAffineTransformMakeRotation(radians)
            rotatedViewBox.transform = t
            let rotatedSize = rotatedViewBox.frame.size
    
            UIGraphicsBeginImageContextWithOptions(rotatedSize, false, self.scale)
            let bitmap = UIGraphicsGetCurrentContext()
    
            CGContextTranslateCTM(bitmap, rotatedSize.width / 2, rotatedSize.height / 2)
            CGContextRotateCTM(bitmap, radians)
            CGContextScaleCTM(bitmap, 1.0, -1.0)
            CGContextDrawImage(bitmap, CGRect(origin: CGPoint(x: -self.size.width / 2, y: -self.size.height / 2), size: self.size), self.CGImage)
    
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return newImage
        }
    }
    

    【讨论】:

      【解决方案5】:

      根据@RyanG 的回答制作的 Swift 版本进行了一些修复:

      func rotated(by degrees: CGFloat) -> UIImage {
          let radians : CGFloat = degrees * CGFloat(.pi / 180.0)
          let rotatedViewBox = UIView(frame: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
          let t = CGAffineTransform(rotationAngle: radians)
          rotatedViewBox.transform = t
          let rotatedSize = rotatedViewBox.frame.size
          UIGraphicsBeginImageContextWithOptions(rotatedSize, false, self.scale)
          defer { UIGraphicsEndImageContext() }
          guard let bitmap = UIGraphicsGetCurrentContext(), let cgImage = self.cgImage else {
            return self
          }
          bitmap.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)
          bitmap.rotate(by: radians)
          bitmap.scaleBy(x: 1.0, y: -1.0)
          bitmap.draw(cgImage, in: CGRect(x: -self.size.width / 2, y: -self.size.height / 2, width: self.size.width, height: self.size.height))
          guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else {
            return self
          }
          return newImage
        }
      

      【讨论】:

      • 旋转后图像尺寸变大了,所以我必须添加:let rotatedSize = rotatedViewBox.frame.size; let roundedSize = CGSize(width: Int(rotatedSize.width), height: Int(rotatedSize.height)); UIGraphicsBeginImageContextWithOptions(roundedSize, false, self.scale);
      【解决方案6】:

      self.imageview.transform = CGAffineTransformMakeRotation(M_PI/2);

      【讨论】:

      • 这相当于 OP 已经看到的 90 * pi / 180 等于 M_PI/2。
      • M_PI_2 常量
      • 这不会旋转图像数据本身
      猜你喜欢
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      • 1970-01-01
      相关资源
      最近更新 更多