fix: Size of inserted retina images (#6350)

* Fix pasted size of retina images

* lint

* lint
This commit is contained in:
Tom Moor
2024-01-05 19:17:39 -08:00
committed by GitHub
parent 47c13c9916
commit 89d905ebb7
10 changed files with 127 additions and 22 deletions

View File

@@ -1,3 +1,5 @@
import extract from "png-chunks-extract";
export default class FileHelper {
/**
* Checks if a file is an image.
@@ -31,6 +33,7 @@ export default class FileHelper {
return new Promise((resolve, reject) => {
const video = document.createElement("video");
video.preload = "metadata";
video.crossOrigin = "anonymous";
video.onloadedmetadata = () => {
window.URL.revokeObjectURL(video.src);
resolve({ width: video.videoWidth, height: video.videoHeight });
@@ -39,4 +42,60 @@ export default class FileHelper {
video.src = URL.createObjectURL(file);
});
}
/**
* Loads the dimensions of an image file currently only PNGs are supported but we mainly use
* this to get the "real" dimensions of a retina image.
*
* @param file The file to load the dimensions for
* @returns The dimensions of the image, if known.
*/
static async getImageDimensions(
file: File
): Promise<{ width: number; height: number } | undefined> {
if (file.type !== "image/png") {
return;
}
function parsePhys(view: DataView) {
return {
ppux: view.getUint32(0),
ppuy: view.getUint32(4),
unit: view.getUint8(4),
};
}
function parseIHDR(view: DataView) {
return {
width: view.getUint32(0),
height: view.getUint32(4),
};
}
try {
const buffer = await file.arrayBuffer();
const chunks = extract(new Uint8Array(buffer));
const pHYsChunk = chunks.find((chunk) => chunk.name === "pHYs");
const iHDRChunk = chunks.find((chunk) => chunk.name === "IHDR");
if (!pHYsChunk || !iHDRChunk) {
return;
}
const idhrData = parseIHDR(new DataView(iHDRChunk.data.buffer));
const physData = parsePhys(new DataView(pHYsChunk.data.buffer));
if (physData.unit === 0 && physData.ppux === physData.ppuy) {
const pixelRatio = Math.round(physData.ppux / 2834.5);
return {
width: idhrData.width / pixelRatio,
height: idhrData.height / pixelRatio,
};
}
} catch {
return undefined;
}
return undefined;
}
}