IOS: When saving masked image, original image is saved? - ios

I am masking an image using an image_mask, the following code shows that:
func maskOriginalImage() -> UIImage? {
if(self.maskImage != nil && self.originalImage != nil){
let maskReference = self.maskImage?.cgImage!
let maskedReference = self.originalImage?.cgImage!.masking(maskReference!)
self.maskImage = nil
return UIImage(cgImage: maskedReference!)
}
return nil
Now I want to save the masked image to photo library.
func saveImageToLibrary(){
UIImageWriteToSavedPhotosAlbum(self.segmentedimage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}
But while saving the maskedImage, original image is saved. The workaround I found is to create a new UIimagecontext and draw the maskedimage in the context and use that image to save.
func getImageFromContext() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(self.size, false, scale)
draw(in: CGRect(origin: .zero, size: size))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
Why I just can't save the masked image directly? I am relatively new to IOS development so any inputs will be helpful.

Related

UIGraphicsImageRenderer mirrors image after applying filter

I'm trying to apply filters on images.
Applying the filter works great, but it mirrors the image vertically.
The bottom row of images calls the filter function after init.
The main image at the top, gets the filter applied after pressing on one at the bottom
The ciFilter is CIFilter.sepiaTone().
func applyFilter(image: UIImage) -> UIImage? {
let rect = CGRect(origin: CGPoint.zero, size: image.size)
let renderer = UIGraphicsImageRenderer(bounds: rect)
ciFilter.setValue(CIImage(image: image), forKey: kCIInputImageKey)
let image = renderer.image { context in
let ciContext = CIContext(cgContext: context.cgContext, options: nil)
if let outputImage = ciFilter.outputImage {
ciContext.draw(outputImage, in: rect, from: rect)
}
}
return image
}
And after applying the filter twice, the new image gets zoomed in.
Here are some screenshots.
You don't need to use UIGraphicsImageRenderer.
You can directly get the image from CIContext.
func applyFilter(image: UIImage) -> UIImage? {
ciFilter.setValue(CIImage(image: image), forKey: kCIInputImageKey)
guard let ciImage = ciFilter.outputImage else {
return nil
}
let outputCGImage = CIContext().createCGImage(ciImage, from: ciImage.extent)
guard let _ = outputCGImage else { return nil }
let filteredImage = UIImage(cgImage: outputCGImage!, scale: image.scale, orientation: image.imageOrientation)
return filteredImage
}

How can I get screenshot of view including sublayer?

I am using code below, but it doesn't include my sublayer
//Create the UIImage
UIGraphicsBeginImageContext(self.localVideoView!.frame.size)
self.localVideoView!.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//Save it to the camera roll
UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
Use this extension:
extension UIView {
var screenShot: UIImage {
return UIGraphicsImageRenderer(size: bounds.size).image { _ in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
}
usage:
guard let image = yourView.screenShot.pngData() else { return }
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
naturally add to your info.plist Privacy - Photo Library Additions Usage Description and Privacy and Photo Library Usage Description

How to create monochromatic UIImage on iOS

I have a UIImage coming from server that I need to present in the UI as a monochromatic image with a given single color that can be an arbitrary as well. What's the best way to achieve it?
In my current method I am using following method that returns a monochromatic image for a given image and a color:
fileprivate func monochromaticImage(from image: UIImage, in color: UIColor) -> UIImage {
guard let img = CIImage(image: image) else {
return image
}
let color = CIColor(color: color)
guard let outputImage = CIFilter(name: "CIColorMonochrome",
withInputParameters: ["inputImage" : img,
"inputColor" : color])?.outputImage else {
return image
}
let context = CIContext()
if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
let newImage = UIImage(cgImage: cgImage, scale: image.scale, orientation: image.imageOrientation)
return newImage
}
return image
}

Why base64 renditions of images are white in swift 3?

I have converted my images with this codes below and this will return base64 of my images but the problem is that when I upload them into the server I just see the white image - can you suggest me the better way to convert images to base64 or this is the best way that I choose
here is the converting image to base64
func base64(from image: UIImage) -> String? {
UIGraphicsBeginImageContext(image.size)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let imageData = UIImageJPEGRepresentation(image!, 1.0)
if let imageString = imageData?.base64EncodedString(options: .endLineWithLineFeed) {
return imageString
}
return nil
}
Try this method:
func convertImageToBase64(_ image:UIImage) -> String
{
let imageData = UIImageJPEGRepresentation(image, 1)//get imageData from image
if(imageData != nil)
{
let Strbase64 = imageData?.base64EncodedString(options: .endLineWithCarriageReturn)//encode imageData
return Strbase64!//return encoded string
}
return ""
}
You passed a UIImage to this method, but never did anything with it, but rather created a new UIImage using UIGraphicsGetImageFromCurrentImageContext, but you never drew anything to that context. That's why the resulting images are white.
But you don't need those UIGraphics calls at all. Just grab the JPEG representation of the UIImage that you passed into this method, and convert it to a base 64 encoded string:
func convertImageToBase64(_ image: UIImage) -> String? {
return UIImageJPEGRepresentation(image, 1)?.base64EncodedString()
}
It is white because nothing is drawn on current context !!!
You are just UIGraphicsBeginImageContext with size
and get with UIGraphicsGetImageFromCurrentImageContext
it will always gives you a white image and there is no relation with Base64
If you want to render something then use like below
yourImageView.layer.render(in: UIGraphicsGetCurrentContext()!)
and after that fetch image from currentContext
EDIT
func base64(from image: UIImage) -> String? {
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let imageData = UIImageJPEGRepresentation(image!, 1.0)
if let imageString = imageData?.base64EncodedString(options: .endLineWithLineFeed) {
return imageString
}
return nil
}
First check wether the error you are facing is from your app or server side .You can choose online base64 to image converter .Copy your base64 String and check them first , you can choose this link
https://codebeautify.org/base64-to-image-converter

SWIFT 3 - CGImage to PNG

I am trying to use a color mask to make a color in JPG image transparent because as I read, color mask only works with JPG.
This code work when I apply the color mask and save the image as a JPG, but as a JPG, there is no transparency so I want to transform the JPG image to a PNG image to keep the transparency but when I try to do it, the color mask doesn't work.
Am I doing something wrong or maybe this isn't the right approach.
Here is the code of the 2 functions :
func callChangeColorByTransparent(_ sender: UIButton){
var colorMasking: [CGFloat] = []
if let textLabel = sender.titleLabel?.text {
switch textLabel {
case "Remove Black":
colorMasking = [0,30,0,30,0,30]
break
case "Remove Red":
colorMasking = [180,255,0,50,0,60]
break
default:
colorMasking = [222,255,222,255,222,255]
}
}
print(colorMasking)
let newImage = changeColorByTransparent(selectedImage, colorMasking: colorMasking)
symbolImageView.image = newImage
}
func changeColorByTransparent(_ image : UIImage, colorMasking : [CGFloat]) -> UIImage {
let rawImage: CGImage = (image.cgImage)!
//let colorMasking: [CGFloat] = [222,255,222,255,222,255]
UIGraphicsBeginImageContext(image.size)
let maskedImageRef: CGImage = rawImage.copy(maskingColorComponents: colorMasking)!
if let context = UIGraphicsGetCurrentContext() {
context.draw(maskedImageRef, in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
var newImage = UIImage(cgImage: maskedImageRef, scale: image.scale, orientation: image.imageOrientation)
UIGraphicsEndImageContext()
var pngImage = UIImage(data: UIImagePNGRepresentation(newImage)!, scale: 1.0)
return pngImage!
}
print("fail")
return image
}
Thank for your help.
Thanks the issue of DonMag in my other question SWIFT 3 - CGImage copy always nil, here is the code to solve this :
func saveImageWithAlpha(theImage: UIImage, destFile: URL) -> Void {
// odd but works... solution to image not saving with proper alpha channel
UIGraphicsBeginImageContext(theImage.size)
theImage.draw(at: CGPoint.zero)
let saveImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
if let img = saveImage, let data = UIImagePNGRepresentation(img) {
try? data.write(to: destFile)
}
}

Resources