Argument labels do not match any available overloads swift - swift

i have a function which draw text on image but issue is when i call this function it gives a error "Argument labels '(_:, _:)' do not match any available overloads"
i am new to swift and dont know how to fix
func write_text_on_image(drawtext text:NSString , inimage img : UIImage , atpoint point : CGPoint) -> UIImage {
let textcolor = UIColor.white
let font = UIFont(name: "Helvetica", size: 16)
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(img.size, false, scale)
let font_attributes = [
kCTFontAttributeName : font,
kCTForegroundColorAttributeName : textcolor
]
img.draw(in: CGRect(origin: CGPoint.zero, size: img.size))
let rect = CGRect(origin: point, size: img.size)
text.draw(in: rect, withAttributes: font_attributes as [NSAttributedString.Key : Any])
let newimg = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndPDFContext()
return newimg!
}
i am calling this func as
write_text_on_image(drawtext: "THis is some text", inimage: UIImage(named: "test.png")!, atpoint: CGPoint(20,20))[!
check out screen of function []1

As #vadian said, code completion would help you. This is what I got from duplicating a fragment in Playground:
func write_text_on_image(drawtext text:NSString , inimage img : UIImage , atpoint point : CGPoint) -> UIImage { return UIImage() }
write_text_on_image(drawtext: "NSString", inimage: UIImage(), atpoint: CGPoint(x: 0, y: 0))
Doesn't do anything, but compiles.

CGPoint(x,y) pass perameter as CGPoint(x : value,y ; value)

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.

How do I add text to my MKOverLayRenderer

I am trying to build a custom MKOverlayRenderer subclass which will display an image and text presented on top of some type of subview based on this answer. At my current stage of implementing this I have gotten the image to appear on the map but now I am trying to add text over the image.
The text is appearing upside down and flipped on top of the image. The image appears to be oriented correctly using the same rectangle and same context. What am I doing wrong how do I go about implementing this?
This is the code pertaining to drawing the text:
UIGraphicsPushContext(context);
// ...
UIGraphicsPushContext(context);
UIColor.black.setStroke()
context.setLineWidth(1)
context.stroke(rect.insetBy(dx: 0.5, dy: 0.5))
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let attributes = [NSAttributedString.Key.paragraphStyle : paragraphStyle,
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 100.0),
NSAttributedString.Key.foregroundColor : UIColor.black]
"\(rect.size)".draw(in: rect, withAttributes: attributes)
UIGraphicsPopContext();
Class in its Entirety
class CustomOverlayView:MKOverlayRenderer{
var overlayImage:UIImage
init(overlay:MKOverlay,image:UIImage){
self.overlayImage = #imageLiteral(resourceName: "DSC00042")
super.init(overlay: overlay)
}
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
super.draw(mapRect, zoomScale: zoomScale, in: context)
guard let imageReference = overlayImage.cgImage else { return }
var rect = self.rect(for: overlay.boundingMapRect)
context.scaleBy(x: 1.0, y: -1.0)
context.translateBy(x: 0.0, y: -rect.size.height)
context.draw(imageReference, in: rect)
UIGraphicsPushContext(context);
// ...
UIGraphicsPushContext(context);
UIColor.black.setStroke()
context.setLineWidth(1)
context.stroke(rect.insetBy(dx: 0.5, dy: 0.5))
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let attributes = [NSAttributedString.Key.paragraphStyle : paragraphStyle,
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 100.0),
NSAttributedString.Key.foregroundColor : UIColor.black]
"\(rect.size)".draw(in: rect, withAttributes: attributes)
UIGraphicsPopContext();
}
}

NSImage Getting Resized when I draw Text on it

I have the following code to draw a text over an NSImage.
But the resulting image is getting resized to smaller one when I save it to disk.
What i'm i doing wrong? Please advice
func drawText(image :NSImage) ->NSImage
{
let text = "Sample Text"
let font = NSFont.boldSystemFont(ofSize: 18)
let imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
let textRect = CGRect(x: 5, y: 5, width: image.size.width - 5, height: image.size.height - 5)
let textStyle = NSMutableParagraphStyle.default().mutableCopy() as! NSMutableParagraphStyle
let textFontAttributes = [
NSFontAttributeName: font,
NSForegroundColorAttributeName: NSColor.white,
NSParagraphStyleAttributeName: textStyle
]
let im:NSImage = NSImage(size: image.size)
let rep:NSBitmapImageRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(image.size.width), pixelsHigh: Int(image.size.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSCalibratedRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)!
im.addRepresentation(rep)
im.lockFocus()
image.draw(in: imageRect)
text.draw(in: textRect, withAttributes: textFontAttributes)
im.unlockFocus()
return im
}
This is a different approach using a temporary NSView to draw the image and the text and cache the result in a new image (code is Swift 4). The benefit it you don't need to deal with pixels
class ImageView : NSView {
var image : NSImage
var text : String
init(image: NSImage, text: String)
{
self.image = image
self.text = text
super.init(frame: NSRect(origin: NSZeroPoint, size: image.size))
}
required init?(coder decoder: NSCoder) { fatalError() }
override func draw(_ dirtyRect: NSRect) {
let font = NSFont.boldSystemFont(ofSize: 18)
let textRect = CGRect(x: 5, y: 5, width: image.size.width - 5, height: image.size.height - 5)
image.draw(in: dirtyRect)
text.draw(in: textRect, withAttributes: [.font: font, .foregroundColor: NSColor.white])
}
var outputImage : NSImage {
let imageRep = bitmapImageRepForCachingDisplay(in: frame)!
cacheDisplay(in: frame, to:imageRep)
let tiffData = imageRep.tiffRepresentation!
return NSImage(data : tiffData)!
}
}
To use it, initialize a view
let image = ... // get some image
let view = ImageView(image: image, text: "Sample Text")
and get the new image
let imageWithText = view.outputImage
Note:
The paragraph style is not used at all, but if you want to create a mutable paragraph style just write
let textStyle = NSMutableParagraphStyle()
Mixed pixel vs point?
Depending on your screen 2x or 3x image is smaller 2 times or 3 times?
Here is more detailed info (scroll down to "Converting between pixels and points")
http://blog.fluidui.com/designing-for-mobile-101-pixels-points-and-resolutions/
But keep in mind that:
NSImage is resolution aware and uses a HiDPI graphics context when you lockFocus on a system with retina screen.
The image dimensions you pass to your NSBitmapImageRep initializer are in points (not pixels). An 150.0 point-wide image therefore uses 300 horizontal pixels in a #2x context.
Source:
How to save PNG file from NSImage (retina issues)
Following simple app works for me. Enjoy ;)
import Cocoa
class ViewController: NSViewController {
func save(image:NSImage, imageURL:String, format:String) -> Bool
{
let bMImg = NSBitmapImageRep(data: (image.tiffRepresentation)!)
switch format {
case ".png":
let filepath = URL(fileURLWithPath: imageURL+".png")
let dataToSave = bMImg?.representation(using: NSBitmapImageRep.FileType.png, properties: [NSBitmapImageRep.PropertyKey.compressionFactor : 1])
do
{
try dataToSave?.write(to: filepath)
return true
} catch {
return false
}
default:
return false
}
}
func draw(text:String, image:NSImage) -> NSImage
{
let font = NSFont.boldSystemFont(ofSize: 18)
let imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
let textRect = CGRect(x: 5, y: 5, width: image.size.width - 5, height: image.size.height - 5)
let textStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
let textFontAttributes = [
NSAttributedStringKey.font: font,
NSAttributedStringKey.foregroundColor: NSColor.white,
NSAttributedStringKey.paragraphStyle: textStyle
]
let im:NSImage = NSImage(size: image.size)
let rep:NSBitmapImageRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(image.size.width), pixelsHigh: Int(image.size.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSColorSpaceName.calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0)!
im.addRepresentation(rep)
im.lockFocus()
image.draw(in: imageRect)
text.draw(in: textRect, withAttributes: textFontAttributes)
im.unlockFocus()
return im
}
#IBAction func action(_ sender: NSButton) {
let dialog = NSOpenPanel();
dialog.title = "Choose a image...";
dialog.showsResizeIndicator = true;
dialog.showsHiddenFiles = false;
dialog.canChooseDirectories = true;
dialog.canCreateDirectories = true;
dialog.allowsMultipleSelection = false;
dialog.allowedFileTypes = ["png", "jpg"];
if (dialog.runModal() == NSApplication.ModalResponse.OK) {
guard let url = dialog.url,
let imageCIImage = CIImage(contentsOf: url) else {
return
}
let rep: NSCIImageRep = NSCIImageRep(ciImage: imageCIImage)
let nsImage = NSImage(size: rep.size)
nsImage.addRepresentation(rep)
let imageWithText = draw(text:"ABC", image: nsImage)
if (save(image: imageWithText, imageURL: "imageWithText", format: ".png")) {
print("Success")
} else {
print("ERROR:Failed to save image")
}
} else {
// User clicked on "Cancel"
return
}
}
}

