Diagonal transparent lines are added while converting UIView to UIImage - uiview

I am trying to convert UIView containing 2 UIImageView to UIImage. Almost everything is working fine, but on final conversion some transparent diagonal lines are shown in final UIImage. I cant understand why is this happening. If someone can help. Thanks.
extension UIView {
/**
Convert UIView to UIImage
*/
func toImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return snapshotImageFromMyView!
}
}
following are before and after saving image
enter image descriptBefore SavingAfter Saving

I found the problem, my code was converting resulting UIImage to Webp at 0.70 quality. That was adding lines in image. By saving jpg and then converting to webp fixed the problem.

Related

How to apply CIFilter to UIView?

According to Apple docs, filters property of CALayer is not supported in iOS. As i used one of the apps which are applying CIFilter to UIView i.e. Splice, Video Editor Videoshow FX for Funimate and artisto. That's means we can apply CIFilter to UIView.
I have used SCRecorder library and try to get this task done by SCPlayer and SCFilterImageView. But i am facing black screen issue when video is playing after apply CIFilter. So kindly help me to complete this task so that i can apply CIFilter to UIView and also can change the filter by clicking on a UIButton.
The technically accurate answer is that a CIFilter requires a CIImage. You can turn a UIView into a UIImage and then convert that into a CIImage, but all CoreImage filters that use an image for input (there are some that generate a new image) use a `CIImage for input and output.
Please note that the origin for a CIImage is bottom left, not top left. Basically the Y axis is flipped.
If you use CoreImage filters dynamically, learn to use a GLKView to render in - it uses the GPU where a UIImageView uses the CPU.
If you want to test out a filter, it's best to use an actual device. The simulator will give you very poor performance. I've seen a simple blur take nearly a minute where on a device it will be a fraction of a second!
Let's say you have a UIView that you wish to apply a CIPhotoEffectMono to. The steps to do this would be:
Convert the UIView into a CIImage.
Apply the filter, getting a CIImage as output.
Use a CIContext to create a CGImage and then convert that to a UIImage.
Here's a UIView extension that will convert the view and all it's subviews into a UIImage:
extension UIView {
public func createImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(
CGSize(width: self.frame.width, height: self.frame.height), true, 1)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
Converting a UIImage into a CIImage is one line of code:
let ciInput = CIImage(image: myView.createImage)
Here's a function that will apply the filter and return a UIImage:
func convertImageToBW(image:UIImage) -> UIImage {
let filter = CIFilter(name: "CIPhotoEffectMono")
// convert UIImage to CIImage and set as input
let ciInput = CIImage(image: image)
filter?.setValue(ciInput, forKey: "inputImage")
// get output CIImage, render as CGImage first to retain proper UIImage scale
let ciOutput = filter?.outputImage
let ciContext = CIContext()
let cgImage = ciContext.createCGImage(ciOutput!, from: (ciOutput?.extent)!)
return UIImage(cgImage: cgImage!)
}

UIImage size doubled when converted to CGImage?

I am trying to crop part of an image taken with the iPhone's camera via the cropping(to:) method on a CGImage but I am encountering a weird phenomenon where my UIImage's dimensions are doubled when converted with .cgImage which, obviously, prevents me from doing what I want.
The flow is:
Picture is taken with the camera and goes into a full-screen imageContainerView
A "screenshot" of this imageContainerView is made with a UIView extension, effectively resizing the image to the container's dimensions
imageContainerView's .image is set to now be the "screenshot"
let croppedImage = imageContainerView.renderToImage()
imageContainerView.image = croppedImage
print(imageContainerView.image!.size) //yields (320.0, 568.0)
print(imageContainerView.image!.cgImage!.width, imageContainerView.image!.cgImage!.height) //yields (640, 1136) ??
extension UIView {
func renderToImage(afterScreenUpdates: Bool = false) -> UIImage {
let rendererFormat = UIGraphicsImageRendererFormat.default()
rendererFormat.opaque = isOpaque
let renderer = UIGraphicsImageRenderer(size: bounds.size, format: rendererFormat)
let snapshotImage = renderer.image { _ in
drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates)
}
return snapshotImage
}
}
I have been wandering around here with no success so far and would gladly appreciate a pointer or a suggestion on how/why the image size is suddenly doubled.
Thanks in advance.
This is because print(imageContainerView.image!.size) prints the size of the image object in points and print(imageContainerView.image!.cgImage!.width, imageContainerView.image!.cgImage!.height) print the size of the actual image in pixels.
On iPhone you are using there are 2 pixels for evert point in both horizontal and vertical. The UIImage scale property will give you the factor which in your case will be 2.
See this link iPhone Resolutions

how to render UIView over UIImageView in swift

I am looking for a way to render UIView over UIImageView on camera in swift. My problem is to capture only small rectangular portion of image.for this i tried by reducing the size of my UIImageView but in this case camera adjusted whole image in this small area which is not my objective.
Finally i decided to hide camera by rendering some other component over it from both side up/down, how can I do?
UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, 0)
view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

How can I add stickers to an image in Swift?

I'm working on a Swift iOS app where I want the user to be able to place an image (a sticker such as a beard or an eyepatch) over another image.
Currently I have it working to where they can take a photo or pull an image up from their Photos and have that display in a UIImage. Obviously next is adding the sticker. I've been able to dig up zero data on this from Google or Stack. And I mean zero.
Does anyone have a general idea of how I would execute this? Specifics would help too of course.
Here's the easy way.
have a UIView as a parent, let's say stickerView
add image to stickerView
add stickers to stickerView
save a snapshot of stickerView
Here's the code to snapshot UIView,
extension UIImage {
class func imageWithView(view: UIView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
Usage
let snapshotImage = UIImage.imageWithView(stickerView)
I would suggest you to add UIImageView for sticker instead of editing image when adding sticker. And after that when save the image then you should edit the image.

iOS UIImage: set image orientation without rotating the image itself

I am using AVCapture+camera portrait mode to capture an image. when I display the captured image, it is fine--looks fine. But when I convert to jpeg representation and then convert to base64 string to server and server stored it, it is "rotated" already.
So I checked the image orientation before sending to server: it is UIImageOrientation.Right(so is there any way to capture an image using portrait mode but the captured image orientation is up? well, I doubt that after some digging). After the server got the image, it did not do anything, just ignored the metadata about orientation I guess.
since the image I captured looks fine, I want just preserve how the image look like. However, I want to set the image orientation to be up. if I just set the image orientation, the image does not look right anymore.
So is there a way to set the orientation without causing the image to be rotated or after setting the orientation to be up, how to I keep the orientation but rotate the actual image to make it look right?
- (UIImage *)removeRotationForImage:(UIImage*)image {
if (image.imageOrientation == UIImageOrientationUp) return image;
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawInRect:(CGRect){0, 0, image.size}];
UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage;
}
swift version of oldrinmendez answer
func removeRotationForImage(image: UIImage) -> UIImage {
if image.imageOrientation == UIImageOrientation.Up {
return image
}
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
image.drawInRect(CGRect(origin: CGPoint(x: 0, y: 0), size: image.size))
let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return normalizedImage
}

Resources