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

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.

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))

Image in NSTextAttachment too big and blurry

I'm trying to place an icon (in form of an image) next to a text in a UILabel. The icons are imported into the assets in al three sizes and are not blurry at all when I simply place them in a normal UIImageView.
However, within the NSTextAttachment they suddenly become extremely blurry and are too big, as well.
I already tried several things on my own and also tried nearly every snippet I could find online - nothing helps. This is what I'm left over with:
func updateWinnableCoins(coins: Int){
let attachImg = NSTextAttachment()
attachImg.image = resizeImage(image: #imageLiteral(resourceName: "geld"), targetSize: CGSize(width: 17.0, height: 17.0))
attachImg.setImageHeight(height: 17.0)
let imageOffsetY:CGFloat = -3.0;
attachImg.bounds = CGRect(x: 0, y: imageOffsetY, width: attachImg.image!.size.width, height: attachImg.image!.size.height)
let attchStr = NSAttributedString(attachment: attachImg)
let completeText = NSMutableAttributedString(string: "")
let tempText = NSMutableAttributedString(string: "You can win " + String(coins) + " ")
completeText.append(tempText)
completeText.append(attchStr)
self.lblWinnableCoins.textAlignment = .left;
self.lblWinnableCoins.attributedText = completeText;
}
func resizeImage(image: UIImage, targetSize: CGSize) -> (UIImage) {
let newRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height).integral
UIGraphicsBeginImageContextWithOptions(targetSize, false, 0)
let context = UIGraphicsGetCurrentContext()
// Set the quality level to use when rescaling
context!.interpolationQuality = CGInterpolationQuality.default
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: targetSize.height)
context!.concatenate(flipVertical)
// Draw into the context; this scales the image
context?.draw(image.cgImage!, in: CGRect(x: 0.0,y: 0.0, width: newRect.width, height: newRect.height))
let newImageRef = context!.makeImage()! as CGImage
let newImage = UIImage(cgImage: newImageRef)
// Get the resized image from the context and a UIImage
UIGraphicsEndImageContext()
return newImage
}
extension NSTextAttachment {
func setImageHeight(height: CGFloat) {
guard let image = image else { return }
let ratio = image.size.width / image.size.height
bounds = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: ratio * height, height: height)
}
}
And this is how it looks:
The font size of the UILabel is 17, so I set the text attachment to be 17 big, too. When I set it to 9, it fits, but it's still very blurry.
What can I do about that?

How to make UItabbar image rounded in swift programmatically

I want to create something like image as below
could you help me any code how to make it rounded
thanks for your help!
I think you need to
(Optional) Resize the image if image is bigger than standard bar button image size)
Make the image round
before using it as UItabBarItem image. Below is an extension for UIImage with these two functions:
extension UIImage{
var roundedImage: UIImage {
let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.size)
UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
UIBezierPath(
roundedRect: rect,
cornerRadius: self.size.height
).addClip()
self.draw(in: rect)
return UIGraphicsGetImageFromCurrentImageContext()!
}
func resizedImage(newWidth: CGFloat) -> UIImage {
let scale = newWidth / self.size.width
let newHeight = self.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
self.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
Example usage:
let barImage: UIImage = UIImage(named: "avatar_copy.png")!.resizedImage(newWidth: 40).roundedImage.withRenderingMode(.alwaysOriginal)
let roundTabBar = UITabBarItem(title: nil, image: barImage.withRenderingMode(.alwaysOriginal), selectedImage: barImage)
self.bottomTabbar.items = [roundTabBar]
I changed and added a new function to #firstinq answer. And this way works for me.
extension UIImage{
var roundMyImage: UIImage {
let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.size)
UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
UIBezierPath(
roundedRect: rect,
cornerRadius: self.size.height
).addClip()
self.draw(in: rect)
return UIGraphicsGetImageFromCurrentImageContext()!
}
func resizeMyImage(newWidth: CGFloat) -> UIImage {
let scale = newWidth / self.size.width
let newHeight = self.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
self.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
func squareMyImage() -> UIImage {
UIGraphicsBeginImageContext(CGSize(width: self.size.width, height: self.size.width))
self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.width))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
In TabBarController I changed it to:
let barImage: UIImage = UIImage(named: "landingpage_image2")!.squareMyImage().resizeMyImage(newWidth: 40).roundMyImage.withRenderingMode(.alwaysOriginal)
self.tabBar.items?[1].image = barImage
let profileImg : UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.image = #imageLiteral(resourceName: "user")
iv.clipsToBounds = true
iv.layer.cornerRadius = 25
return iv
}()
// add constraint
override func viewDidLoad() {
super.viewDidLoad()
profileImg.leftAnchor.constraint(equalTo: view.leftAnchor, constant : 8).isActive = true
profileImg.topAnchor.constraint(equalTo: view.topAnchor , constant : 8).isActive = true
profileImg.widthAnchor.constraint(equalToConstant: 50).isActive = true
profileImg.heightAnchor.constraint(equalToConstant: 50).isActive = true
}

Change the Size of Marker in GoogleMap using Swift

I have placed a marker in GoogleMap which contains Image. but the size of image is much bigger. so how can i decrease the size of an marker. i have tried this :
marker.icon = self.image(marker.icon, scaledToSize: CGSize(width: 3.0, height: 3.0))
To resize the image refer to :The simplest way to resize an UIImage?
Now the set the resized image as marker icon ,i.e,
marker.icon = self.imageWithImage(image: UIImage(named: "imageName")!, scaledToSize: CGSize(width: 3.0, height: 3.0))
Edit:
func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
Edit (swift 4)
func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
If you want to use an extension you can implement like this:
Swift 4.2
extension GMSMarker {
func setIconSize(scaledToSize newSize: CGSize) {
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
icon?.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
icon = newImage
}
}
and use the extension like This:
let position = CLLocationCoordinate2D(latitude: yourLatitude,longitude: yourLongitude)
let marker = GMSMarker(position: position)
marker.title = "Receiver"
marker.icon = UIImage(named: "receiver_set")
marker. setIconSize(scaledToSize: .init(width: 40, height: 40))
marker.map = self.mapView
Based in the answer of #PGDev
My implementation for Swift 3 is:
func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
//image.draw(in: CGRectMake(0, 0, newSize.width, newSize.height))
image.draw(in: CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: newSize.width, height: newSize.height)) )
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
And used in this way:
marker.icon = self.imageWithImage(image: UIImage(named: place.icon)!, scaledToSize: CGSize(width: 100.0, height: 100.0))
Another easy way is to use the new UIGraphicsImageRenderer
marker.icon = UIGraphicsImageRenderer(size: .init(width: 3.0, height: 3.0)).image { context in
UIImage(named: "pin").draw(in: .init(origin: .zero, size: context.format.bounds.size))
}
you can override this callback when camera position changed
func mapView(_ mapView: GMSMapView, idleAt cameraPosition: GMSCameraPosition) {
self.mapView?.clear()
//redraw your marker use smaller UIImage...
....
var smallerImage : UIImage = UIImage(named: "example_icon")
marker.icon = smallerImage
}