Reputation: 793
For rotating an UIImage I used an extension which is downloaded from the internet. There, rotating is working but there are some wired behaviours.
This is the extension code
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;
}
}
This is how I call extension method and set returned image to the image view. image view's 'contentMode' property is set to 'Scale to Fill'
currentPagePreviewImageVew.image = currentPagePreviewImageVew.image!.imageRotatedByDegrees(90, flip: false);
This is how it looks before pressing rotate button
This is after pressing rotate button once.(See image is not rotated but it's size has been changed)
This is when the image rotation is 90 degrees.(Here after image is rotating but as you can see the other views get stretched when image is in 0 and 180 degrees as in the above screen(2))
Can some one please tell me what is wrong with my code and if there is a better solution please let me know. Any help would be highly appreciated.
Edited: Stretching views was because of an constraint issue. I got it solved by putting a height constraint to the tool bar above the imageview. But still couldn't find an answer for that first time thing.
Upvotes: 4
Views: 1975
Reputation: 793
I used below extension and it worked fine. This is swift 3 actually.
import UIKit
extension UIImage {
public func rotateImageByDegrees(_ degrees: CGFloat) -> UIImage {
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: CGPoint.zero, size: self.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
bitmap?.scaleBy(x: 1.0, y: -1.0)
bitmap?.draw(self.cgImage!, in: CGRect(x: -self.size.width / 2, y: -self.size.height / 2, width: self.size.width, height: self.size.height))
let cgimage:CGImage = bitmap!.makeImage()!
return UIImage(cgImage: cgimage)
}
}
All the other things are same as in the question.
Upvotes: 0
Reputation: 3317
func flipImageVertical(originalImage: UIImage) -> UIImage
{
let tempImageView:UIImageView = UIImageView(image: originalImage)
UIGraphicsBeginImageContext(tempImageView.frame.size)
let context:CGContextRef = UIGraphicsGetCurrentContext()!
let flipVertical:CGAffineTransform = CGAffineTransformMake(1,0,0,-1,0,tempImageView.frame.size.height)
CGContextConcatCTM(context, flipVertical)
tempImageView.layer .renderInContext(context)
let flippedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return flippedImage
}
func flipImageHorizontal(originalImage: UIImage) -> UIImage
{
let tempImageView:UIImageView = UIImageView(image: originalImage)
UIGraphicsBeginImageContext(tempImageView.frame.size)
let context:CGContextRef = UIGraphicsGetCurrentContext()!
let flipHorizontal:CGAffineTransform = CGAffineTransformMake(-1,0,0,1,tempImageView.frame.size.width,0)
CGContextConcatCTM(context, flipHorizontal)
tempImageView.layer .renderInContext(context)
let flippedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return flippedImage
}
Upvotes: 4
Reputation: 35392
You must try this:
extension UIImage {
public func imageRotatedByDegrees(degrees: Double, flip: Bool) -> UIImage {
// 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(CGFloat(toRadian(degrees)))
rotatedViewBox.transform = t
let rotatedSize = rotatedViewBox.frame.size
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize)
let bitmap = UIGraphicsGetCurrentContext()
CGContextSetAllowsAntialiasing(bitmap, true)
CGContextSetShouldAntialias(bitmap, true)
CGContextSetInterpolationQuality(bitmap, CGInterpolationQuality.High)
// 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, CGFloat(toRadian(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
}
Then use this method to satisfy your new size:
extension UIImage {
public func resizeImage(newSize:CGSize) -> UIImage {
let newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height))
let imageRef:CGImageRef = self.CGImage!
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
let context:CGContextRef = UIGraphicsGetCurrentContext()!
// Set the quality level to use when rescaling
CGContextSetInterpolationQuality(context, CGInterpolationQuality.High)
CGContextSetAllowsAntialiasing(context, true)
CGContextSetShouldAntialias(context, true)
let flipVertical:CGAffineTransform = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height)
CGContextConcatCTM(context, flipVertical)
// Draw into the context; this scales the image
CGContextDrawImage(context, newRect, imageRef)
// Get the resized image from the context and a UIImage
let newImage:UIImage = UIImage(CGImage: CGBitmapContextCreateImage(context)!)
UIGraphicsEndImageContext();
return newImage
}
}
Upvotes: 1