Rendering image with textview - ios

I am placing a textview on a image. With following code:
var previewImageView=UIImageView()
self.previewImageView.frame = CGRect(x:0, y:0, width:UIScreen.mainScreen().bounds.width, height:UIScreen.mainScreen().bounds.height)
self.view.addSubview(self.previewImageView)
textField = UITextView(frame: CGRect(x: 0, y: self.view.bounds.height/2 - 50, width: self.view.bounds.width, height: 36))
textField.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
self.view.addSubview(textField)
It works well. But I want to render this image with textview. Then I will save it to gallery.
How can I do this?
Edit:
I tried following code but it is only rendering image not textview:
//Setup the image context using the passed image.
UIGraphicsBeginImageContext(inImage.size)
//Put the image into a rectangle as large as the original image.
inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))
// Creating a point within the space that is as bit as the image.
var rect: CGRect = CGRectMake(atPoint.x, atPoint.y, inImage.size.width, inImage.size.height)
//Now Draw the text into an image.
drawText.drawRect(rect)
// Create a new image out of the images we have created
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
// End the context now that we have the image we need
UIGraphicsEndImageContext()
//And pass it back up to the caller.
return newImage

You can render whole view into an UIImage using CGGraphicsContext. Here is an example of the code:
func imageWithView(view: UIView!) -> UIImage! {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
view.layer.renderInContext(UIGraphicsGetCurrentContext())
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
When you pass scale = 0.0 it will take a scale of your screen.
An example of usage:
let image = imageWithView(view)
Code to save image:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
More information about UIGraphicsContext and image saving can be found here.
Update:
If you want to render only specific views, then you should use CALayer, renderInContext. When you use renderInContext it does not know views.frame and draws at (0:0) in coordinate system, so you should use CGContextTranslateCTM to move coordinate system.
To render only these two views you can do:
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0)
let context = UIGraphicsGetCurrentContext()
CGContextTranslateCTM(context, previewImageView.frame.origin.x, previewImageView.frame.origin.y)
previewImageView.layer.renderInContext(context)
CGContextTranslateCTM(context, textField.frame.origin.x - previewImageView.frame.origin.x, textField.frame.origin.y - previewImageView.frame.origin.y)
textField.layer.renderInContext(context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Please set opaque true/false as you need. When I was testing in playground I was using not opaque views.
Update 2:
Code which should work in all scenarios:
func imageFromViews(views: [UIView]!, contextSize: CGSize!) -> UIImage {
UIGraphicsBeginImageContextWithOptions(contextSize, false, 0.0)
let context = UIGraphicsGetCurrentContext()
for view in views {
CGContextTranslateCTM(context, view.frame.origin.x, view.frame.origin.y)
view.layer.renderInContext(UIGraphicsGetCurrentContext())
CGContextTranslateCTM(context, -view.frame.origin.x, -view.frame.origin.y)
}
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}

Related

Set UIImage color

I am on swift 4, and my goal is to change the color of a system UIImage in code. I declare the image with
let defaultImage = UIImage(systemName: "person.circle.fill")
But when I change its tint color with:
let grayDefaultImage = defaultImage?.withTintColor(.gray)
The grayDefaultImage still display the standard blue color. Next I use an extension
//MARK: -UIImage extension
extension UIImage {
/// #Todo: this blurs the image for some reason
func imageWithColor(color: UIColor) -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
color.setFill()
let context = UIGraphicsGetCurrentContext()
context?.translateBy(x: 0, y: self.size.height)
context?.scaleBy(x: 1.0, y: -1.0)
context?.setBlendMode(CGBlendMode.normal)
let rect = CGRect(origin: .zero, size: CGSize(width: self.size.width, height: self.size.height))
context?.clip(to: rect, mask: self.cgImage!)
context?.fill(rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
And the image renders in a very "pixelated" or "low res" form.
withTintColor(_:) say: The new image uses the same rendering mode as the original image.
So if original image's rendering mode is .alwaysTemplate, means image will ignoring its color information. you need set mode to .alwaysOriginal:
defaultImage?.withTintColor(.gray, renderingMode: .alwaysOriginal)

Convert Square UIImage to round UIIMage for use with CAEmitterCell.contents

I have a custom UI component that produces an image of a round ball with some labels superimposed over top of it.
I am taking a snapshot of the component using the following UIView extension I found here on StackOverflow.
I am taking the resulting UIImage and using it in a CAEmitterCell.
My problem is that the snapshot image is square - my round ball on a white background. I would like the background to be clear when it is emitted but I can't seem to find a way to do it.
Is there any way I can modify the UIImage to make its corners transparent?
Thanks.
extension UIView {
/// Create snapshot
///
/// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted),
/// return snapshot of the whole view.
///
/// - returns: Returns `UIImage` of the specified portion of the view.
func snapshot(of rect: CGRect? = nil) -> UIImage? {
// snapshot entire view
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
drawHierarchy(in: bounds, afterScreenUpdates: true)
let wholeImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// if no `rect` provided, return image of whole view
guard let image = wholeImage, let rect = rect else { return wholeImage }
// otherwise, grab specified `rect` of image
let scale = image.scale
let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale)
guard let cgImage = image.cgImage?.cropping(to: scaledRect) else { return nil }
return UIImage(cgImage: cgImage, scale: scale, orientation: .up)
}
}
After figuring out how to word my question here, I thought of another way to search for my answer and found a solution.
Someone posted an extension to turn white backgrounds transparent as an answer to a previous question. White didn't work for me, but a simple edit and a name change made the extension work for black backgrounds instead of white.
extension UIImage {
func imageByMakingBlackBackgroundTransparent() -> UIImage? {
let image = UIImage(data: UIImageJPEGRepresentation(self, 1.0)!)!
let rawImageRef: CGImage = image.cgImage!
let colorMasking: [CGFloat] = [0, 0, 0, 0, 0, 0]
UIGraphicsBeginImageContext(image.size);
let maskedImageRef = rawImageRef.copy(maskingColorComponents: colorMasking)
UIGraphicsGetCurrentContext()?.translateBy(x: 0.0,y: image.size.height)
UIGraphicsGetCurrentContext()?.scaleBy(x: 1.0, y: -1.0)
UIGraphicsGetCurrentContext()?.draw(maskedImageRef!, in: CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height))
let result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result
}
}
My image was originally on a white background, but there was also white in the important part of the image. I temporarily changed my background to black, took a snapshot, then converted black to transparent, then changed my background back to white.
The end result is that my problem is fixed.
Thanks to anyone who took any time to read or think about this problem.

Partial Screenshot with Swift 3

I would like to make partial screenshot in my project.
However, I tried the output screenshot is not good that I want to be.
Here is my code.
let size = CGSize(width: 398, height: 300)
UIGraphicsBeginImageContextWithOptions(size, false, 0);
view.layer.render(in: UIGraphicsGetCurrentContext()!)
var sourceImage = UIGraphicsGetImageFromCurrentImageContext()
sourceImage?.draw(at: CGPoint(x: 0, y: 0))
var cropimage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(cropimage!,nil,nil,nil)
I would like to save only white View. If I set width and height, the output image is small and does not get completely.
Anyone help me please?
extend UIView and capture an image of that white view
// Untested
import UIKit
extension UIView {
func capture() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.frame.size, self.opaque, UIScreen.mainScreen().scale)
self.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
usage:
let whiteImage = myWhiteView.capture()

How apply and move a UIImageView layered above another UIImageView Swift3

i read here many guides how to create a new image merging two existing ones, using the UIGraphics and the layer.render methods for the two UIImageViews, and finally i can create an then save my new image. The problem is that i can't understand how to put the second UIImageView where i want, at the bottom for example. I 'll post now a image of an merged image and the function that my code run making this possible.
Captured merged photo
And here's my code that do the trick:
extension UIImage {
class func imageWithWatermark(image1: UIImageView, image2: UIImageView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(image1.bounds.size, false, 0.0)
let frame = image1.frame
image2.frame = CGRect(x: 0, y: frame.size.height * 0.80, width: frame.size.width, height: frame.size.height * 0.20 )
image1.layer.render(in: UIGraphicsGetCurrentContext()!)
image2.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
}
And then my func that saves the merged image:
func addWatermark() {
let newImage = UIImage.imageWithWatermark(image1: cameraPreview, image2: provaImage)
UIImageWriteToSavedPhotosAlbum(newImage, nil,nil,nil)
}
You can use this function which merge two images and the second will be replaces on bottom
func mergeTwoImageSeconInBottom(backgroundImage: UIImage, imageOnBottom: UIImage) -> UIImage {
let size = YOUR_CG_SIZE
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
backgroundImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
imageOnBottom.draw(at: CGPoint(x: (size.width - imageOnBottom.size.width) / 2, y: size.height - imageOnBottom.size.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}

I have a png file with no background, how can I create a clear color background for this image in iOS?

So I understand that a UIImage inherently doesn't have a background. As many of us know, a lot of PNG files don't have a background Color thus making it clear. I'm attempting to upload a png file that doesn't have a background color, thus a clear color. Yes, I know I can set the background Color myself in adobe or sketch, but I'm assuming that other users don't know how to do this.
Here is a screenshot of the png that I have created:
As you can see, it's just two lines that are unioned together so there's no background set.
Now below is a screenshot of the aftermath of using the imagePicker to choose this png image from my photo roll.
Notice that the area that is supposed to be transparent is actually black. I want to color in the black part and make it actually clearColor instead and keep the green cross as it is. Now, I'm not sure if the black color is actually even a black color because perhaps it's just empty space. Can I fill in the empty black space and turn it into a clear color?
Here's my code right now that isn't working very well:
func overlayImage(image: UIImage, color: UIColor) -> UIImage? {
let rect = CGRectMake(0, 0, image.size.width, image.size.height)
let backgroundView = UIView(frame: rect)
backgroundView.backgroundColor = color
UIGraphicsBeginImageContext(rect.size)
let gcSize: CGSize = backgroundView.frame.size
UIGraphicsBeginImageContext(gcSize)
let context: CGContextRef = UIGraphicsGetCurrentContext()!
backgroundView.layer.renderInContext(context)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
Any help in either obj-C or Swift would be greatly appreciated.
I got rid of the overlay method above and am using the code below:
Updated with new code that still doesn't work
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
scaleImage(overlayImage(image, color: UIColor.clearColor()))
}
func scaleImageAndAddAugmented(image: UIImage?) {
let rect = CGRectMake(0, 0, image!.size.width, image!.size.height)
let backgroundView = UIView(frame: rect)
backgroundView.backgroundColor = UIColor.clearColor()
let size = CGSizeApplyAffineTransform(image!.size, CGAffineTransformMakeScale(0.25, 0.25))
let hasAlpha = false
let scale: CGFloat = 0.0
UIGraphicsBeginImageContextWithOptions(size, !hasAlpha, scale)
image!.drawInRect(CGRect(origin: CGPointZero, size: size))
let context = CGBitmapContextCreate(nil, Int(image!.size.width), Int(image!.size.height), 8, 0, CGColorSpaceCreateDeviceRGB(), CGImageAlphaInfo.PremultipliedLast.rawValue)
let myGeneratedImage = CGBitmapContextCreateImage(context)
CGContextDrawImage(context, rect, myGeneratedImage)
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.dismissViewControllerAnimated(true, completion: nil)
// set image below
}
It seems a bit of excess work to use UIGraphicsGetImageFromCurrentImageContext to generate an image from context, when you can just create an image from a file.
As first mentioned it is required to have Opaque = NO:
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
My bet is its the image itself, because the whole thing is faded.
Make 100% certain that the passed colour is a clear colour for:
backgroundView.backgroundColor = color
You could create a bitmap context and use that instead:
CGContextRef context = CGBitmapContextCreate(NULL,
width,
height,
8,
0,
rgbColorSpace,
kCGImageAlphaPremultipliedLast);
Rather than using the current context and you can use:
myGeneratedImage = CGBitmapContextCreateImage(context)
Drawing is easy as pie:
CGContextDrawImage(realContext,bounds,myGeneratedImage)
Swift code below:
func scaleImage(image: UIImage?) {
if let image = image {
let rect = CGRectMake(0, 0, image.size.width, image.size.height)
let size: CGSize = CGSizeApplyAffineTransform(image.size, CGAffineTransformMakeScale(0.25, 0.25))
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
image.drawInRect(CGRect(origin: CGPointZero, size: size))
let context = CGBitmapContextCreate(nil, Int(image.size.width), Int(image.size.height), 8, 0, CGColorSpaceCreateDeviceRGB(), CGImageAlphaInfo.PremultipliedLast.rawValue)
let myGeneratedImage = CGBitmapContextCreateImage(context)
CGContextDrawImage(context, rect, myGeneratedImage)
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}

Resources