Skip to main content

Images

Overview

Most Viewtron camera events include JPEG snapshot images embedded as base64 in the XML payload. A typical event has a source image (full camera view at the time of detection) and optionally a target image (cropped region of the detected object).

The Node.js SDK provides both the raw base64 strings and lazy-decoded Buffer objects, so you can choose the most efficient path for your use case.

Image Properties

Available on every ViewtronEvent object:

PropertyTypeDescription
sourceImagestringBase64-encoded source image, or empty string '' if not present
targetImagestringBase64-encoded target image, or empty string '' if not present
sourceImageBytesBuffer or nullDecoded source image (lazy, cached). null if no source image.
targetImageBytesBuffer or nullDecoded target image (lazy, cached). null if no target image.
hasImagesbooleantrue if either sourceImage or targetImage is non-empty

sourceImage and targetImage are plain string properties set during parsing. sourceImageBytes, targetImageBytes, and hasImages are getters.

Lazy Decoding

sourceImageBytes and targetImageBytes are JavaScript getters that decode the base64 string to a Buffer on first access, then cache the result in a private property. Subsequent accesses return the cached Buffer without re-decoding.

// First access — decodes base64 to Buffer and caches it
const buf = event.sourceImageBytes;

// Second access — returns the cached Buffer (no decode)
const sameBuf = event.sourceImageBytes;

This means:

  • If you only need the base64 string (e.g., for a JSON API response or an HTML \<img> tag), use sourceImage / targetImage directly. No Buffer allocation occurs.
  • If you need binary data (e.g., writing to disk, sending over a socket), access sourceImageBytes / targetImageBytes. The decode happens once and is cached for the lifetime of the event object.
  • If you never access the Bytes properties, the base64 string is never decoded — no wasted memory or CPU.

Source vs Target Images

Image TypeWhat It ContainsTypical Use
Source imageFull camera view at the moment of detectionScene context, recording, human review
Target imageCropped region of the detected objectPlate crops, face crops, object identification

When Images Are Included

Event TypeSource ImageTarget Image
LPRYes — full sceneYes — cropped plate
Face DetectionYes — full sceneYes — cropped face
IntrusionYes — full sceneSometimes
CountingSometimesRarely
TrajectNoNo

Image availability depends on camera model and firmware configuration. Always check hasImages or test the specific property before using images.

Code Examples

Saving Images to Disk

const fs = require('fs');

server.on('event', (event, clientIP) => {
const prefix = `${event.category}_${Date.now()}`;

if (event.sourceImage) {
fs.writeFileSync(`${prefix}_source.jpg`, event.sourceImageBytes);
}

if (event.targetImage) {
fs.writeFileSync(`${prefix}_target.jpg`, event.targetImageBytes);
}
});

Sending via HTTP / fetch

server.on('event', async (event, clientIP) => {
if (event.category === 'lpr' && event.sourceImage) {
await fetch('https://your-api.example.com/upload', {
method: 'POST',
headers: { 'Content-Type': 'image/jpeg' },
body: event.sourceImageBytes,
});
}
});

Base64 for JSON API

server.on('event', (event, clientIP) => {
if (event.category === 'face' && event.targetImage) {
// sourceImage and targetImage are already base64 strings —
// no Buffer allocation needed for JSON payloads
const payload = JSON.stringify({
camera: event.cameraName,
faceImage: event.targetImage,
});
// Send to your API, or embed in HTML as data:image/jpeg;base64,...
}
});

Checking Before Accessing

server.on('event', (event, clientIP) => {
if (!event.hasImages) {
console.log(`No images in ${event.category} event`);
return;
}

if (event.sourceImage) {
console.log(`Source image: ${event.sourceImageBytes.length} bytes`);
}

if (event.targetImage) {
console.log(`Target image: ${event.targetImageBytes.length} bytes`);
}
});

Image Sizes

Typical image sizes vary by camera resolution and model:

  • Source images: 50KB-500KB (full resolution camera snapshot)
  • Target images: 5KB-50KB (cropped region)

These are embedded as base64 in the XML payload, so events with images are significantly larger than events without. The base64 encoding adds ~33% overhead, which is removed when you access the Bytes properties.