# Αλλαγή μεγέθους και μετατροπή εικόνων

> Επεξεργαστείτε εικόνες με το Image.load(), συνδέστε λειτουργίες μεγέθους, περικοπής και μορφής, αποθηκεύστε το αποτέλεσμα, μετρήστε το μέγεθός του και σερβίρετε μικρογραφίες με το $.image().

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: el
Content-SHA256: a74b9d6c606f11a98948f65778c5df8da7bedec33a8ef16311d9ba1a2985b45b
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

Το Total.js επεξεργάζεται εικόνες καλώντας το **GraphicsMagick** (`gm`) ή το ImageMagick, που πρέπει να είναι εγκατεστημένα στον διακομιστή (`brew install graphicsmagick`, `apt install graphicsmagick`). Η ρύθμιση `$imageconverter` επιλέγει το πρόγραμμα: `gm` (προεπιλογή), `im` ή `magick`.

Το `Image.load(filename)` (ή ένα `Buffer` ή ένα stream) επιστρέφει μια αλυσίδα που καταγράφει τις λειτουργίες και τις εκτελεί όταν καλέσετε το `.save(filename, callback)`. Οι χρήσιμες λειτουργίες είναι `resize(width, height)` (διατηρεί τις αναλογίες μέσα στο πλαίσιο), `thumbnail(width, height)` (μια γρήγορη, μικρή προεπισκόπηση), `miniature(width, height)` (χωράει την εικόνα στο πλαίσιο και γεμίζει το υπόλοιπο με το φόντο), `crop(width, height, x, y)`, `rotate(degrees)`, `grayscale()`, `blur(radius)`, `quality(percentage)` και `output('jpg')` για μετατροπή της μορφής. Με τα αρχεία που ανεβάζονται γίνεται απευθείας: το `file.image()` σε έναν χειριστή διαδρομών `@upload` επιστρέφει την ίδια αλυσίδα.

Για να διαβάσετε το μέγεθος δεν χρειάζεται GraphicsMagick: το `Image.measure('png', buffer)` επιστρέφει `{ width, height }` από τα πρώτα bytes δεδομένων PNG, JPG, GIF και WebP.

Το `$.image(options)` προορίζεται για μια διαδρομή που δημιουργεί μια εικόνα κατά απαίτηση: το `ext` είναι η μορφή, το `load(next)` παραδίδει την πηγή (ένα stream ή μια διαδρομή) με το `next(...)`, το `image(img)` περιγράφει τις λειτουργίες και το `cache` είναι ένα όνομα με το οποίο το αποτέλεσμα φυλάσσεται στο `tmp/` για τα επόμενα αιτήματα.

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