ForgeTotal.js 5
de

Total.js 5

Bilder skalieren und konvertieren

Total.js 5 · total5@0.0.19 imagesthumbnailsgraphicsmagick Mit Total.js 5 ausgeführt

Total.js verarbeitet Bilder, indem es GraphicsMagick (gm) oder ImageMagick aufruft, die auf dem Server installiert sein müssen (brew install graphicsmagick, apt install graphicsmagick). Die Einstellung $imageconverter wählt das Programm: gm (Standard), im oder magick.

Image.load(filename) (oder ein Buffer oder ein Stream) gibt eine Kette zurück, die die Operationen aufzeichnet und beim Aufruf von .save(filename, callback) ausführt. Die nützlichen Operationen sind resize(width, height) (behält die Proportionen innerhalb des Rahmens), thumbnail(width, height) (eine schnelle, kleine Vorschau), miniature(width, height) (passt das Bild in den Rahmen ein und füllt den Rest mit dem Hintergrund), crop(width, height, x, y), rotate(degrees), grayscale(), blur(radius), quality(percentage) und output('jpg') zum Umwandeln des Formats. Hochgeladene Dateien gehen direkt: file.image() in einem Handler für @upload-Routen gibt dieselbe Kette zurück.

Die Größe zu lesen braucht kein GraphicsMagick: Image.measure('png', buffer) gibt { width, height } aus den ersten Bytes von PNG-, JPG-, GIF- und WebP-Daten zurück.

$.image(options) ist für eine Route gedacht, die ein Bild bei Bedarf erzeugt: ext ist das Format, load(next) übergibt die Quelle (einen Stream oder einen Pfad) mit next(...), image(img) beschreibt die Operationen und cache ist ein Name, unter dem das Ergebnis in tmp/ für die nächsten Anfragen aufbewahrt wird.

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);
		}
	});
}