Use emoji for UIImage [duplicate] - swift

I'm currently developing a simple photoshop like application on iphone. When I want to flatten my layers, the labels are at the good position but with a bad font size.
Here's my code to flatten :
UIGraphicsBeginImageContext(CGSizeMake(widthDocument,widthDocument));
for (UILabel *label in arrayLabel) {
[label drawTextInRect:label.frame];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Anybody can help me ?

From: pulling an UIImage from a UITextView or UILabel gives white image.
// iOS
- (UIImage *)grabImage {
// Create a "canvas" (image context) to draw in.
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0); // high res
// Make the CALayer to draw in our "canvas".
[[self layer] renderInContext: UIGraphicsGetCurrentContext()];
// Fetch an UIImage of our "canvas".
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// Stop the "canvas" from accepting any input.
UIGraphicsEndImageContext();
// Return the image.
return image;
}
// Swift extension w/ usage. credit #Heberti Almeida in below comments
extension UIImage {
class func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
The usage:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)

I have created a Swift extension to render the UILabel into a UIImage:
extension UIImage {
class func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
EDIT: Improved Swift 4 version
extension UIImage {
class func imageWithLabel(_ label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0)
defer { UIGraphicsEndImageContext() }
label.layer.render(in: UIGraphicsGetCurrentContext()!)
return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
}
}
The usage is simple:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)

you need to render the label in a context
replace
[label drawTextInRect:label.frame];
with
[label.layer renderInContext:UIGraphicsGetCurrentContext()];
and you will need to create one image per label, so move the for loop to outside the begin and end context calls

