A colleague designed an application in which a product image (up to 5000 KB) is uploaded into a document template. From there, it is used in several instances - always with a copy of the image as supporting material and, if necessary, for documentation in Word/PDF format.
Regardless of whether an alternative approach might be more appropriate, we explored how to reduce database usage with this variant.
In this case, we were allowed to reduce the resolution of the image already at its initial save within the document template. We chose a maximum resolution of Full HD – 1920x1080 pixels, depending on the image orientation.
This prevents the image from unnecessarily occupying space in the workflow histories.
Our solution was JavaScript. We used an older version of the Pica library by Vitaly Puzrin, which is available under the MIT license.
How does it work?
The script reads the image resolution and determines which of the two dimensions needs to be reduced so that neither exceeds the 1920x1080 limit (while maintaining the aspect ratio). If both values are already within the limits, the image remains unchanged. The alert messages can be commented out for productive use, but they are useful during testing.
After executing the JavaScript, a hidden save button is triggered. Since the visible JavaScript button is part of the DownScaler code, make sure to deactivate the JavaScript after this step to prevent the save button from being incorrectly displayed in later steps, which may lead to faulty behavior.
#{FLD:10523}# = Picture field: [Picture (max. 5000 KB)]
#{PH:2526}# = Path: [HIDDEN: Save Picture after JS downscaling]
<script src="https://unpkg.com/pica@8.0.0/dist/pica.min.js">
// https://app.unpkg.com/pica@8.0.0/files/LICENSE
// MIT License
// Copyright (C) 2014-2017 by Vitaly Puzrin
</script>
<script>
setTimeout(() => {
const resizeButton = document.getElementById("downscale-and-save-button");
if (resizeButton) {
resizeButton.addEventListener("click", async function () {
const fieldId = "#{FLD:10523}#";
const rawBase64 = GetValue(fieldId);
if (!rawBase64 || rawBase64.length < 50) {
alert("No valid image content in the field.");
return;
}
const img = new Image();
img.src = rawBase64;
img.onload = async () => {
const originalWidth = img.width;
const originalHeight = img.height;
const longerSide = Math.max(originalWidth, originalHeight);
const shorterSide = Math.min(originalWidth, originalHeight);
const MAX_LONG = 1920;
const MAX_SHORT = 1080;
// Keine Skalierung nötig
if (longerSide <= MAX_LONG && shorterSide <= MAX_SHORT) {
alert("Image is already smaller than (or exactly) 1920×1080 (long/short side) – saved without changes.");
MoveToNextStep(#{PH:2526}#);
return;
}
// Verhältnis zur Längeren Seite und zur Kürzeren
const ratioLong = MAX_LONG / longerSide;
const ratioShort = MAX_SHORT / shorterSide;
const scaleFactor = Math.min(ratioLong, ratioShort);
const targetWidth = Math.round(originalWidth * scaleFactor);
const targetHeight = Math.round(originalHeight * scaleFactor);
const canvas = document.createElement("canvas");
canvas.width = targetWidth;
canvas.height = targetHeight;
try {
const pica = window.pica();
await pica.resize(img, canvas);
const resizedBase64 = canvas.toDataURL("image/jpeg", 0.95);
SetValue(fieldId, resizedBase64);
alert("Image resized to " + targetWidth + "×" + targetHeight + " and saved.");
MoveToNextStep(#{PH:2526}#);
} catch (err) {
console.error("Error during image processing:", err);
alert("Error while resizing the image.");
}
};
img.onerror = () => {
alert("The image could not be loaded.");
};
});
} else {
console.error("Button with ID 'downscale-and-save-button' not found.");
}
}, 500);
</script>
<br><br>
<button id="downscale-and-save-button" style="background-color: #C8DEB6; font-weight: bold; border-radius: 10px; font-size:16px;">[DownScale and then Save] JS-Button</button>