I face a problem when after UIImage
rotation the white lines appear on sides of the image. In my image redactor I have rotateButton. After tapping on it I call this function:
func rotateLeft() -> UIImage? {
let radians = CGFloat.rotateRadians
// Calculate the size of the rotated image
var rotatedSize = CGRect(origin: .zero, size: size)
.applying(CGAffineTransform(rotationAngle: radians))
.integral.size
// Round the dimensions to the nearest whole number
rotatedSize.width = round(rotatedSize.width)
rotatedSize.height = round(rotatedSize.height)
// Create a context for the rotated image
UIGraphicsBeginImageContext(rotatedSize)
defer { UIGraphicsEndImageContext() }
if let context = UIGraphicsGetCurrentContext() {
// Move the origin to the center of the image
context.translateBy(x: rotatedSize.width / 2.0, y: rotatedSize.height / 2.0)
// Rotate the context
context.rotate(by: radians)
// Draw the image
draw(in: CGRect(
x: -size.width / 2.0,
y: -size.height / 2.0,
width: size.width,
height: size.height)
)
// Get the rotated image from the context
if let rotatedImage = UIGraphicsGetImageFromCurrentImageContext() {
return rotatedImage
}
}
return nil
}
This function return rotated image, after what I just animate image in UIImageVIew
, and in completion I assigns this new rotate image to UIImageView (everything works fine, I think).
But the problem is that if I spam this button many times (button tap only work when previous rotation logic finished), the white lines become bigger and bigger.
I read that a problem is cause of floting points after rotation, so I tried to round
size, but it doesn't help.
So can someone explain what Is a problem, or give me some link where I can read about this problem.
P.S. When I use UIGraphicsImageRenderer
it works much slower than previous deprecated method:
func rotateLeft() -> UIImage? {
let radians = CGFloat.rotateRadians
// Calculate the size of the rotated view's containing box for our drawing space
let rotatedSize = CGSize(width: size.height, height: size.width)
// Create the renderer with the rotatedSize
let renderer = UIGraphicsImageRenderer(size: rotatedSize)
// Perform the rotation transformation within the image renderer context
let rotatedImage = renderer.image { context in
context.cgContext.translateBy(x: rotatedSize.width / 2.0, y: rotatedSize.height / 2.0)
context.cgContext.rotate(by: radians)
// Translate and rotate the graphics context
let origin = CGPoint(x: -size.width / 2, y: -size.height / 2)
// Draw the original image in the rotated context
draw(at: origin)
}
return rotatedImage
}
The problem with UIGraphicsImageRenderer
was that it automatically take iPhone scale(in my case 3), so image 2000x1000 became 6000x3000. You need to setup scale factor to 1, in renderer.
The CGRect function applying(_ t: CGAffineTransform) -> CGRect
doesn't return meaningful values for rotations unless they are multiples of 90°, and even then, you might get floating point errors. Does your app support arbitrary rotation angles? If not, I would suggest either leaving the rectangle the same size for 180° rotations, or just swapping the height and width for 90° rotations.
That should preserve your image without introducing white bars on the sides, since you'll always be rendering your image into a rect with the exact number of pixels.