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;
}
}

View File

@@ -61,6 +61,8 @@ const uploadPlaceholder = new Plugin({
const img = document.createElement("img");
img.src = URL.createObjectURL(action.add.file);
img.width = action.add.dimensions?.width;
img.height = action.add.dimensions?.height;
element.appendChild(img);
@@ -77,6 +79,8 @@ const uploadPlaceholder = new Plugin({
video.src = URL.createObjectURL(action.add.file);
video.autoplay = false;
video.controls = false;
video.width = action.add.dimensions?.width;
video.height = action.add.dimensions?.height;
element.appendChild(video);

View File

@@ -47,7 +47,7 @@ const uploadPlugin = (options: Options) =>
}
const pos = tr.selection.from;
insertFiles(view, event, pos, files, options);
void insertFiles(view, event, pos, files, options);
return true;
},
drop(view, event: DragEvent): boolean {
@@ -71,7 +71,7 @@ const uploadPlugin = (options: Options) =>
});
if (result) {
insertFiles(view, event, result.pos, files, options);
void insertFiles(view, event, result.pos, files, options);
return true;
}