Why Your Watermark Is Tiny on One Photo and Huge on the Next: Resolution-Independent Overlays in Swift
The obvious first version of batch watermark code has one setting that looks completely reasonable: a font size of 48. On a screenshot that's enormous. On a 48-megapixel photo it's a speck in the corner you'd need to zoom in to find. On a portrait photo it sits at a different distance from the edge than on a landscape one. Every photo in the batch gets "the same" watermark, and no two of them…
The challenge of creating a consistent watermark across a mixed set of images lies in the fact that a fixed font size can appear vastly different depending on the image's resolution and orientation. A 48-pixel-tall line of text may seem substantial on a small screenshot but become practically invisible on a high-resolution 48-megapixel photo. The inconsistency arises because the watermark's size is defined in points, not pixels, leading to varying appearances across images.
To resolve this issue, the key is to work with pixel dimensions instead of points. By converting the image size to pixels using the `pixelSize(of:)` function, we can ensure that the watermark is applied based on the actual pixel dimensions of each image. This approach accounts for orientation changes and provides a more accurate basis for sizing the watermark.
In addition to working in pixels, the size of the watermark should be relative to the short side of the image. This approach ensures that the watermark remains proportionate across different image dimensions, such as a landscape photo versus a portrait screenshot. By using the short side as the reference point, we can maintain a consistent appearance regardless of the image's aspect ratio.
To implement this solution in Swift with UIKit drawing, follow these steps:
1. Convert the image size to pixels using the `pixelSize(of:)` function, which takes the image as input and returns its size in pixels, accounting for the image's scale.
2. Define a `WatermarkStyle` struct that includes properties for the watermark text, relative cap height (a fraction of the short side), relative margin (distance from the edges), maximum allowed width (as a fraction of the image), and opacity.
3. Create a function called `font(forCapHeight:)` that takes a target cap height (in pixels) and font weight as input. This function calculates the appropriate font size by solving for the font point size that results in the desired cap height. It uses the `UIFont.capHeight` property to determine the relationship between font size and cap height for the chosen font.
4. Implement a function called `attributes(font:,opacity:,shortSide:)` that generates the attributes for the attributed string used to render the watermark. This function sets the font, foreground color (white), and applies a shadow effect to the text. The shadow's blur radius and offset are proportionally scaled based on the image's short side, ensuring that the watermark remains visually consistent across different image sizes.
By following these steps and considering the unique challenges posed by varying image resolutions and orientations, you can create a resolution-independent watermark overlay that appears consistently across all images in a batch. This approach ensures that the watermark is visually balanced, regardless of the image's dimensions, providing a professional and polished look to the final output.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.