Using CoreGraphics to render text with attributes as as an image and return that image – the code that returns the image is:
func textualImage(text: String, textSize: CGFloat, textColor: UIColor, backgroundColor: UIColor = .white) -> UIImage? {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let attributes = [
NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: textSize),
NSAttributedString.Key.backgroundColor: UIColor.white,
NSAttributedString.Key.paragraphStyle: paragraphStyle
]
let textSize = text.size(withAttributes: attributes)
UIGraphicsBeginImageContextWithOptions(textSize, true, 0)
backgroundColor.setFill() // tried this but no different
let rect = CGRect(origin: .zero, size: textSize)
text.draw(in: rect, withAttributes: attributes)
let imageOriginal = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return imageOriginal
}
When running this code, I will get black lines (sometimes thin, sometimes thick, sometimes any edge) like in this photo
Have tried providing a background color and using the .setFill() function on the color inside of the graphics rendering context. Would anyone be able to help me understand why this is happening?
This is being done with text annotations to ‘flatten’ that particular field of a PDF so it can no longer be altered.
To note, if the text provided is multiple lines and one line is shorter than another, whatever space is the ’empty overlap’ is solid black – this seems to be relevant to the issue but changing the size of the graphics context is making no difference.
Any help would be appreciated thank you
2
Answers
It appears the solution to this is two parts. Using the method in the question was forcing the black lines because that method colors the entire background black and then the text had the background of white. While there seems to be a solution of coloring the background of the context to other-than-black, I could not get the method to work. Instead I changed the rendering method itself to what is below, which gives no background color to the rendered area by default and removing the background color of the text then draws only the text in the frame, with no other background. The text background removal (as suggested by Cy-4AH) with the original style produces a solid black box, but removing the background with this style renders as expected.
You initial method is quite OK and is working exactly as expected. Let’s break it down to more simple components.
First of all try to just remove the text part and get the image from the context itself:
The result is a black rectangle. And the reason for it is because a default color in a context is a transparent color as RGBA
(0,0,0,0)
. But in your case you set a context to be opaque which means it is translated to RGB(0,0,0)
, a black color.Simply setting you options as
UIGraphicsBeginImageContextWithOptions(textSize, false, 0)
the black rectangle is gone.The opaque value may still make sense but in that case you should draw some color over the whole context with paths. For instance
This is how the context rect is being set to a certain color. And this specific code isolates your issue that you were initially facing. You can see anomalies on right or/and bottom side of your rectangle. The reason for this is that your text size has a "strange" value and is not an integer. Both, context and returned image, will have integer size. So you need to round those values.
You can get your context size by using
But you will find out that the size of a context is much larger as it already includes your screen scale. This has happened again because of the options you set when generating your context. By providing a scale of
0
you let system to decide the scale of your context. That is OK in most cases but in your case you may wish to control this based on the scale of your PDF or your screen (From your question it is hard to tell). Try it like so:So now that we have all values we can try and put it all together:
I hope the comments give enough additional information.