ForgeTotal.js 5
fr

Total.js 5

Redimensionner et convertir des images

Total.js 5 · total5@0.0.19 imagesthumbnailsgraphicsmagick Exécutée avec Total.js 5

Total.js traite les images en appelant GraphicsMagick (gm) ou ImageMagick, qui doivent être installés sur le serveur (brew install graphicsmagick, apt install graphicsmagick). Le réglage $imageconverter choisit le programme : gm (par défaut), im ou magick.

Image.load(filename) (ou un Buffer ou un flux) renvoie une chaîne qui enregistre les opérations et les exécute quand vous appelez .save(filename, callback). Les opérations utiles sont resize(width, height) (conserve les proportions dans le cadre), thumbnail(width, height) (un petit aperçu rapide), miniature(width, height) (fait tenir l'image dans le cadre et remplit le reste avec l'arrière-plan), crop(width, height, x, y), rotate(degrees), grayscale(), blur(radius), quality(percentage) et output('jpg') pour convertir le format. Les fichiers téléversés le font directement : file.image() dans un gestionnaire de routes @upload renvoie la même chaîne.

Lire la taille ne nécessite pas GraphicsMagick : Image.measure('png', buffer) renvoie { width, height } à partir des premiers octets de données PNG, JPG, GIF et WebP.

$.image(options) est destiné à une route qui crée une image à la demande : ext est le format, load(next) fournit la source (un flux ou un chemin) avec next(...), image(img) décrit les opérations et cache est le nom sous lequel le résultat est conservé dans tmp/ pour les requêtes suivantes.

controllers/images.js
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);
		}
	});
}