Unravel image processing recursion and fix bugs

Although I find the previous implementation more elegant, it results in
a deeper nesting of Promises than necessary, which can make debugging
more complicated. The canvas scaling and compression apis are actually
synchronous, so the callback structure isn't really recessary here.
Converting to a loop also makes this process easier to understand at
a glance.

Fixed some bugs along the way:
* accidentally scaling small images up to 1920px
* jpeg compressing gifs and other formats even if unnecessary
This commit is contained in:
lilia 2015-03-04 18:25:16 -08:00
parent 0da04632f2
commit 7c9ad975bb

View file

@ -53,36 +53,45 @@ var Whisper = Whisper || {};
} }
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
// components/blueimp-load-image var url = URL.createObjectURL(file);
window.loadImage(file, resolve, { var img = document.createElement('img');
maxWidth: 1920, img.onerror = reject;
maxHeight: 1920, img.onload = function () {
canvas: true, URL.revokeObjectURL(url);
contain: true
var maxSize = 420 * 1024;
var maxHeight = 1920;
var maxWidth = 1920;
if (img.width <= maxWidth && img.height <= maxHeight &&
file.size <= maxSize) {
resolve(file);
return;
}
// loadImage.scale -> components/blueimp-load-image
var canvas = loadImage.scale(img, {
canvas: true, maxWidth: 1920, maxHeight: 1920
}); });
}).then(this.autoCompress.bind(this));
},
autoCompress: function(canvas, numRetries, quality) { var quality = 0.95;
if (numRetries === undefined) { numRetries = 3; } var i = 4;
if (quality === undefined) { quality = 0.95; } var blob;
do {
var autoCompress = this.autoCompress.bind(this); i = i - 1;
// dataURLtoBlob -> components/blueimp-canvas-to-blob
return new Promise(function(resolve, reject) { blob = dataURLtoBlob(
canvas.toBlob(function(blob) { canvas.toDataURL('image/jpeg', quality)
var kb = blob.size/1024; );
if (kb < 420 || numRetries === 0) { quality = quality * maxSize / blob.size;
resolve(blob);
} else {
quality = quality * 420 / kb;
if (quality < 50) { if (quality < 50) {
quality = 50; quality = 50;
numRetries = 1; i = 1;
} }
resolve(autoCompress(canvas, numRetries - 1, quality)); } while (i > 0 && blob.size > maxSize);
}
}, 'image/jpeg', quality); resolve(blob);
};
img.src = url;
}); });
}, },