Je ne parviens pas à faire pivoter l'image de 90 degrés avec Swift. J'ai écrit ci-dessous le code mais il y a une erreur et ne compile pas
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
}
ci-dessous est le code que je ne suis pas sûr de
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))
Ceci est une extension de UIImage
qui cible Swift 4. et peut faire pivoter uniquement l'image sans avoir besoin d'un UIImageView
. Testé avec succès que l'image a été pivotée, et pas seulement ses données exif ont été modifiées.
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
}
}
Pour effectuer une rotation de 180 degrés, vous pouvez l'appeler comme suit:
let rotatedImage = image.rotate(radians: .pi)
Si, pour une raison quelconque, la rotation n’est pas effectuée, l’image d’origine sera alors renvoyée.
définir l'image 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
En une ligne:
rotatedViewBox.transform = CGAffineTransform(rotationAngle: CGFloat.pi/2)
Dans Swift 4.2 et Xcode 10.0
dropDownImageView.transform = dropDownImageView.transform.rotated(by: CGFloat(Double.pi / 2))
Si vous voulez ajouter une animation ...
UIView.animate(withDuration: 2.0, animations: {
self.dropDownImageView.transform = self.dropDownImageView.transform.rotated(by: CGFloat(Double.pi / 2))
})
Vous pouvez utiliser le code ci-dessous pour 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
}
Vous pouvez d'abord définir votre image dans imageView et faire pivoter pour obtenir votre image dans imageView
Ici:
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!
Votre code n'est pas si loin d'être fonctionnel. Vous pouvez appliquer la transformation comme vous le faites directement au bitmap, vous n'avez pas besoin d'une vue intermédiaire:
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
}
En outre, si vous créez une fonction qui fait pivoter une image, il est généralement judicieux d'inclure un paramètre clockwise: Bool
qui interprétera l'argument degrees
comme une rotation dans le sens des aiguilles d'une montre ou non. La mise en œuvre et la conversion appropriée en radians je vous laisse.
Notez aussi que c'est un peu vague de ma part de supposer que oldImage.size
est différent de zéro. Si tel est le cas, le décompressage forcé UIGraphicsGetCurrentContext()!
se produira probablement. Vous devez valider la taille de oldImage
et, si elle est invalide, vous devez simplement renvoyer oldImage
.
Votre problème est que vous utilisez un initialiseur non existant pour CGRect. Si vous souhaitez utiliser CGRect (Origin: size:), créez correctement Origin, sans paramètres de largeur et de hauteur. Ou supprimez le paramètre de taille et utilisez CGRect (x: y: largeur: hauteur:).
Il suffit de remplacer cette ligne
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))
avec celui-ci:
let rect = CGRect(Origin: CGPoint(x: -oldImage.size.width / 2, y: -oldImage.size.height / 2), size: oldImage.size)
bitmap.draw(oldImage.cgImage!, in: rect)