How to make text appear in centre of the image?

I want to add a text on an image, and I'm able to do it as shown in below code.
func textToImage(drawText: NSString, inImage: UIImage, atPoint:CGPoint)->UIImage{
// Setup the font specific variables
var textColor: UIColor = UIColor.redColor()
var textFont: UIFont = UIFont(name: "AmericanTypewriter", size: 75)!
let textStyle = NSTextEffectLetterpressStyle
//Setup the image context using the passed image.
UIGraphicsBeginImageContext(inImage.size)
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
NSTextEffectAttributeName : textStyle
]
inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))
var rect: CGRect = CGRectMake(atPoint.x, atPoint.y, inImage.size.width, inImage.size.height)
drawText.drawInRect(rect, withAttributes: textFontAttributes)
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
I called this function like shown below
let newImage : UIImage = textToImage(textToAdd!, inImage: imageToSave, atPoint:CGPoint(x: 20, y: 20)) //For now text is displaying at the top in left end for point(x:20 ,y:20)
But the problem is, text is taken by user. They can give either single word or big sentence. So if they give only single word, it should appear in top and middle of the image or else in top from left to right. it is more like, I want to set the text alignment to centre. To achieve it, Accordingly I should change the CGPoint given above. But I'm not getting how to change it so that it should look good in all scenarios. Please help me how to achieve this.
You can center the text near the top of the image like this:
func textToImage(drawText: NSString, inImage: UIImage, atPoint:CGPoint)->UIImage{
// Setup the font specific variables
var textColor: UIColor = UIColor.redColor()
var textFont: UIFont = UIFont(name: "AmericanTypewriter", size: 75)!
let textStyle = NSTextEffectLetterpressStyle
//Setup the image context using the passed image.
UIGraphicsBeginImageContext(inImage.size)
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
NSTextEffectAttributeName : textStyle
]
inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))
let textSize = drawText.sizeWithAttributes(textFontAttributes)
let textRect = CGRectMake(inImage.size.width / 2 - textSize.width / 2, 0,
inImage.size.width / 2 + textSize.width / 2, inImage.size.height - textSize.height)
drawText.drawInRect(textRect, withAttributes: textFontAttributes)
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
Added to #osteven answer. Below code works as I expected. Hope it helps others.
func textToImage(drawText: NSString, inImage: UIImage, atPoint:CGPoint)->UIImage{
// Setup the font specific variables
var textColor: UIColor = UIColor.redColor()
var textFont: UIFont = UIFont(name: "AmericanTypewriter", size: 75)!
let textStyle = NSTextEffectLetterpressStyle
//Setup the image context using the passed image.
UIGraphicsBeginImageContext(inImage.size)
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
NSTextEffectAttributeName : textStyle
]
inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))
let textSize = drawText.sizeWithAttributes(textFontAttributes)
if textSize.width < inImage.size.width {
println("lesser")
let textRect = CGRectMake(inImage.size.width / 2 - textSize.width / 2, 0,
inImage.size.width / 2 + textSize.width / 2, inImage.size.height - textSize.height)
drawText.drawInRect(textRect, withAttributes: textFontAttributes)
}
else {
println("greater")
let textRect = CGRectMake(0 , 0,
inImage.size.width, inImage.size.height)
drawText.drawInRect(textRect, withAttributes: textFontAttributes)
}
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
It may be a simple as what you suggested with "I want to set the text alignment to centre".
Add a line here:
// Setup the font specific variables
var textColor: UIColor = UIColor.redColor()
var textFont: UIFont = UIFont(name: "AmericanTypewriter", size: 75)!
let textStyle = NSTextEffectLetterpressStyle
let textAlignment = NSTextAlignment.Center
and add to your array:
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
NSTextEffectAttributeName : textStyle
NSTextAlignment: textAlignment
]
This should make the text centered in the image.
If you change the point of text origin back to (0, 0) and set your Text Rectangle as big as the image, it should be able to account for the width of Rect and thus center all of the text accordingly.

Saving an image on top of another image in Swift

I am learning Swift and I am creating an app that uses a personal photo and puts another on top of it. I now have a hacky solution, to create a screenshot of the area and save it. I need to do this in Swift
#IBAction func saveImage(sender: AnyObject) {
//Create the UIImage
UIGraphicsBeginImageContext(imageView.frame.size)
view.layer.renderInContext(UIGraphicsGetCurrentContext())
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//Save it to the camera roll
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
But, this was working and isn't anymore. But, this is also not the best solution.
So guys, how can I save an image to the camera roll from a personal image, with an image as overlay?
Help would be greatly appreciated!! Thanks!
I would recommend reading through this thread. All your answers are there. Once you read through that article, the following code sample should help you composite the two images together properly.
func saveImage() {
let bottomImage = UIImage(named: "bottom")!
let topImage = UIImage(named: "top")!
let newSize = CGSizeMake(100, 100) // set this to what you need
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
bottomImage.drawInRect(CGRect(origin: CGPointZero, size: newSize))
topImage.drawInRect(CGRect(origin: CGPointZero, size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
Hopefully this gets you going in the right direction.
Apple advises against UIGraphicsBeginImageContext, so as long as your app does not support devices older than iOS 10, then use something like this:
private func drawLogoIn(_ image: UIImage, _ logo: UIImage, position: CGPoint) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: image.size)
return renderer.image { context in
image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
logo.draw(in: CGRect(origin: position, size: logo.size))
}
}
Besides performance gains, you get full P3 range.
UPDATE FOR SWIFT 4
func saveImage() {
let bottomImage = UIImage(named: "your bottom image name")!
let topImage = UIImage(named: "your top image name")!
let newSize = CGSize(width: 100, height: 100) // set this to what you need
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
bottomImage.draw(in: CGRect(origin: CGPoint.zero, size: newSize))
topImage.draw(in: CGRect(origin: CGPoint.zero, size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
To use the image just refer to newImage
EXAMPLE HOW TO USE THE IMAGE:
#IBOutlet weak var imageButton: UIButton!
imageButton.setBackgroundImage(newImage), for: .normal)
This is an edit of cnoon's answer but optimized for Swift 4.
Updated to Swift 3.0:
func saveImage() {
let bottomImage = UIImage(named: "bottom")!
let topImage = UIImage(named: "top")!
let newSize = CGSizeMake(100, 100) // set this to what you need
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
bottomImage.draw(in: CGRect(origin: CGPointZero, size: newSize))//As drawInRect is deprecated
topImage.draw(at: CGRect(origin: CGPointZero, size: newSize))//As drawInRect is deprecated
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}