From 851280fa847368c1f9c0e46e7523fa2ae3769864 Mon Sep 17 00:00:00 2001 From: kuuuube Date: Thu, 26 Dec 2024 17:53:46 -0500 Subject: [PATCH] Fix low quality image resizing --- ext/js/dictionary/dictionary-database.js | 6 +++--- ext/js/display/structured-content-generator.js | 10 +++++++++- types/ext/dictionary-database.d.ts | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ext/js/dictionary/dictionary-database.js b/ext/js/dictionary/dictionary-database.js index 98347de52..5da2cd064 100644 --- a/ext/js/dictionary/dictionary-database.js +++ b/ext/js/dictionary/dictionary-database.js @@ -462,7 +462,7 @@ export class DictionaryDatabase { } else { const image = new Blob([m.content], {type: m.mediaType}); // eslint-disable-next-line no-undef - await createImageBitmap(image).then((decodedImage) => { + await createImageBitmap(image, {resizeWidth: m.canvasWidth, resizeHeight: m.canvasHeight, resizeQuality: 'high'}).then((decodedImage) => { // we need to do a dumb hack where we convert this ImageBitmap to an ImageData by drawing it to a temporary canvas, because Firefox doesn't support transferring ImageBitmaps cross-process const canvas = new OffscreenCanvas(decodedImage.width, decodedImage.height); const ctx = canvas.getContext('2d'); @@ -815,9 +815,9 @@ export class DictionaryDatabase { * @param {import('dictionary-database').FindMultiBulkData} data * @returns {import('dictionary-database').DrawMedia} */ - _createDrawMedia(row, {itemIndex: index, item: {canvasIndexes, canvasWidth, generation}}) { + _createDrawMedia(row, {itemIndex: index, item: {canvasIndexes, canvasWidth, canvasHeight, generation}}) { const {dictionary, path, mediaType, width, height, content} = row; - return {index, dictionary, path, mediaType, width, height, content, canvasIndexes, canvasWidth, generation}; + return {index, dictionary, path, mediaType, width, height, content, canvasIndexes, canvasWidth, canvasHeight, generation}; } /** diff --git a/ext/js/display/structured-content-generator.js b/ext/js/display/structured-content-generator.js index 0f83902a0..6ff8cf12f 100644 --- a/ext/js/display/structured-content-generator.js +++ b/ext/js/display/structured-content-generator.js @@ -131,7 +131,15 @@ export class StructuredContentGenerator { const image = this._contentManager instanceof DisplayContentManager ? /** @type {HTMLCanvasElement} */ (this._createElement('canvas', 'gloss-image')) : /** @type {HTMLImageElement} */ (this._createElement('img', 'gloss-image')); - image.width = width; + if (sizeUnits === 'em' && (hasPreferredWidth || hasPreferredHeight)) { + const emSize = 14; // We could Number.parseFloat(getComputedStyle(document.documentElement).fontSize); here for more accuracy but it would cause a layout and be extremely slow; possible improvement would be to calculate and cache the value + const scaleFactor = 2 * window.devicePixelRatio; + image.style.width = `${usedWidth}em`; + image.style.height = `${usedWidth * invAspectRatio}em`; + image.width = usedWidth * emSize * scaleFactor; + } else { + image.width = usedWidth; + } image.height = image.width * invAspectRatio; // Anki will not render images correctly without specifying to use 100% width and height diff --git a/types/ext/dictionary-database.d.ts b/types/ext/dictionary-database.d.ts index 69078c114..33aaf7ade 100644 --- a/types/ext/dictionary-database.d.ts +++ b/types/ext/dictionary-database.d.ts @@ -40,7 +40,7 @@ type MediaType = ArrayBuffer | string | null; export type Media = {index: number} & MediaDataBase; -export type DrawMedia = {index: number} & MediaDataBase & {canvasWidth: number, canvasIndexes: number[], generation: number}; +export type DrawMedia = {index: number} & MediaDataBase & {canvasWidth: number, canvasHeight: number, canvasIndexes: number[], generation: number}; export type DatabaseTermEntry = { expression: string;