for Swift, I use this UIView-extension:
// Updated for Swift 3.0
extension UIView {
var grabbedImage:UIImage? {
get {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0.0)
layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
}

You can use renderInContext on any CALayer. It will draw your view's layer on the context. So that you can change it to an image. Also if you do renderInContext on a view , all its subviews will be drawn onto the context. So instead of iterating through all the labels, while adding the labels, you can add those to a containerView. And just need to do renderInContext on that containerView.

extension UIImage {
class func imageFrom(text: String, width: CGFloat, font: UIFont, textAlignment: NSTextAlignment, lineBreakMode: NSLineBreakMode) -> UIImage? {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.text = text
label.font = font
label.textAlignment = textAlignment
label.lineBreakMode = lineBreakMode
label.sizeToFit()
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
Using:
let iv = UIImageView(image: UIImage.imageFrom(text: "Test For \nYarik", width: 537.0, font: UIFont.systemFont(ofSize: 30), textAlignment: .center, lineBreakMode: .byWordWrapping))
iv.contentMode = .scaleAspectFit

Related

Adding TextViews over UIImage - Swift - Programmatically

I have a camera which provides me UIImage with resolution of 1920x1080, I have implemented a system where I can add UITextViews as subviews and my goal is to add them to the original UIImage and export a final Image of the resolution of 1920x1080.
So the procedure I have been thinking about is this:
I add upperView over view.frame which is responsible of drawing all the textViews present on screen.
Then I want to add this view over the original UIImage scaling it proportionally
This is the code I implemented in order to do it:
func passingAndDrawingTextViews(textViews : [UITextView], viewPassed : UIView, inImage : UIImage) -> UIImage{
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(viewPassed.frame.size, false, scale)
viewPassed.draw(CGRect(x: 0, y: 0, width: viewPassed.frame.width, height: viewPassed.frame.height))
//adding each textView
textViews.forEach { (textView) in
let textColor = textView.textColor
let textFont = UIFont(name: textView.font!.fontName, size: textView.font!.pointSize)
let textAlignment = textView.textAlignment
//alignment of the text
let paragraphStyle: NSMutableParagraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = textAlignment
let textFontAttributes = [
NSAttributedString.Key.font: textFont,
NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.paragraphStyle : paragraphStyle,
]
let rect = CGRect(x: textView.frame.minX + textView.textContainer.lineFragmentPadding, y: textView.frame.minY + textView.textContainerInset.top, width: textView.frame.width, height: textView.frame.height)
textView.text.draw(in: rect, withAttributes: textFontAttributes as [NSAttributedString.Key : Any])
}
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIGraphicsBeginImageContext(inImage.size)
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
inImage.draw(in: CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height))
newImage!.draw(in: rect)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}
In the function I respectively pass the list of textViews, the upperView, and the originalImage.
But the problem is that the textView I get are stretched on the x axis. I don't know why this happens.
What I get:
What I want
the rect you are passing in this line :
newImage!.draw(in: rect)
is actually the size of screen it self so the image will strech to fill this rect.
so make this :
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
the size of the image you are passing in.

punch a clear hole in a UIImage

I'm trying to have a transperant hole in a uiimage This is what I found so far:
let hole = CGRect(x: 0, y: 0, width: 50, height: 50)
let context = UIGraphicsGetCurrentContext()!
context.clear(hole)
myImage.image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
but I get nil at : let context = UIGraphicsGetCurrentContext()!
I understand that I need to define current context somewhere but I'm not sure where and how
You need to have a context available to draw with. Create one explicitly with UIGraphicsBeginImageContext, and when you are done drawing, call UIGraphicsEndImageContext to clean it up.
Here your code, with the call to UIGraphicsBeginImageContext, wrapped in an extension method:
extension UIImage {
func imageWithHole(at rect: CGRect) -> UIImage? {
UIGraphicsBeginImageContext(self.size)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
self.draw(at: CGPoint.zero)
context.clear(rect)
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
}
Use it like this:
let sourceImage = UIImage(named: "sample.jpg")
let imageWithHole = sourceImage?.imageWithHole(at: CGRect(x: 50, y: 50, width: 50, height: 50))

Emoji to UIImage for use on slider.setThumbImage [duplicate]

I'm currently developing a simple photoshop like application on iphone. When I want to flatten my layers, the labels are at the good position but with a bad font size.
Here's my code to flatten :
UIGraphicsBeginImageContext(CGSizeMake(widthDocument,widthDocument));
for (UILabel *label in arrayLabel) {
[label drawTextInRect:label.frame];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Anybody can help me ?
From: pulling an UIImage from a UITextView or UILabel gives white image.
// iOS
- (UIImage *)grabImage {
// Create a "canvas" (image context) to draw in.
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0); // high res
// Make the CALayer to draw in our "canvas".
[[self layer] renderInContext: UIGraphicsGetCurrentContext()];
// Fetch an UIImage of our "canvas".
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// Stop the "canvas" from accepting any input.
UIGraphicsEndImageContext();
// Return the image.
return image;
}
// Swift extension w/ usage. credit #Heberti Almeida in below comments
extension UIImage {
class func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
The usage:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)
I have created a Swift extension to render the UILabel into a UIImage:
extension UIImage {
class func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
EDIT: Improved Swift 4 version
extension UIImage {
class func imageWithLabel(_ label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0)
defer { UIGraphicsEndImageContext() }
label.layer.render(in: UIGraphicsGetCurrentContext()!)
return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
}
}
The usage is simple:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)
you need to render the label in a context
replace
[label drawTextInRect:label.frame];
with
[label.layer renderInContext:UIGraphicsGetCurrentContext()];
and you will need to create one image per label, so move the for loop to outside the begin and end context calls
for Swift, I use this UIView-extension:
// Updated for Swift 3.0
extension UIView {
var grabbedImage:UIImage? {
get {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0.0)
layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
}
You can use renderInContext on any CALayer. It will draw your view's layer on the context. So that you can change it to an image. Also if you do renderInContext on a view , all its subviews will be drawn onto the context. So instead of iterating through all the labels, while adding the labels, you can add those to a containerView. And just need to do renderInContext on that containerView.
extension UIImage {
class func imageFrom(text: String, width: CGFloat, font: UIFont, textAlignment: NSTextAlignment, lineBreakMode: NSLineBreakMode) -> UIImage? {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.text = text
label.font = font
label.textAlignment = textAlignment
label.lineBreakMode = lineBreakMode
label.sizeToFit()
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
Using:
let iv = UIImageView(image: UIImage.imageFrom(text: "Test For \nYarik", width: 537.0, font: UIFont.systemFont(ofSize: 30), textAlignment: .center, lineBreakMode: .byWordWrapping))
iv.contentMode = .scaleAspectFit

How can I add a watermark to an image using this code?

I know there are several other ways to do this; I don't want to import anything that I don't need to. If someone can help me with his code, that would be great.
Currently, it is only saving the original image without the watermark image.
extension UIImage {
class func imageWithWatermark(image1: UIImageView, image2: UIImageView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(image1.bounds.size, false, 0.0)
image2.layer.renderInContext(UIGraphicsGetCurrentContext()!)
image1.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
func addWatermark() {
let newImage = UIImage.imageWithWatermark(imageView, image2: watermarkImageView)
UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil)
}
EDIT: I've got the watermark appearing on the saved images.
I had to switch the order of the layers:
image1.layer.renderInContext(UIGraphicsGetCurrentContext()!)
image2.layer.renderInContext(UIGraphicsGetCurrentContext()!)
HOWEVER, it is not appearing in the correct place.It seems to always appear in the center of the image.
If you grab the UIImageViews' images you could use the following concept:
if let img = UIImage(named: "image.png"), img2 = UIImage(named: "watermark.png") {
let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
UIGraphicsBeginImageContextWithOptions(img.size, true, 0)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextFillRect(context, rect)
img.drawInRect(rect, blendMode: .Normal, alpha: 1)
img2.drawInRect(CGRectMake(x,y,width,height), blendMode: .Normal, alpha: 1)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(result, nil, nil, nil)
}
SWIFT 4
Use this
let backgroundImage = imageData!
let watermarkImage = #imageLiteral(resourceName: "jodi_url_icon")
let size = backgroundImage.size
let scale = backgroundImage.scale
UIGraphicsBeginImageContextWithOptions(size, false, scale)
backgroundImage.draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
watermarkImage.draw(in: CGRect(x: 10, y: 10, width: size.width, height: size.height - 40))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Use result to UIImageView, tested.

iPhone, how does one overlay one image onto another to create a new image to save? (watermark)

Basically I want to take an image that the user chooses from their photo library and then apply a watermark, a triangle in the lower right that has the app name on it. I have the second image already made with a transparent layer in photoshop.
I tried a function, which I can't remember the exact name, but it involved CGIImages and masks. This combines the two images, but as a mask, which made the image darker where the transparent layer was and the images were not merged per se, just masked.
How would I get the watermark image to merge with another image, to make a UIImage, without displaying the images on the screen?
Thank you.
It's pretty easy:
UIImage *backgroundImage = [UIImage imageNamed:#"image.png"];
UIImage *watermarkImage = [UIImage imageNamed:#"watermark.png"];
UIGraphicsBeginImageContext(backgroundImage.size);
[backgroundImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
[watermarkImage drawInRect:CGRectMake(backgroundImage.size.width - watermarkImage.size.width, backgroundImage.size.height - watermarkImage.size.height, watermarkImage.size.width, watermarkImage.size.height)];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
If you want the background and watermark to be of the same size then use this code
...
[backgroundImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
[watermarkImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
...
The solution provided by omz also works in Swift, like so:
let backgroundImage = UIImage(named: "image.png")!
let watermarkImage = UIImage(named: "watermark.png")!
UIGraphicsBeginImageContextWithOptions(backgroundImage.size, false, 0.0)
backgroundImage.draw(in: CGRect(x: 0.0, y: 0.0, width: backgroundImage.size.width, height: backgroundImage.size.height))
watermarkImage.draw(in: CGRect(x: backgroundImage.size.width - watermarkImage.size.width, y: backgroundImage.size.height - watermarkImage.size.height, width: watermarkImage.size.width, height: watermarkImage.size.height))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
SWIFT 4
let backgroundImage = imageData!
let watermarkImage = #imageLiteral(resourceName: "jodi_url_icon")
UIGraphicsBeginImageContextWithOptions(backgroundImage.size, false, 0.0)
backgroundImage.draw(in: CGRect(x: 0.0, y: 0.0, width: backgroundImage.size.width, height: backgroundImage.size.height))
watermarkImage.draw(in: CGRect(x: 10, y: 10, width: watermarkImage.size.width, height: backgroundImage.size.height - 40))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.imgaeView.image = result
Use result to UIImageView, tested.
You can use this method, which is very dynamic and you can specify the starting position of the second image and total size of the image.
-(UIImage *) addImageToImage:(UIImage *)img withImage2:(UIImage *)img2 andRect:(CGRect)cropRect withImageWidth:(int) width{
CGSize size = CGSizeMake(width,40);
UIGraphicsBeginImageContext(size);
CGPoint pointImg1 = CGPointMake(0,0);
[img drawAtPoint:pointImg1];
CGPoint pointImg2 = cropRect.origin;
[img2 drawAtPoint: pointImg2];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
SWIFT 5 Function:
func addWaterMark(image: UIImage) -> UIImage {
let backgroundImage = image//UIImage(named: "image.png")
let watermarkImage = UIImage(named: "waterMark.png")
UIGraphicsBeginImageContextWithOptions(backgroundImage.size, false, 0.0)
backgroundImage.draw(in: CGRect(x: 0.0, y: 0.0, width: backgroundImage.size.width, height: backgroundImage.size.height))
watermarkImage!.draw(in: CGRect(x: backgroundImage.size.width - watermarkImage!.size.width, y: backgroundImage.size.height - watermarkImage!.size.height, width: watermarkImage!.size.width, height: watermarkImage!.size.height))
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result!
}