From 12ea378b022dcee365fdc8ce60a77ed4c27aa9ea Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 8 Feb 2020 20:35:26 +0100 Subject: [PATCH] Photo uploader: reduce client memory usage. To create inline thumbnails locally, the previous version of the photo uploader used base64 representations of the local files to be uploaded. While this is effective, it is a little wasteful. When uploading several photos at once, this could even lead to the page becoming less responsive. This commit changes the process such that the photos are actually resized on a canvas, only using the local original as a buffer. Hence, only the resized photo is retained in memory. --- public/js/upload_queue.js | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/public/js/upload_queue.js b/public/js/upload_queue.js index dcec335..75b237d 100644 --- a/public/js/upload_queue.js +++ b/public/js/upload_queue.js @@ -45,9 +45,8 @@ UploadQueue.prototype.addPreviewForFile = function(file, index, callback) { return false; } - var preview = document.createElement('img'); + var preview = document.createElement('canvas'); preview.title = file.name; - preview.style.maxHeight = '150px'; var preview_box = document.getElementById('upload_preview_' + index); preview_box.appendChild(preview); @@ -55,12 +54,34 @@ UploadQueue.prototype.addPreviewForFile = function(file, index, callback) { var reader = new FileReader(); var that = this; reader.addEventListener('load', function() { - preview.src = reader.result; - if (callback) { - preview.addEventListener('load', function() { + var original = document.createElement('img'); + original.src = reader.result; + + original.addEventListener('load', function() { + // Preparation: make canvas size proportional to the original image. + preview.height = 150; + preview.width = preview.height * (original.width / original.height); + + // First pass: resize to 50% on temp canvas. + var temp = document.createElement('canvas'), + tempCtx = temp.getContext('2d'); + + temp.width = original.width * 0.5; + temp.height = original.height * 0.5; + tempCtx.drawImage(original, 0, 0, temp.width, temp.height); + + // Second pass: resize again on temp canvas. + tempCtx.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5); + + // Final pass: resize to desired size on preview canvas. + var context = preview.getContext('2d'); + context.drawImage(temp, 0, 0, temp.width * 0.5, temp.height * 0.5, + 0, 0, preview.width, preview.height); + + if (callback) { callback(); - }); - } + } + }); }, false); reader.readAsDataURL(file); };