JAMES
LOPER

How to crop & reorient images before upload

Center crop to a square, reorient, and resize, callback as base64. Don't think I can make this any smaller.

function getOrientation(file, callback) {
	var reader = new FileReader();
	reader.onload = function(e) {
		var view = new DataView(e.target.result);
		if (view.getUint16(0, false) != 0xFFD8) return callback(-2);
		var length = view.byteLength, offset = 2;
		while (offset < length) {
			var marker = view.getUint16(offset, false);
			offset += 2;
			if (marker == 0xFFE1) {
				if (view.getUint32(offset += 2, false) != 0x45786966) return callback(-1);
				var little = view.getUint16(offset += 6, false) == 0x4949;
				offset += view.getUint32(offset + 4, little);
				var tags = view.getUint16(offset, little);
				offset += 2;
				for (var i = 0; i < tags; i++)
					if (view.getUint16(offset + (i * 12), little) == 0x0112)
						return callback(view.getUint16(offset + (i * 12) + 8, little));
			}
			else if ((marker & 0xFF00) != 0xFF00) break;
			else offset += view.getUint16(offset, false);
		}
		return callback(-1);
	};
	reader.readAsArrayBuffer(file);
}

function cropSquare(file, size, orient, callback) {
	var reader = new FileReader(), img = new Image();
	reader.onload = () => {img.src = reader.result};
	img.onload = function() {
		var x=0, y=0, w=img.width, h=img.height;
		var scale = size / Math.min(w,h);
		if (w > h) {x = (w - h) / 2} else {y = (h - w) / 2}
		var canvas = document.createElement('canvas');
		canvas.width = size; canvas.height = size;
		var ctx = canvas.getContext('2d');

		var rotate = {6:90, 3:180, 8:-90};
		if (rotate[orient]) {
			var offset = size/2;
			ctx.translate(offset, offset);
			ctx.rotate(Math.PI / 180 * rotate[orient]);
			ctx.translate(-offset, -offset);
		}

		ctx.drawImage(img, -x*scale, -y*scale, w*scale, h*scale);
		callback(canvas.toDataURL('image/jpeg'));
	}
	reader.readAsDataURL(file);
}

var Crop = {
	square(file, size, callback) {
		getOrientation(file, function(orient) {
			cropSquare(file, size, orient, callback);
		});
	},
};

export { Crop };