Swiftで画像を90度回転させることができません。私は以下のコードを書きましたが、エラーがあり、コンパイルしません
func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage {
//Calculate the size of the rotated view's containing box for our drawing space
let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height))
let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat(M_PI / 180))
rotatedViewBox.transform = t
let rotatedSize: CGSize = rotatedViewBox.frame.size
//Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize)
let bitmap: CGContext = UIGraphicsGetCurrentContext()!
//Move the Origin to the middle of the image so we will rotate and scale around the center.
bitmap.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)
//Rotate the image context
bitmap.rotate(by: (degrees * CGFloat(M_PI / 180)))
//Now, draw the rotated/scaled image into the context
bitmap.scaleBy(x: 1.0, y: -1.0)
bitmap.draw(oldImage, in: CGRect(Origin: (x: -oldImage.size.width / 2, y: -oldImage.size.height / 2, width: oldImage.size.width, height: oldImage.size.height), size: oldImage.cgImage))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
以下は私がわからないコードです
bitmap.draw(oldImage, in: CGRect(Origin: (x: -oldImage.size.width / 2, y: -oldImage.size.height / 2, width: oldImage.size.width, height: oldImage.size.height), size: oldImage.cgImage))
これは、Swift 4.をターゲットとするUIImage
の拡張であり、UIImageView
を必要とせずにイメージのみを回転できます。 exifデータが変更されただけでなく、画像が回転したことを正常にテストしました。
import UIKit
extension UIImage {
func rotate(radians: CGFloat) -> UIImage {
let rotatedSize = CGRect(Origin: .zero, size: size)
.applying(CGAffineTransform(rotationAngle: CGFloat(radians)))
.integral.size
UIGraphicsBeginImageContext(rotatedSize)
if let context = UIGraphicsGetCurrentContext() {
let Origin = CGPoint(x: rotatedSize.width / 2.0,
y: rotatedSize.height / 2.0)
context.translateBy(x: Origin.x, y: Origin.y)
context.rotate(by: radians)
draw(in: CGRect(x: -Origin.y, y: -Origin.x,
width: size.width, height: size.height))
let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return rotatedImage ?? self
}
return self
}
}
180度の回転を実行するには、次のように呼び出すことができます。
let rotatedImage = image.rotate(radians: .pi)
何らかの理由で回転に失敗した場合、元の画像が返されます。
imageView画像を設定します
ImageView.transform = ImageView.transform.rotated(by: CGFloat(M_PI_2))
let angle = CGFloat(M_PI_2)
let tr = CGAffineTransform.identity.rotated(by: angle)
ImageView.transform = tr
1行で:
rotatedViewBox.transform = CGAffineTransform(rotationAngle: CGFloat.pi/2)
Swift 4.2およびXcode 10.0
dropDownImageView.transform = dropDownImageView.transform.rotated(by: CGFloat(Double.pi / 2))
アニメーションを追加する場合...
UIView.animate(withDuration: 2.0, animations: {
self.dropDownImageView.transform = self.dropDownImageView.transform.rotated(by: CGFloat(Double.pi / 2))
})
Swift 3には次のコードを使用できます。
extension UIImage {
func fixImageOrientation() -> UIImage? {
var flip:Bool = false //used to see if the image is mirrored
var isRotatedBy90:Bool = false // used to check whether aspect ratio is to be changed or not
var transform = CGAffineTransform.identity
//check current orientation of original image
switch self.imageOrientation {
case .down, .downMirrored:
transform = transform.rotated(by: CGFloat(M_PI));
case .left, .leftMirrored:
transform = transform.rotated(by: CGFloat(M_PI_2));
isRotatedBy90 = true
case .right, .rightMirrored:
transform = transform.rotated(by: CGFloat(-M_PI_2));
isRotatedBy90 = true
case .up, .upMirrored:
break
}
switch self.imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: self.size.width, y: 0)
flip = true
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: self.size.height, y: 0)
flip = true
default:
break;
}
// calculate the size of the rotated view's containing box for our drawing space
let rotatedViewBox = UIView(frame: CGRect(Origin: CGPoint(x:0, y:0), size: size))
rotatedViewBox.transform = transform
let rotatedSize = rotatedViewBox.frame.size
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize)
let bitmap = UIGraphicsGetCurrentContext()
// Move the Origin to the middle of the image so we will rotate and scale around the center.
bitmap!.translateBy(x: rotatedSize.width / 2.0, y: rotatedSize.height / 2.0);
// Now, draw the rotated/scaled image into the context
var yFlip: CGFloat
if(flip){
yFlip = CGFloat(-1.0)
} else {
yFlip = CGFloat(1.0)
}
bitmap!.scaleBy(x: yFlip, y: -1.0)
//check if we have to fix the aspect ratio
if isRotatedBy90 {
bitmap?.draw(self.cgImage!, in: CGRect(x: -size.width / 2, y: -size.height / 2, width: size.height,height: size.width))
} else {
bitmap?.draw(self.cgImage!, in: CGRect(x: -size.width / 2, y: -size.height / 2, width: size.width,height: size.height))
}
let fixedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return fixedImage
}
最初にimageViewで画像を設定し、imageViewで画像を回転して取得できます。
ここに:
let customImageView = UIImageView()
customImageView.frame = CGRect.init(x: 0, y: 0, w: 250, h: 250)
customImageView.image = UIImage(named: "yourImage")
customImageView .transform = customImageView .transform.rotated(by: CGFloat.init(M_PI_2))
var rotatedImage = UIImage()
rotatedImage = customImageView.image!
あなたのコードは機能的からそう遠くありません。ビットマップに直接行うように変換を適用できます。中間ビューは必要ありません。
func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage {
let size = oldImage.size
UIGraphicsBeginImageContext(size)
let bitmap: CGContext = UIGraphicsGetCurrentContext()!
//Move the Origin to the middle of the image so we will rotate and scale around the center.
bitmap.translateBy(x: size.width / 2, y: size.height / 2)
//Rotate the image context
bitmap.rotate(by: (degrees * CGFloat(M_PI / 180)))
//Now, draw the rotated/scaled image into the context
bitmap.scaleBy(x: 1.0, y: -1.0)
let Origin = CGPoint(x: -size.width / 2, y: -size.width / 2)
bitmap.draw(oldImage.cgImage!, in: CGRect(Origin: Origin, size: size))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
また、画像を回転させる関数を作成する場合、通常、degrees
引数を時計回りに回転するかどうかを解釈するclockwise: Bool
パラメーターを含めるのが適切です。実装とラジアンへの適切な変換はあなたにお任せします。
また、oldImage.size
がゼロ以外であると仮定することは、私の側では少し手作業であることに注意してください。そうである場合、UIGraphicsGetCurrentContext()!
を強制的にアンラップすると、おそらくクラッシュします。 oldImage
のサイズを検証し、無効な場合はoldImage
を返す必要があります。
問題は、CGRectに存在しない初期化子を使用することです。 CGRect(Origin:size:)を使用する場合は、幅と高さのパラメーターを指定せずにOriginを適切に作成します。または、サイズパラメータを削除してCGRect(x:y:width:height:)を使用します。
この行を置き換えるだけです
bitmap.draw(oldImage, in: CGRect(Origin: (x: -oldImage.size.width / 2, y: -oldImage.size.height / 2, width: oldImage.size.width, height: oldImage.size.height), size: oldImage.cgImage))
これで:
let rect = CGRect(Origin: CGPoint(x: -oldImage.size.width / 2, y: -oldImage.size.height / 2), size: oldImage.size)
bitmap.draw(oldImage.cgImage!, in: rect)