Theme
Images Preview
Four functions, all operating on the Connector host's local disk, not on a virtual file system. To work on a file a user uploaded, export it first.
Resizing
js
function JPEGResample(imgFile, maxWidth, maxHeight, quality): boolean;
function PNGResample(imgFile, maxWidth, maxHeight): boolean;Both resample in place, using Lanczos3, and both preserve the aspect ratio: the image is fitted inside the box you give, and whichever of the two limits binds first is the one that applies. Pass 0 for a dimension to leave it unconstrained. quality runs 1 to 100.
js
JPEGResample("/var/staging/photo.jpg", 1600, 1200, 85);
PNGResample("/var/staging/diagram.png", 1600, 0);These overwrite the original
There is no output path argument. The file you name is the file that is replaced, and the pixels you threw away are gone. Copy first if the original matters:
js
CopyFile("/var/staging/photo.jpg", "/var/originals");
JPEGResample("/var/staging/photo.jpg", 1600, 1200, 85);Metadata
js
function JPEGMetadata(imgFile): object;
function PNGMetadata(imgFile): object;Both return an object, empty when the file is not a valid image of that type. PNGMetadata gives you dimensions and validity; JPEGMetadata adds the full EXIF block when the file carries one.
js
var meta = JPEGMetadata("/var/staging/photo.jpg");
if (meta.Valid) {
Log.Info(meta.Width + "x" + meta.Height);
if (meta.Exif && meta.Exif.Make) {
Log.Info("taken with a " + meta.Exif.Make + " " + meta.Exif.Model);
}
}json
{
"Valid": true,
"Width": 480,
"Height": 360,
"Exif": {
"Make": "Canon",
"Model": "Canon PowerShot S40",
"DateTime": "2003:12:14 12:01:44",
"ColorSpace": [1]
}
}The EXIF fields present depend entirely on the camera and on whatever software has touched the file since. Guard every field access; many JPEGs carry no EXIF at all, and many editors strip it.
EXIF often contains a location
A photograph taken on a phone commonly carries GPS coordinates, a device serial number and a timestamp. If your users upload photographs and you resize or republish them, you may be redistributing where and when each one was taken. JPEGResample does not preserve EXIF, which for this purpose is a feature: resampling drops it. If you need to keep the image untouched but strip the metadata, use a dedicated tool through RunCapture.
A worked example
Cap the size of uploaded images, on an after handler in the background:
js
// Bound to after.upload, Run in the background, timeout 60000.
var ext = ExtractExt(CtxRelPath()).toLowerCase();
if (ext !== ".jpg" && ext !== ".jpeg" && ext !== ".png") {
Exit(0);
}
var vfs = GetCurrentVFS();
var local = "/var/staging/" + ShortUID() + ext;
if (!vfs.ExportFile(CtxRelPath(), local).Ok()) {
Log.Error("could not export " + CtxRelPath());
Exit(0);
}
var resized = (ext === ".png")
? PNGResample(local, 2000, 2000)
: JPEGResample(local, 2000, 2000, 88);
if (resized) {
var resp = vfs.ImportFile(local, CtxRelPath());
if (resp.Ok()) {
Log.Info("resized " + CtxRelPath());
} else {
Log.Error("could not write the resized image back: " + resp.ErrorMsg());
}
}
DelFile(local);Rewriting a file the user just uploaded surprises people
The user's client believes it uploaded a file; a moment later the bytes on the server are different, and a checksum they took locally no longer matches. If you do this, tell your users, and consider writing the derived image alongside the original under a different name instead of replacing it.