prevent png chunk parsing and image loading racing with each other

pull/21833/head
Bruno Windels 2019-04-09 12:32:44 +02:00
parent ea71970299
commit 774314badd
1 changed files with 19 additions and 19 deletions

View File

@ -101,48 +101,48 @@ function createThumbnail(element, inputWidth, inputHeight, mimeType) {
* @param {File} imageFile The file to load in an image element. * @param {File} imageFile The file to load in an image element.
* @return {Promise} A promise that resolves with the html image element. * @return {Promise} A promise that resolves with the html image element.
*/ */
function loadImageElement(imageFile) { async function loadImageElement(imageFile) {
const deferred = Promise.defer();
// Load the file into an html element // Load the file into an html element
const img = document.createElement("img"); const img = document.createElement("img");
const objectUrl = URL.createObjectURL(imageFile); const objectUrl = URL.createObjectURL(imageFile);
const imgPromise = new Promise((resolve, reject) => {
img.onload = function() {
URL.revokeObjectURL(objectUrl);
resolve(img);
};
img.onerror = function(e) {
reject(e);
};
});
img.src = objectUrl; img.src = objectUrl;
// check for hi-dpi PNGs and fudge display resolution as needed. // check for hi-dpi PNGs and fudge display resolution as needed.
// this is mainly needed for macOS screencaps // this is mainly needed for macOS screencaps
let hidpi = false; let parsePromise;
if (imageFile.type === "image/png") { if (imageFile.type === "image/png") {
// in practice macOS happens to order the chunks so they fall in // in practice macOS happens to order the chunks so they fall in
// the first 0x1000 bytes (thanks to a massive ICC header). // the first 0x1000 bytes (thanks to a massive ICC header).
// Thus we could slice the file down to only sniff the first 0x1000 // Thus we could slice the file down to only sniff the first 0x1000
// bytes (but this makes extractPngChunks choke on the corrupt file) // bytes (but this makes extractPngChunks choke on the corrupt file)
const headers = imageFile; //.slice(0, 0x1000); const headers = imageFile; //.slice(0, 0x1000);
readFileAsArrayBuffer(headers).then(arrayBuffer=>{ parsePromise = readFileAsArrayBuffer(headers).then(arrayBuffer => {
const buffer = new Uint8Array(arrayBuffer); const buffer = new Uint8Array(arrayBuffer);
const chunks = extractPngChunks(buffer); const chunks = extractPngChunks(buffer);
for (const chunk of chunks) { for (const chunk of chunks) {
if (chunk.name === 'pHYs') { if (chunk.name === 'pHYs') {
if (chunk.data.byteLength !== PHYS_HIDPI.length) return; if (chunk.data.byteLength !== PHYS_HIDPI.length) return;
hidpi = chunk.data.every((val, i) => val === PHYS_HIDPI[i]); const hidpi = chunk.data.every((val, i) => val === PHYS_HIDPI[i]);
return; return hidpi;
} }
} }
return false;
}); });
} }
// Once ready, create a thumbnail const [hidpi] = await Promise.all([parsePromise, imgPromise]);
img.onload = function() { const width = hidpi ? (img.width >> 1) : img.width;
URL.revokeObjectURL(objectUrl); const height = hidpi ? (img.height >> 1) : img.height;
const width = hidpi ? (img.width >> 1) : img.width; return {width, height, img};
const height = hidpi ? (img.height >> 1) : img.height;
deferred.resolve({ img, width, height });
};
img.onerror = function(e) {
deferred.reject(e);
};
return deferred.promise;
} }
/** /**