A watermark looks balanced on a landscape photo. Apply the same settings to a portrait photo and it covers the product. Apply them to a small thumbnail and the text becomes unreadable.
The problem is often the placement policy, not the logo.
A batch watermark feature needs more than a text field and an opacity slider. It needs a clear purpose, a coordinate system that survives different dimensions, and a review step that catches cases a shared setting cannot handle.
This article develops a reference workflow for visible watermarks. It is not a description of BatchSet's internal implementation, and it does not cover invisible watermarking or forensic identification.
1. Decide what the visible mark should do
“Add a watermark” can mean several different things:
| Purpose | Likely design priority |
|---|---|
| Brand attribution | Readable identity without hiding the subject |
| A draft or proof label | An unmistakable status that survives a casual glance |
| A product-photo preview | A useful view of the item with a visible mark |
| Internal review identification | A clear reference label or version |
Choose the purpose before tuning opacity.
A subtle corner logo and a repeated “DRAFT” pattern solve different communication problems. Neither should be described as making a file impossible to copy or alter.
For an attribution workflow, my acceptance criteria would include the logo remaining readable at the expected viewing size, important product details remaining visible, and the final crop retaining the mark.
That last condition is easy to miss. The un-cropped export may look correct even though the receiving interface crops the corner away.
2. Keep clean sources and labeled derivatives
A visible raster watermark becomes part of the exported pixels. Keep an untouched master so another destination can receive a clean image or a different mark.
A simple output naming scheme might distinguish:
product-042-master.png
product-042-preview-watermarked.jpg
product-042-approved-clean.jpg
These are workflow labels, not a recommendation to send all three files to every recipient.
Avoid reopening the watermarked JPEG, moving the mark, and encoding again as the normal editing path. Generate each derivative from the clean source and the approved watermark asset.
Keep the watermark asset version with your export settings. Otherwise, a repeated job can produce different branding even when the placement values are unchanged.
3. Choose coordinates relative to the output
Fixed pixels are easy to implement and easy to misuse.
A 200-pixel-wide logo occupies 20% of a 1000-pixel image and 5% of a 4000-pixel image. A 24-pixel inset similarly becomes much less visible on a larger export.
Relative coordinates make the policy easier to explain:
- Mark width: a fraction of output width.
- Edge inset: a fraction of the shorter output side.
- Placement: a named anchor, such as bottom-right.
- Shape: preserve the watermark asset's aspect ratio.
Relative placement is still a default, not an automatic understanding of the image's subject. A corner may contain a product label or a person's face. Include per-image review where that matters.
4. Calculate a bounded placement box
The following reference helper positions a logo at the bottom-right. It also limits height so a very tall watermark does not consume the entire image.
The numbers are illustrative defaults for a workflow, not universal design rules.
function watermarkBox({
outputWidth,
outputHeight,
markWidth,
markHeight,
widthRatio = 0.18,
insetRatio = 0.03,
maxHeightRatio = 0.2,
}) {
for (const value of [outputWidth, outputHeight, markWidth, markHeight]) {
if (!Number.isFinite(value) || value <= 0) {
throw new RangeError("Dimensions must be positive finite numbers");
}
}
if (!Number.isFinite(widthRatio) || widthRatio <= 0 || widthRatio > 1 ||
!Number.isFinite(maxHeightRatio) || maxHeightRatio <= 0 || maxHeightRatio > 1 ||
!Number.isFinite(insetRatio) || insetRatio < 0 || insetRatio >= 0.5) {
throw new RangeError("Invalid placement ratios");
}
const inset = Math.min(outputWidth, outputHeight) * insetRatio;
const availableWidth = outputWidth - 2 * inset;
const availableHeight = outputHeight - 2 * inset;
const scale = Math.min(
outputWidth * widthRatio / markWidth,
outputHeight * maxHeightRatio / markHeight,
availableWidth / markWidth,
availableHeight / markHeight,
);
const width = markWidth * scale;
const height = markHeight * scale;
return {
x: outputWidth - inset - width,
y: outputHeight - inset - height,
width,
height,
};
}
This function computes a box. It does not detect faces, evaluate contrast, enforce a minimum readable logo size, or predict a platform's crop.
It permits upscaling. For a raster logo, you may choose a separate policy that rejects excessive enlargement or uses a higher-resolution asset. A large blurry logo can satisfy the geometry and still fail the design.
5. Keep watermark opacity local to the watermark
Canvas drawing state can leak between operations if you change it and forget to restore it.
MDN documents globalAlpha, while save and restore provide a state stack.
For a context whose base image has already been drawn and whose transform is set to output-pixel coordinates, isolate temporary opacity like this:
function drawWatermark(ctx, decodedMark, box, opacity = 0.35) {
if (!Number.isFinite(opacity) || opacity < 0 || opacity > 1) {
throw new RangeError("Opacity must be between 0 and 1");
}
ctx.save();
try {
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = opacity;
ctx.drawImage(decodedMark, box.x, box.y, box.width, box.height);
} finally {
ctx.restore();
}
}
The placement box should come from validated dimensions, such as the helper above. The drawing context must not have an unintended clip or transform; saving it does not clear an existing clip.
The mark's own alpha and the drawing opacity both affect the visible result. An asset whose pixels are already translucent can look fainter than an opaque asset at the same global opacity setting.
The finally block restores state even if drawing throws. It does not undo pixels already drawn or restore the original image. To retry with different settings, redraw the derivative from the clean source.
6. Place the mark after the intended crop and resize
For a typical destination-specific preview, I would use this order:
- Decode the clean source and the watermark asset.
- Calculate the intended crop, resize, and final canvas dimensions.
- Fill the output canvas with the approved background if it must be opaque.
- Draw the cropped and resized base image over that background.
- Composite the watermark at the final output dimensions.
- Encode and reopen the actual export for review.
The advantage of marking at final dimensions is that the selected relative size is visible in the export. Marking a very large source and then shrinking it can make the logo unnecessarily hard to evaluate.
If a receiving site crops after upload, your final dimensions are not the last transformation. Preview representative crops or choose an inset that accommodates the actual destination. There is no universal safe zone for every placement.
7. Test contrast on difficult images
One opacity value cannot make a white logo equally readable over every photograph.
Review light images, dark images, busy textures, and subjects that occupy the chosen corner. Include portrait, landscape, square, and unusually narrow exports.
Possible design responses include a darker mark variant, a light mark variant, a restrained backing plate, a different anchor, or an image-specific override. Each changes the appearance and should be deliberate.
Do not infer success from the full-size preview alone. A mark readable at 1600 pixels may vanish in a 160-pixel product thumbnail. Inspect both the intended display size and a larger detail view.
If the mark is a text label, use a font-loading policy that prevents export before the selected typeface is ready. Otherwise, a preview and download can disagree even when the text and coordinates match.
8. Make batch approval a visible step
For a proposed batch interface, I would separate applying a shared watermark from approving every result.
Show representative previews early, then let the user inspect individual outputs and move the mark where it obscures useful content. Record those overrides against stable item IDs rather than filenames alone.
An export summary should include output count, watermark asset or text version, shared placement settings, and which items used overrides. This makes a later rerun easier to reproduce.
Export failures still need explicit handling. A watermark preview is not evidence that the final encoder produced a downloadable file. Check the output format, bytes, and successful item count before offering the package.
Add the mark with a clear output policy
BatchSet's Bulk Image Converter provides browser-based image conversion and batch ZIP export. Its current advanced options list watermarking as a Pro feature; the ordinary free conversion workflow does not add a watermark.
When using a watermark workflow, keep your clean sources and inspect the final exported images at their destination size. Consistency means applying the same intention across a batch, with room for the images that need a different placement.
Top comments (0)