import { Uint16Image } from "./Uint16Image";
import { getBrowserVersion } from "./browser-util";
import type { HDRHTMLCanvasElement, CanvasRenderingContext2DHDRSettings, CanvasRenderingContext2DHDR } from "./types/HDRCanvas.d.ts";
/**
* Gets a `CanvasRenderingContext2DSettings` object configured for HDR.
* This function detects the browser version to determine the appropriate `colorType` for HDR support.
*
* @returns {CanvasRenderingContext2DHDRSettings} An options object for creating an HDR canvas context.
*/
export function getHdrOptions(): CanvasRenderingContext2DHDRSettings {
const hdrOptions: CanvasRenderingContext2DHDRSettings = { colorSpace: Uint16Image.DEFAULT_COLORSPACE };
const browserMajorVersion = getBrowserVersion();
if (browserMajorVersion == null) {
console.warn(`Unsupported / untested browser (${navigator.userAgent}) detected - using more modern defaults`);
hdrOptions["colorType"] = "float16";
} else {
if (browserMajorVersion < 134) {
console.warn("Older Chrome / chromium based browser detected, using older `pixelFormat`");
} else {
hdrOptions["pixelFormat"] = "float16";
}
}
return hdrOptions;
}
/**
* Initializes a given `HTMLCanvasElement` for HDR and returns its 2D rendering context.
* It first configures the canvas for high dynamic range and then gets the 2D context with HDR options.
*
* @param {HDRHTMLCanvasElement} canvas - The canvas element to initialize.
* @returns {CanvasRenderingContext2DHDR | null} The 2D rendering context, or `null` if the context cannot be created. Can be cast down to `CanvasRenderingContext2D` or `RenderingContext`
*/
export function initHDRCanvas(canvas: HDRHTMLCanvasElement): CanvasRenderingContext2DHDR | null {
canvas.configureHighDynamicRange({ mode: "extended" });
const ctx = canvas.getContext("2d", getHdrOptions());
return ctx as CanvasRenderingContext2DHDR;
}
/**
* Patches the `getContext` method of `HTMLCanvasElement` to default to HDR settings.
* This allows all subsequent calls to `getContext('2d')` to be HDR-enabled without
* explicitly passing the HDR options.
*
* @remarks
* This function modifies the global `HTMLCanvasElement.prototype` and should be used with caution.
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
export function defaultGetContextHDR() {
(HTMLCanvasElement.prototype as HDRHTMLCanvasElement)._getContext = HTMLCanvasElement.prototype.getContext;
(HTMLCanvasElement.prototype as any).getContext = function (type: string, options: object) {
if (options !== undefined) {
options = Object.assign({}, options, getHdrOptions());
} else {
options = getHdrOptions();
}
return (this as HDRHTMLCanvasElement)._getContext(type, options);
};
}
/**
* Resets the `getContext` method of `HTMLCanvasElement` to its original behavior.
* This reverses the changes made by `defaultGetContextHDR`.
*
* @remarks
* This function only works if `defaultGetContextHDR` has been previously called.
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
export function resetGetContext() {
if (typeof (HTMLCanvasElement.prototype as HDRHTMLCanvasElement)._getContext === "function") {
HTMLCanvasElement.prototype.getContext = (HTMLCanvasElement.prototype as any)._getContext;
}
}
Source