SwiftでXcode 6.0.1を使用しています。 UIImageがあり、古い画像をソースとして使用して別の画像を作成します。新しい画像は何らかの方法で回転します。たとえば、垂直に反転します。
この質問はすでに回答済みです 数か月前 。ただし、状況は同じですが、この解決策は機能しません。
私が持っているとき
var image = UIImage(CGImage: otherImage.CGImage, scale: 1.0, orientation: .DownMirrored)
Xcodeは、「呼び出し中に追加の引数 'scale'」があることを訴えています。 Apple documentation回転。
私が見つけることができるこれへの唯一の他の参照は、同じ問題を抱えていた this guy です。
どう思いますか?
このバージョンのXcodeで実行するにはこれが必要なので、回転を実行する別の方法があれば(まだ見つかりませんでした)、役に立つでしょう。
これが最も簡単な解決策です
extension UIImage {
func rotate(radians: Float) -> UIImage? {
var newSize = CGRect(Origin: CGPoint.zero, size: self.size).applying(CGAffineTransform(rotationAngle: CGFloat(radians))).size
// Trim off the extremely small float value to prevent core graphics from rounding it up
newSize.width = floor(newSize.width)
newSize.height = floor(newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, self.scale)
let context = UIGraphicsGetCurrentContext()!
// Move Origin to middle
context.translateBy(x: newSize.width/2, y: newSize.height/2)
// Rotate around middle
context.rotate(by: CGFloat(radians))
// Draw the image at its center
self.draw(in: CGRect(x: -self.size.width/2, y: -self.size.height/2, width: self.size.width, height: self.size.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
このソリューションを使用するには、次のことができます
let image = UIImage(named: "image.png")!
let newImage = image.rotate(radians: .pi/2) // Rotate 90 degrees
UIImageの簡単な拡張を次に示します。
//ImageRotation.Swift
import UIKit
extension UIImage {
public func imageRotatedByDegrees(degrees: CGFloat, flip: Bool) -> UIImage {
let radiansToDegrees: (CGFloat) -> CGFloat = {
return $0 * (180.0 / CGFloat(M_PI))
}
let degreesToRadians: (CGFloat) -> CGFloat = {
return $0 / 180.0 * CGFloat(M_PI)
}
// calculate the size of the rotated view's containing box for our drawing space
let rotatedViewBox = UIView(frame: CGRect(Origin: CGPointZero, size: size))
let t = CGAffineTransformMakeRotation(degreesToRadians(degrees));
rotatedViewBox.transform = t
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.
CGContextTranslateCTM(bitmap, rotatedSize.width / 2.0, rotatedSize.height / 2.0);
// // Rotate the image context
CGContextRotateCTM(bitmap, degreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
var yFlip: CGFloat
if(flip){
yFlip = CGFloat(-1.0)
} else {
yFlip = CGFloat(1.0)
}
CGContextScaleCTM(bitmap, yFlip, -1.0)
CGContextDrawImage(bitmap, CGRectMake(-size.width / 2, -size.height / 2, size.width, size.height), CGImage)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
( ソース )
以下で使用します:
rotatedPhoto = rotatedPhoto?.imageRotatedByDegrees(90, flip: false)
前者は、画像が回転し、反転がtrueに設定されている場合に反転します。
extension UIImage {
struct RotationOptions: OptionSet {
let rawValue: Int
static let flipOnVerticalAxis = RotationOptions(rawValue: 1)
static let flipOnHorizontalAxis = RotationOptions(rawValue: 2)
}
func rotated(by rotationAngle: Measurement<UnitAngle>, options: RotationOptions = []) -> UIImage? {
guard let cgImage = self.cgImage else { return nil }
let rotationInRadians = CGFloat(rotationAngle.converted(to: .radians).value)
let transform = CGAffineTransform(rotationAngle: rotationInRadians)
var rect = CGRect(Origin: .zero, size: self.size).applying(transform)
rect.Origin = .zero
let renderer = UIGraphicsImageRenderer(size: rect.size)
return renderer.image { renderContext in
renderContext.cgContext.translateBy(x: rect.midX, y: rect.midY)
renderContext.cgContext.rotate(by: rotationInRadians)
let x = options.contains(.flipOnVerticalAxis) ? -1.0 : 1.0
let y = options.contains(.flipOnHorizontalAxis) ? 1.0 : -1.0
renderContext.cgContext.scaleBy(x: CGFloat(x), y: CGFloat(y))
let drawRect = CGRect(Origin: CGPoint(x: -self.size.width/2, y: -self.size.height/2), size: self.size)
renderContext.cgContext.draw(cgImage, in: drawRect)
}
}
}
次のように使用できます。
let rotatedImage = UIImage(named: "my_amazing_image")?.rotated(by: Measurement(value: 48.0, unit: .degrees))
反転フラグを指定した場合:
let flippedImage = UIImage(named: "my_amazing_image")?.rotated(by: Measurement(value: 48.0, unit: .degrees), options: [.flipOnVerticalAxis])
通常、「呼び出し中の追加引数」は、入力タイプの1つが正しくない場合に発生します。
コードを修正するには
var image = UIImage(CGImage: otherImage.CGImage, scale: CGFloat(1.0), orientation: .DownMirrored)
スウィフト3:
右に回転:
let image = UIImage(cgImage: otherImage.cgImage!, scale: CGFloat(1.0), orientation: .right)
プレイグラウンドでテスト済み:
// MyPlayground.playground
import UIKit
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
view.backgroundColor = UIColor.white
PlaygroundPage.current.liveView = view
let otherImage = UIImage(named: "burger.png", in: Bundle.main,
compatibleWith: nil)
let imageViewLeft = UIImageView(image: UIImage(cgImage: (otherImage?.cgImage!)!, scale: CGFloat(1.0), orientation: .left))
let imageViewRight = UIImageView(image: UIImage(cgImage: (otherImage?.cgImage!)!, scale: CGFloat(1.0), orientation: .right))
view.addSubview(imageViewLeft)
view.addSubview(imageViewRight)
view.layoutIfNeeded()
このコードを試してください、それは私のために働いた:
@IBAction func btnRotateImagePressed(sender: AnyObject) {
if let originalImage = self.imageView.image {
let rotateSize = CGSize(width: originalImage.size.height, height: originalImage.size.width)
UIGraphicsBeginImageContextWithOptions(rotateSize, true, 2.0)
if let context = UIGraphicsGetCurrentContext() {
CGContextRotateCTM(context, 90.0 * CGFloat(M_PI) / 180.0)
CGContextTranslateCTM(context, 0, -originalImage.size.height)
originalImage.drawInRect(CGRectMake(0, 0, originalImage.size.width, originalImage.size.height))
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
}
@ confile answerがSwift 4に更新されました
import UIKit
extension UIImage {
public func imageRotatedByDegrees(degrees: CGFloat, flip: Bool) -> UIImage {
let radiansToDegrees: (CGFloat) -> CGFloat = {
return $0 * (180.0 / CGFloat.pi)
}
let degreesToRadians: (CGFloat) -> CGFloat = {
return $0 / 180.0 * CGFloat.pi
}
// calculate the size of the rotated view's containing box for our drawing space
let rotatedViewBox = UIView(frame: CGRect(Origin: .zero, size: size))
let t = CGAffineTransform(rotationAngle: degreesToRadians(degrees));
rotatedViewBox.transform = t
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)
// // Rotate the image context
bitmap?.rotate(by: degreesToRadians(degrees))
// 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)
let rect = CGRect(x: -size.width / 2, y: -size.height / 2, width: size.width, height: size.height)
bitmap?.draw(cgImage!, in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
UIGraphicsBeginImageContext
を使用しないでください。ベクトルの品質が損なわれるため、UIGraphicsBeginImageContextWithOptions
を使用してください。これはSwift 3/4での私の実装です:
extension UIImage {
func rotated(degrees: CGFloat) -> UIImage? {
let degreesToRadians: (CGFloat) -> CGFloat = { (degrees: CGFloat) in
return degrees / 180.0 * CGFloat.pi
}
// Calculate the size of the rotated view's containing box for our drawing space
let rotatedViewBox: UIView = UIView(frame: CGRect(Origin: .zero, size: size))
rotatedViewBox.transform = CGAffineTransform(rotationAngle: degreesToRadians(degrees))
let rotatedSize: CGSize = rotatedViewBox.frame.size
// Create the bitmap context
UIGraphicsBeginImageContextWithOptions(rotatedSize, false, 0.0)
guard let bitmap: CGContext = UIGraphicsGetCurrentContext(), let unwrappedCgImage: CGImage = cgImage else {
return nil
}
// 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)
// Rotate the image context
bitmap.rotate(by: degreesToRadians(degrees))
bitmap.scaleBy(x: CGFloat(1.0), y: -1.0)
let rect: CGRect = CGRect(
x: -size.width/2,
y: -size.height/2,
width: size.width,
height: size.height)
bitmap.draw(unwrappedCgImage, in: rect)
guard let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() else {
return nil
}
UIGraphicsEndImageContext()
return newImage
}
For Swift 4.2の場合
extension UIImage {
func rotate(_ radians: CGFloat) -> UIImage {
let cgImage = self.cgImage!
let LARGEST_SIZE = CGFloat(max(self.size.width, self.size.height))
let context = CGContext.init(data: nil, width:Int(LARGEST_SIZE), height:Int(LARGEST_SIZE), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: cgImage.colorSpace!, bitmapInfo: cgImage.bitmapInfo.rawValue)!
var drawRect = CGRect.zero
drawRect.size = self.size
let drawOrigin = CGPoint(x: (LARGEST_SIZE - self.size.width) * 0.5,y: (LARGEST_SIZE - self.size.height) * 0.5)
drawRect.Origin = drawOrigin
var tf = CGAffineTransform.identity
tf = tf.translatedBy(x: LARGEST_SIZE * 0.5, y: LARGEST_SIZE * 0.5)
tf = tf.rotated(by: CGFloat(radians))
tf = tf.translatedBy(x: LARGEST_SIZE * -0.5, y: LARGEST_SIZE * -0.5)
context.concatenate(tf)
context.draw(cgImage, in: drawRect)
var rotatedImage = context.makeImage()!
drawRect = drawRect.applying(tf)
rotatedImage = rotatedImage.cropping(to: drawRect)!
let resultImage = UIImage(cgImage: rotatedImage)
return resultImage
}
}
これはiOS 8以降で機能し、画質を維持します。 UIImageの2つの拡張機能です。
extension UIImage {
func withSize(_ width: CGFloat, _ height: CGFloat) -> UIImage {
let target = CGSize(width, height)
var scaledImageRect = CGRect.zero
let aspectWidth:CGFloat = target.width / self.size.width
let aspectHeight:CGFloat = target.height / self.size.height
let aspectRatio:CGFloat = min(aspectWidth, aspectHeight)
scaledImageRect.size.width = self.size.width * aspectRatio
scaledImageRect.size.height = self.size.height * aspectRatio
scaledImageRect.Origin.x = (target.width - scaledImageRect.size.width) / 2.0
scaledImageRect.Origin.y = (target.height - scaledImageRect.size.height) / 2.0
UIGraphicsBeginImageContextWithOptions(target, false, 0)
self.draw(in: scaledImageRect)
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return scaledImage!
}
func rotated(degrees: Double) -> UIImage {
let radians = CGFloat(Double.pi * degrees / 180)
var rotatedViewBox: UIView? = UIView(frame: CGRect(x: 0, y: 0, width: size.width * scale, height: size.height * scale))
let t = CGAffineTransform(rotationAngle: radians)
rotatedViewBox!.transform = t
let rotatedSize = rotatedViewBox!.frame.size
rotatedViewBox = nil
// 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, y: rotatedSize.height/2)
// // Rotate the image context
bitmap.rotate(by: radians)
// Now, draw the rotated/scaled image into the context
bitmap.scaleBy(x: 1.0, y: -1.0)
bitmap.draw(cgImage!, in: CGRect(x:-size.width * scale / 2, y: -size.height * scale / 2, width: size.width * scale, height: size.height * scale))
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage.withSize(newImage.size.width/scale, newImage.size.height/scale)
}
}
これをチェックして:
func rotatedImage(with angle: CGFloat) -> UIImage {
let updatedSize = CGRect(Origin: .zero, size: size)
.applying(CGAffineTransform(rotationAngle: angle))
.size
return UIGraphicsImageRenderer(size: updatedSize)
.image { _ in
let context = UIGraphicsGetCurrentContext()
context?.translateBy(x: updatedSize.width / 2.0, y: updatedSize.height / 2.0)
context?.rotate(by: angle)
draw(in: CGRect(x: -size.width / 2.0, y: -size.height / 2.0, width: size.width, height: size.height))
}
.withRenderingMode(renderingMode)
}