From 7c9ad975bbbcf8769f5e20c785ec87c12b343bcb Mon Sep 17 00:00:00 2001 From: lilia Date: Wed, 4 Mar 2015 18:25:16 -0800 Subject: [PATCH] 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 --- js/views/file_input_view.js | 57 +++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/js/views/file_input_view.js b/js/views/file_input_view.js index e0fcfd8e..a1fbc2d5 100644 --- a/js/views/file_input_view.js +++ b/js/views/file_input_view.js @@ -53,36 +53,45 @@ var Whisper = Whisper || {}; } return new Promise(function(resolve, reject) { - // components/blueimp-load-image - window.loadImage(file, resolve, { - maxWidth: 1920, - maxHeight: 1920, - canvas: true, - contain: true - }); - }).then(this.autoCompress.bind(this)); - }, + var url = URL.createObjectURL(file); + var img = document.createElement('img'); + img.onerror = reject; + img.onload = function () { + URL.revokeObjectURL(url); - autoCompress: function(canvas, numRetries, quality) { - if (numRetries === undefined) { numRetries = 3; } - if (quality === undefined) { quality = 0.95; } + var maxSize = 420 * 1024; + var maxHeight = 1920; + var maxWidth = 1920; + if (img.width <= maxWidth && img.height <= maxHeight && + file.size <= maxSize) { + resolve(file); + return; + } - var autoCompress = this.autoCompress.bind(this); + // loadImage.scale -> components/blueimp-load-image + var canvas = loadImage.scale(img, { + canvas: true, maxWidth: 1920, maxHeight: 1920 + }); - return new Promise(function(resolve, reject) { - canvas.toBlob(function(blob) { - var kb = blob.size/1024; - if (kb < 420 || numRetries === 0) { - resolve(blob); - } else { - quality = quality * 420 / kb; + var quality = 0.95; + var i = 4; + var blob; + do { + i = i - 1; + // dataURLtoBlob -> components/blueimp-canvas-to-blob + blob = dataURLtoBlob( + canvas.toDataURL('image/jpeg', quality) + ); + quality = quality * maxSize / blob.size; if (quality < 50) { quality = 50; - numRetries = 1; + i = 1; } - resolve(autoCompress(canvas, numRetries - 1, quality)); - } - }, 'image/jpeg', quality); + } while (i > 0 && blob.size > maxSize); + + resolve(blob); + }; + img.src = url; }); },