I face a problem when afterUIImage 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 inUIImageVIew, 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 toround 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 useUIGraphicsImageRenderer 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 withUIGraphicsImageRenderer 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.
- Note that
UIGraphicsBeginImageContextandUIGraphicsBeginImageContextWithOptions(_:_:_:)are deprecated. You should useUIGraphicsImageRendererinstead.Duncan C– Duncan C2023-11-07 20:34:33 +00:00CommentedNov 7, 2023 at 20:34
1 Answer1
The CGRect functionapplying(_ 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.
2 Comments
floor width and height, but white lines still were there.Explore related questions
See similar questions with these tags.