prevent png chunk parsing and image loading racing with each other
parent
ea71970299
commit
774314badd
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue