punch a clear hole in a UIImage - swift

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

Related

Setting image quality using UIGraphicsPDFRenderer

Trying to add a Aztec barcode to a PDF using UIGraphicsPDFRenderer my issue is that the result is blurry thought the fix was setting interpolationQuality, Thanks for your help.
let renderer = UIGraphicsPDFRenderer(bounds: CGRect(x: 0, y: 0, width: 70.8661, height: 70.8661))
return renderer.pdfData{ ctx in
ctx.beginPage()
ctx.cgContext.interpolationQuality = .none //Doesn't do anything
let barcode = generateQRCode(from: UUID().description)
barcode.draw(in: CGRect(x: 0, y: 0, width: 70.8661, height: 70.8661))
}
func generateQRCode(from string: String) -> UIImage {
filter.message = Data(string.utf8)
if let outputImage = filter.outputImage {
if let cgimg = context.createCGImage(outputImage, from: outputImage.extent) {
return UIImage(cgImage: cgimg)
}
}
return UIImage()
}

Why App is Crashed when Change Uiimage Color

I Have Changed Color Of Uiimage But App is crashed. I do this code in a loop. I have Added Autoreleasepool but not solve my problem.
func withColor(_ color: UIColor) -> UIImage {
//this method is extendtion of UIImage
UIGraphicsBeginImageContextWithOptions(size, false, scale)
guard let ctx = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return self }
color.setFill()
ctx.translateBy(x: 0, y: size.height)
ctx.scaleBy(x: 1.0, y: -1.0)
ctx.clip(to: CGRect(x: 0, y: 0, width: size.width, height: size.height), mask: cgImage)
ctx.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
guard let colored = UIGraphicsGetImageFromCurrentImageContext() else { return self }
UIGraphicsEndImageContext()
return colored
}
func getImage() {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
for i in 0..<50{
let url = arrImages[i]
let elemetView = UIImageView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
elementView.imgVContent.image = UIImage(named: url)
if let imgColor = elementData.bgColor, imgColor != ""{
elementView.image = elementView.image?.withColor(UIColor(hexString: imgColor))
elementView.image.imgColor = UIColor(hexString: imgColor)
}
view.addSubview(elementView)
}
}
you have mentioned that you have used autorelease pool but I could not find it. May be trying using as below and see if it solves the problem.
In your getImage function, use your for loop with autoreleasepool like below.
for i in 0..<50{
autoreleasepool{
let url = arrImages[i]
let elemetView = UIImageView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
elementView.imgVContent.image = UIImage(named: url)
if let imgColor = elementData.bgColor, imgColor != ""{
elementView.image = elementView.image?.withColor(UIColor(hexString: imgColor))
elementView.image.imgColor = UIColor(hexString: imgColor)
}
view.addSubview(elementView)
}
}

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?

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
}

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.