iOS Image Rotation Method Example Code

  • 2021-11-29 08:40:29
  • OfStack

Rotate a specific angle through CGImage or CIImage

UIImage can be initialized by CGImage or CIImage, and the initialization methods are as follows init(cgImage: CGImage, scale: CGFloat, orientation: UIImageOrientation)和init(ciImage: CIImage, scale: CGFloat, orientation: UIImageOrientation) . Through different values of UIImageOrientation, the picture can be rotated 90, 180 and 270 degrees.

Draw with the original drawing

Rotate the picture at any angle by drawing the original image. You can draw a red background first, and the effect is as follows


static func rotateImage(_ image: UIImage, withAngle angle: Double) -> UIImage? {
  if angle.truncatingRemainder(dividingBy: 360) == 0 { return image }
  let imageRect = CGRect(origin: .zero, size: image.size)
  let radian = CGFloat(angle / 180 * M_PI)
  let rotatedTransform = CGAffineTransform.identity.rotated(by: radian)
  var rotatedRect = imageRect.applying(rotatedTransform)
  rotatedRect.origin.x = 0
  rotatedRect.origin.y = 0
  UIGraphicsBeginImageContext(rotatedRect.size)
  guard let context = UIGraphicsGetCurrentContext() else { return nil }
  context.translateBy(x: rotatedRect.width / 2, y: rotatedRect.height / 2)
  context.rotate(by: radian)
  context.translateBy(x: -image.size.width / 2, y: -image.size.height / 2)
  image.draw(at: .zero)
  let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return rotatedImage
}

If the rotation angle can be divisible by 360, it is not necessary to rotate and return to the original image directly. If it is a different angle, it needs to be drawn.

First of all, we should obtain CGRect with zero origin and the size of the original image, which is represented by imageRect. CGAffineTransform. identity obtains the identity matrix. CGAffineTransform的rotated(by angle: CGFloat) -> CGAffineTransform Method rotates the matrix by 1 fixed angle and returns the rotated matrix. The angle adopts radian system, with positive value being counterclockwise and negative value being clockwise. applying for CGRect (_ t: CGAffineTransform)- > The CGRect method uses the rotated matrix for the imageRect and returns the minimum CGRect containing the rotated imageRect, expressed as rotatedRect, as the bitmap size. The origin of rotatedRect may not be zero and needs to be set to zero.

The CGContext of the bitmap rotates on the origin axis. To rotate the picture around the center, first move the origin of CGContext to the center context.translateBy(x: rotatedRect.width / 2, y: rotatedRect.height / 2) And then rotate context. rotate (by: radian). The rotate (by angle: CGFloat) method of CGContext also adopts radian system, and the positive value indicates that context rotates counterclockwise, and the drawn effect is that the picture rotates clockwise. At this point, the origin of context is in the center of the bitmap, which needs to be shifted according to 1.5% of the original size. context.translateBy(x: -image.size.width / 2, y: -image.size.height / 2) So that the center of the whole map after drawing from the origin is in the center of the bitmap area.

If you want to get a red background, fill it in red immediately after getting context, that is, in guard let context = UIGraphicsGetCurrentContext() else { return nil } Add after


UIColor.red.setFill()
context.fill(rotatedRect)

Drawing through CALayer

You can put the picture on UIView and draw the rotated picture with CALayer.


static func rotateImage(_ image: UIImage, withAngle angle: Double) -> UIImage? {
  if angle.truncatingRemainder(dividingBy: 360) == 0 { return image }
  let imageView = UIImageView(image: image)
  imageView.transform = CGAffineTransform.identity.rotated(by: CGFloat(angle / 180 * M_PI))
  let rotatedRect = imageView.bounds.applying(imageView.transform)
  let containerView = UIView(frame: CGRect(origin: .zero, size: rotatedRect.size))
  imageView.center = containerView.center
  containerView.addSubview(imageView)
  UIGraphicsBeginImageContext(containerView.bounds.size)
  guard let context = UIGraphicsGetCurrentContext() else { return nil }
  containerView.layer.render(in: context)
  let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()
  return rotatedImage
}

Put the original image into UIImageView, represent it with imageView, and then rotate the matrix. Get the rotated CGRect and create an UIView of the same size, represented by containerView, as the parent view of imageView (superview). Center the imageView. Drawing with layer of containerView.

If you want a red background, set the background color after creating containerView, that is, in the let containerView = UIView(frame: CGRect(origin: .zero, size: rotatedRect.size)) Add after


containerView.backgroundColor = .red

Related articles: