Episode #292

Watermarking Photos

Series: Dive Into Core Graphics

6 minutes
Published on July 21, 2017

This video is only available to subscribers. Get access to this video and 578 others.

In this episode we’ll learn how to draw images with core graphics, then watermark a photo by drawing text overlaid on top of it.

Preparing a Custom Context

let scale: CGFloat = 2
let bounds = CGRect(x: 0, y: 0, width: 320, height: 320)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGImageAlphaInfo.premultipliedFirst.rawValue

let context = CGContext(
    data: nil,
    width: Int(bounds.width * scale),
    height: Int(bounds.height * scale),
    bitsPerComponent: 8,
    bytesPerRow: 0,
    space: colorSpace,
    bitmapInfo: bitmapInfo

// Apply scale
context.scaleBy(x: scale, y: scale)

Drawing an image in the context

context.draw(#imageLiteral(resourceName: "San-Francisco@2x.png").cgImage!, in: bounds)

Drawing Text on top of the image

We'll want to invert our y-axis first, otherwise our text will be upside down.

// Invert Y axis
context.translateBy(x: bounds.midX, y: bounds.midY)
context.scaleBy(x: 1, y: -1)
context.translateBy(x: -bounds.midX, y: -bounds.midY)

// Draw text
let string = "San Francisco" as NSString
let stringRect = CGRect(x: 4, y: bounds.height - 24, width: bounds.width - 8, height: 20)

// we have to use the push/pop context trick, otherwise the UIStringDrawing helpers won't work,
// because they rely on the _current_ context...

string.draw(in: stringRect, withAttributes: [
    NSForegroundColorAttributeName: UIColor(white: 1, alpha: 0.5),
    NSFontAttributeName: UIFont.systemFont(ofSize: 20, weight: UIFontWeightMedium)

Getting the rendered image

let cgImage = context.makeImage()!
let image = UIImage(cgImage: cgImage, scale: scale, orientation: .up)

Saving the image to disk

let pngData = UIImagePNGRepresentation(image)
FileManager.default.createFile(atPath: "foo@2x.png", contents: pngData, attributes: nil)

let jpegData = UIImageJPEGRepresentation(image)
FileManager.default.createFile(atPath: "foo@2x.jpg", contents: jpegData, attributes: nil)

This episode uses Swift 3.0, Xcode 8.3.