import { DOCS_GRAPHIC_DEFAULTS } from "./docs-graphic-types.ts" import { GRAPHIC_KEYBOARD_MIN_SIZE } from "./docs-graphic-keyboard.ts" /** Max frame width when inserting large photos into the page body. */ export const DOCS_IMAGE_INSERT_MAX_WIDTH_PX = 560 /** Max frame height when inserting very tall images. */ export const DOCS_IMAGE_INSERT_MAX_HEIGHT_PX = 720 export type ImageNaturalSize = { width: number height: number } /** Frame size that preserves the source aspect ratio, scaled down when needed. */ export function computeImageInsertFrameSize( naturalWidth: number, naturalHeight: number, options: { maxWidth?: number maxHeight?: number minSize?: number } = {} ): ImageNaturalSize { const maxWidth = options.maxWidth ?? DOCS_IMAGE_INSERT_MAX_WIDTH_PX const maxHeight = options.maxHeight ?? DOCS_IMAGE_INSERT_MAX_HEIGHT_PX const minSize = options.minSize ?? GRAPHIC_KEYBOARD_MIN_SIZE if (naturalWidth <= 0 || naturalHeight <= 0) { return { width: DOCS_GRAPHIC_DEFAULTS.width, height: DOCS_GRAPHIC_DEFAULTS.height, } } const scale = Math.min(1, maxWidth / naturalWidth, maxHeight / naturalHeight) let width = Math.max(minSize, Math.round(naturalWidth * scale)) let height = Math.max(minSize, Math.round(naturalHeight * scale)) // Keep ratio after integer rounding (derive height from width). height = Math.max(minSize, Math.round(width * (naturalHeight / naturalWidth))) if (height > maxHeight) { height = maxHeight width = Math.max(minSize, Math.round(height * (naturalWidth / naturalHeight))) } return { width, height } } /** Load intrinsic pixel dimensions for a data URL or remote image src. */ export function readImageNaturalSize(src: string): Promise { if (typeof Image === "undefined") { return Promise.resolve({ width: DOCS_GRAPHIC_DEFAULTS.width, height: DOCS_GRAPHIC_DEFAULTS.height, }) } return new Promise((resolve, reject) => { const img = new Image() img.onload = () => { resolve({ width: img.naturalWidth, height: img.naturalHeight, }) } img.onerror = () => reject(new Error("Failed to read image dimensions")) img.src = src }) }