Redimensionează și convertește imagini
Total.js procesează imaginile apelând GraphicsMagick (gm) sau ImageMagick, care trebuie să fie instalate pe server (brew install graphicsmagick, apt install graphicsmagick). Setarea $imageconverter alege programul: gm (implicit), im sau magick.
Image.load(filename) (sau un Buffer ori un stream) returnează un lanț care înregistrează operațiile și le execută când apelezi .save(filename, callback). Operațiile utile sunt resize(width, height) (păstrează proporțiile în interiorul cadrului), thumbnail(width, height) (o previzualizare mică și rapidă), miniature(width, height) (încadrează imaginea și umple restul cu fundalul), crop(width, height, x, y), rotate(degrees), grayscale(), blur(radius), quality(percentage) și output('jpg') pentru a converti formatul. Cu fișierele încărcate se face direct: file.image() într-un handler de rute @upload returnează același lanț.
Citirea dimensiunilor nu are nevoie de GraphicsMagick: Image.measure('png', buffer) returnează { width, height } din primii octeți ai datelor PNG, JPG, GIF și WebP.
$.image(options) este pentru o rută care creează o imagine la cerere: ext este formatul, load(next) predă sursa (un stream sau o cale) cu next(...), image(img) descrie operațiile, iar cache este numele sub care rezultatul este păstrat în tmp/ pentru cererile următoare.
const Zlib = require('zlib');
const Fs = require('fs');
exports.install = function() {
ROUTE('GET /resize/', resize);
ROUTE('GET /thumb/', thumb);
};
// Builds a solid red PNG so that the example needs no file
function makepng(width, height) {
function chunk(type, data) {
var length = Buffer.alloc(4);
length.writeUInt32BE(data.length);
var body = Buffer.concat([Buffer.from(type), data]);
var crc = Buffer.alloc(4);
crc.writeUInt32BE(Zlib.crc32(body));
return Buffer.concat([length, body, crc]);
}
var header = Buffer.alloc(13);
header.writeUInt32BE(width, 0);
header.writeUInt32BE(height, 4);
header[8] = 8; // bit depth
header[9] = 2; // RGB
var row = Buffer.alloc(1 + width * 3);
for (var x = 0; x < width; x++)
row[1 + x * 3] = 255;
var raw = Buffer.concat(Array(height).fill(row));
return Buffer.concat([
Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
chunk('IHDR', header),
chunk('IDAT', Zlib.deflateSync(raw)),
chunk('IEND', Buffer.alloc(0))
]);
}
function source() {
var filename = PATH.tmp('source.png');
Fs.writeFileSync(filename, makepng(200, 100));
return filename;
}
function resize($) {
var target = PATH.tmp('small.jpg');
Image.load(source()).resize(50, 50).output('jpg').save(target, function(err) {
if (err) {
$.invalid(err);
return;
}
var size = Image.measure('jpg', Fs.readFileSync(target));
$.json({ width: size.width, height: size.height, original: Image.measure('png', Fs.readFileSync(source())) });
});
}
function thumb($) {
$.image({
ext: 'png',
cache: 'thumb-example',
load: function(next) {
next(Fs.createReadStream(source()));
},
image: function(img) {
img.resize(40, 40);
}
});
}