Store photo-tag coordinates across image sizes

Model point and box tags with normalized coordinates so annotations survive resizing, cropping decisions, and multiple image variants.

Design: photo tags that survive resizing

A photo tag associates an account with a place in an image. That place should stay attached to its subject when a laptop-sized photo becomes a phone thumbnail. Storing the click's screen coordinates cannot provide that guarantee: the next display may have a different size, margins or crop.

We'll work through source coordinates, map a point into a square card, and extend the model to boxes and crop edits. Then we'll follow a tag through placement, approval and image replacement in a small executable service.

Store a place in the source image

Choose a coordinate convention before choosing a database. Here the origin is the upper-left corner, horizontal coordinates increase rightward, and vertical coordinates increase downward. Each tag belongs to one immutable image version with known dimensions and orientation.

For our 800 by 600 source, a point at (200,150) is one quarter of the way across and down. Store those fractions as u=0.25 and v=0.25 . In a simple 400 by 300 resize, the same point becomes (100,75).

text u = source x / source width v = source y / source height

rendered x = u rendered image width rendered y = v rendered image height

Source pixels would also work if every consumer knew which source dimensions they referred to. The mistake is storing pixels from an unspecified display. Ratios make the convention convenient; the image version keeps their meaning stable.

Keep full precision in storage. For example, rounding a 600/1024 ratio to 0.586 before multiplying it by 512 yields 300.032 instead of 300. Round only when presenting a value or placing a raster pixel.

Our point domain includes 0 and 1. The point (1,1) denotes the lower-right boundary of the image extent, not an indexed raster pixel. Whether the marker's label extends beyond that boundary is a separate layout choice.

Account for the display box

The rendered image and its surrounding box are not always the same size. With contain , the entire image fits and unused space becomes margins. With cover , the image fills the box and some source content may be cropped. Both preserve aspect ratio.

For a centered image in a box of width W and height H, choose a scale and then an offset:

text contain: s = min(W / 800, H / 600) cover: s = max(W / 800, H / 600)

ox = (W - 800 s) / 2 oy = (H - 600 s) / 2 X = ox + 800 s u Y = oy + 600 s v