How to Replace the AtomCam Watermark Logo with Custom PNG Images

You can replace the AtomCam watermark by converting a PNG to a BGRA raw format file named watermark.bgra and placing it at /media/mmc/watermark.bgra on the device.

The AtomCam firmware overlays a watermark logo on video streams by reading a raw bitmap file from the media partition. According to the mnakada/atomcam_tools source code, you can replace the watermark logo with custom PNG images by converting them to the expected BGRA binary format and deploying the file to the correct path.

Understanding the Watermark Loading Mechanism

The implementation that loads and paints the logo lives in [libcallback/watermark.c](https://github.com/mnakada/atomcam_tools/blob/main/libcallback/watermark.c). At boot or when triggered by a reload command, the firmware opens /media/mmc/watermark.bgra and processes it in three stages.

First, lines 52‑63 read a 2‑integer header representing the image dimensions (x, y). These are 32‑bit little‑endian integers indicating width and height.

Next, lines 64‑69 read x * y pixels (each pixel is 32‑bit BGRA) into WatermarkBuffer. If the dimensions exceed the firmware limits, the loader rejects the file with a watermark file format error.

Finally, lines 70‑75 pass the bitmap to the video OSD subsystem via local_sdk_video_osd_set_logo_bitmap and sdkosd_update_logo_data. Lines 89‑108 apply the stored bitmap to both the full‑resolution and the scaled‑down OSD layers, positioning it according to the constants defined in the header.

Image Requirements and Limitations

Before converting your artwork, ensure it complies with the firmware constraints defined in libcallback/watermark.c.

  • Maximum dimensions: WATERMARK_MAX_WIDTH = 500 pixels and WATERMARK_MAX_HEIGHT = 200 pixels (lines 10‑13). Images larger than these limits will be rejected.
  • Color format: 32‑bit BGRA (Blue, Green, Red, Alpha) with 8 bits per channel.
  • File structure: A binary header containing two little‑endian 32‑bit integers (width, height) followed immediately by the raw pixel data.
  • Default position: The logo appears at WATERMARK_LEFT = 51 pixels from the left and WATERMARK_BOTTOM = 21 pixels from the bottom (lines 15‑16).

Converting PNG to BGRA Format

To create a valid watermark.bgra file from a standard PNG, use ImageMagick to handle resizing, format conversion, and binary header generation.


# Resize to stay within the limits (optional)

convert logo.png -resize 500x200\> resized.png

# Export width and height as little‑endian 32‑bit integers

WIDTH=$(identify -format "%w" resized.png)
HEIGHT=$(identify -format "%h" resized.png)

# Create the header (two 32‑bit little‑endian ints)

printf "%d\\0\\0\\0%d\\0\\0\\0" $WIDTH $HEIGHT > watermark.bgra

# Append raw BGRA pixel data (ImageMagick outputs BGRA with -depth 8)

convert resized.png -depth 8 BGRA:- >> watermark.bgra

For automated builds, you can use a complete conversion script that enforces size limits and generates the proper binary header:

#!/usr/bin/env bash

# replace_watermark.sh – generate watermark.bgra from a PNG

set -e

SRC="${1:-logo.png}"
OUT="${2:-watermark.bgra}"

# Enforce size limits

MAX_W=500
MAX_H=200
convert "$SRC" -resize "${MAX_W}x${MAX_H}>" tmp.png

WIDTH=$(identify -format "%w" tmp.png)
HEIGHT=$(identify -format "%h" tmp.png)

# Header: little‑endian 32‑bit width, height

printf "$(printf '\\x%02x\\x%02x\\x%02x\\x%02x' $((WIDTH & 0xFF)) $(((WIDTH>>8) & 0xFF)) $(((WIDTH>>16) & 0xFF)) $(((WIDTH>>24) & 0xFF)))" \
       "$(printf '\\x%02x\\x%02x\\x%02x\\x%02x' $((HEIGHT & 0xFF)) $(((HEIGHT>>8) & 0xFF)) $(((HEIGHT>>16) & 0xFF)) $(((HEIGHT>>24) & 0xFF)))" \
       > "$OUT"

# Append raw BGRA data

convert tmp.png -depth 8 BGRA:- >> "$OUT"

rm -f tmp.png
echo "Created $OUT ( $WIDTH × $HEIGHT )"

Deploying the Custom Watermark

You can deploy the new watermark either during the firmware build process or on a running device.

During image build: Replace the pre‑installed file in the overlay directory. The build pipeline copies overlay_rootfs/etc/watermark.bgra into the root filesystem when assembling the firmware image.

cp watermark.bgra overlay_rootfs/etc/watermark.bgra

On a running device: Copy the file to the MMC partition and trigger a reload.


# Copy the generated file to the MMC partition

sudo cp watermark.bgra /media/mmc/watermark.bgra

# Trigger immediate reload via the console command

echo "Watermark update" | nc -U /tmp/atomcam_cmd_sock

If you do not send the Watermark update command, the firmware will load the new logo automatically on the next reboot.

Verification and Troubleshooting

After deployment, verify the logo appears in the lower‑left corner of the video preview. If the watermark does not appear:

  • Check the system logs for watermark file format error, which indicates the image exceeds WATERMARK_MAX_WIDTH or WATERMARK_MAX_HEIGHT.
  • Confirm the file is at /media/mmc/watermark.bgra and not in a subdirectory.
  • Ensure the binary header uses little‑endian byte order; big‑endian systems will misinterpret the dimensions.

Summary

  • The AtomCam firmware loads watermark graphics from /media/mmc/watermark.bgra as implemented in libcallback/watermark.c.
  • Custom images must be converted to BGRA format with a binary header containing two 32‑bit little‑endian integers (width, height).
  • Maximum dimensions are strictly enforced at 500×200 pixels.
  • Deploy by copying to the MMC partition at runtime or to overlay_rootfs/etc/watermark.bgra during builds.
  • Use the Watermark update command or a reboot to apply changes immediately.

Frequently Asked Questions

What is the maximum size for a custom watermark?

The firmware enforces hard limits of 500 pixels wide and 200 pixels tall as defined by WATERMARK_MAX_WIDTH and WATERMARK_MAX_HEIGHT in libcallback/watermark.c. Images exceeding these dimensions trigger a watermark file format error and are rejected by the loader at lines 52‑63.

What format does the watermark.bgra file use?

The file uses a custom binary format consisting of an 8‑byte header followed by raw pixel data. The header contains two 32‑bit little‑endian integers representing width and height. The pixel data is 32‑bit BGRA (8 bits per channel), totaling width × height × 4 bytes.

How do I force the camera to reload the watermark without rebooting?

Send the Watermark update command through the AtomCam control socket. You can invoke this via SSH or a local shell using echo "Watermark update" | nc -U /tmp/atomcam_cmd_sock. This triggers the reload routine in watermark.c without requiring a full system restart.

Where is the default watermark stored in the firmware source?

The default watermark shipped with the firmware image is located at overlay_rootfs/etc/watermark.bgra. When the build system assembles the firmware image, it copies this file into the root filesystem. Replacing this source file bakes your custom logo into every firmware image you generate.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →