hdr-canvas 0.0.8 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +79 -5
- package/dist/hdr-canvas.cjs +23 -18
- package/dist/hdr-canvas.cjs.map +1 -1
- package/dist/hdr-canvas.d.ts +22 -0
- package/dist/hdr-canvas.js +23 -18
- package/dist/hdr-canvas.js.map +1 -1
- package/dist/hdr-canvas.min.js +1 -1
- package/dist/hdr-canvas.min.js.map +1 -1
- package/package.json +8 -8
- package/src/Uint16Image.ts +17 -34
- package/src/hdr-canvas.ts +2 -0
- package/src/hdr-check.ts +13 -15
- package/src/index.ts +1 -5
- package/src/{@types → types}/HDRCanvas.d.ts +4 -5
- package/three/HDRWebGPUBackend.js +2 -2
- package/three/HDRWebGPURenderer.js +2 -2
package/README.md
CHANGED
@@ -4,6 +4,8 @@ This module contains a collection of functions and classes to work with the HDR
|
|
4
4
|
|
5
5
|
**This should only be considered as proof of concept or alpha code, don't use it in production environments!**
|
6
6
|
|
7
|
+
**Even if the display of HDR images works, the HDR support for the `canvas` element needs the browser flag `enable-experimental-web-platform-features` to be enabled. For example, open chrome://flags#enable-experimental-web-platform-features in Chrome to activate it.**
|
8
|
+
|
7
9
|
**Especially operations on the `ImageData` arrays are not optimized, e.g. quite slow.**
|
8
10
|
|
9
11
|
# Feature detection
|
@@ -44,6 +46,8 @@ if (checkHDRCanvas()) {
|
|
44
46
|
|
45
47
|
# Canvas
|
46
48
|
|
49
|
+
**Note: Currently the Chrome flag `enable-experimental-web-platform-features` needs to be enabled to have HDR support for the `canvas` element. You need to tell your visitors about that.**
|
50
|
+
|
47
51
|
The HDR `canvas` support is activated by initializing a canvas context using the following snippet:
|
48
52
|
|
49
53
|
```javascript
|
@@ -51,7 +55,7 @@ const colorSpace = "rec2100-hlg";
|
|
51
55
|
canvas.configureHighDynamicRange({ mode: "extended" });
|
52
56
|
const ctx = canvas.getContext("2d", {
|
53
57
|
colorSpace: colorSpace,
|
54
|
-
pixelFormat: "float16"
|
58
|
+
pixelFormat: "float16"
|
55
59
|
});
|
56
60
|
```
|
57
61
|
|
@@ -63,6 +67,31 @@ The snippet above is also available as function:
|
|
63
67
|
import { initHDRCanvas } from "hdr-canvas";
|
64
68
|
```
|
65
69
|
|
70
|
+
## Implicit Canvas setup
|
71
|
+
|
72
|
+
It's now also possible to use a HDR enabled Canvas by wrapping the browser internal `getContext()` function, by calling `defaultGetContextHDR()`.
|
73
|
+
|
74
|
+
```
|
75
|
+
import {defaultGetContextHDR, checkHDR, checkHDRCanvas} from 'hdr-canvas';
|
76
|
+
|
77
|
+
if (checkHDR() && checkHDRCanvas()) {
|
78
|
+
defaultGetContextHDR();
|
79
|
+
console.log('Enabled HDR Canvas');
|
80
|
+
}
|
81
|
+
```
|
82
|
+
|
83
|
+
**Note:** This example wraps the call to `defaultGetContextHDR()` into a check (`checkHDR() && checkHDRCanvas()`), because calling the function in a browser that isn't HDR-capable will break every subsequent call to `getContext()`.
|
84
|
+
|
85
|
+
## Resetting default HDR canvas
|
86
|
+
|
87
|
+
Use the method `resetGetContext()` to undo the changes by `defaultGetContextHDR()`.
|
88
|
+
|
89
|
+
```
|
90
|
+
import {resetGetContext} from 'hdr-canvas';
|
91
|
+
|
92
|
+
resetGetContext();
|
93
|
+
```
|
94
|
+
|
66
95
|
## Importing `Uint16Image`
|
67
96
|
|
68
97
|
Afterwards one can use [ImageData](https://developer.mozilla.org/en-US/docs/Web/API/ImageData) with a `float16` array, first the `Uint16Image` needs to be imported:
|
@@ -73,7 +102,7 @@ import { Uint16Image } from "hdr-canvas";
|
|
73
102
|
|
74
103
|
## Example: Loading an image
|
75
104
|
|
76
|
-
|
105
|
+
This example assumes `image` to be a [HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement) including an existing image.
|
77
106
|
|
78
107
|
```javascript
|
79
108
|
const offscreen = new OffscreenCanvas(image.width, image.height);
|
@@ -96,21 +125,66 @@ ctx.putImageData(rec210hglImage.getImageData(), 0, 0);
|
|
96
125
|
|
97
126
|
**Note**: Make sure to have Three.js added as a dependency.
|
98
127
|
|
99
|
-
This is just a drop
|
128
|
+
This is just a drop-in-replacement for the regular `WebGPURenderer` of Three.js.
|
100
129
|
|
101
130
|
```javascript
|
102
131
|
import HDRWebGPURenderer from "hdr-canvas/three/HDRWebGPURenderer.js";
|
103
132
|
```
|
104
133
|
|
134
|
+
**Note:** Starting Three.js 167 the WebGPU renderer is the new default renderer. This has several consequences for the required imports. Use this import instead of the official one and if your using Vite _don't_ provide an import map of resolver alias configuration.
|
135
|
+
|
136
|
+
```
|
137
|
+
import * as THREE from 'three/src/Three.js';
|
138
|
+
```
|
139
|
+
|
105
140
|
Use it as you'll do with a `WebGPURenderer`.
|
106
141
|
|
107
142
|
```javascript
|
108
143
|
renderer = new HDRWebGPURenderer({ canvas: canvas, antialias: true });
|
109
144
|
```
|
110
145
|
|
111
|
-
|
146
|
+
## Updating textures
|
147
|
+
|
148
|
+
Starting from Three.js version 167 you need to fix imported UHDR Textures, otherwise they will appear black:
|
149
|
+
|
150
|
+
```
|
151
|
+
model = gltf.scene;
|
152
|
+
model.traverse((element) => {
|
153
|
+
if (element?.material?.type != undefined) {
|
154
|
+
let targetMaterial = new THREE.MeshBasicMaterial();
|
155
|
+
THREE.MeshBasicMaterial.prototype.copy.call(targetMaterial, element.material);
|
156
|
+
element.material = targetMaterial;
|
157
|
+
}
|
158
|
+
});
|
159
|
+
scene.add(model);
|
160
|
+
```
|
161
|
+
|
162
|
+
## Compatibility
|
163
|
+
|
164
|
+
This currently doesn't work with Firefox, due to missing support for HDR and only partial WebGPU support.
|
165
|
+
One can import `WebGPU` and use also a HDR check to guard from errors:
|
166
|
+
|
167
|
+
```
|
168
|
+
import WebGPU from 'hdr-canvas/three/WebGPU.js';
|
169
|
+
```
|
170
|
+
|
171
|
+
Only use the provided renderer if the browser supports WebGPU and HDR:
|
172
|
+
|
173
|
+
```
|
174
|
+
if (WebGPU.isAvailable() && checkHDRCanvas()) {
|
175
|
+
renderer = new HDRWebGPURenderer({canvas: canvas, antialias: true});
|
176
|
+
} else {
|
177
|
+
renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
|
178
|
+
}
|
179
|
+
```
|
180
|
+
|
181
|
+
# Examples
|
182
|
+
|
183
|
+
All examples requires a Chromium based browser (like Chrome, Edge, Opera and Brave) and a HDR-enable monitor.
|
112
184
|
|
113
|
-
|
185
|
+
- [Contrast enhancement for UV images using HDR](https://christianmahnke.de/en/post/hdr-image-analysis/)
|
186
|
+
- [HDR IIIF](https://christianmahnke.de/en/post/hdr-iiif/)
|
187
|
+
- [Ultraviolet Photogrammetry](https://christianmahnke.de/en/post/uv-photogrammetry/)
|
114
188
|
|
115
189
|
---
|
116
190
|
|
package/dist/hdr-canvas.cjs
CHANGED
@@ -5752,6 +5752,18 @@ Color.extend(interpolation);
|
|
5752
5752
|
Color.extend(contrastMethods);
|
5753
5753
|
|
5754
5754
|
class Uint16Image {
|
5755
|
+
height;
|
5756
|
+
width;
|
5757
|
+
data;
|
5758
|
+
static DEFAULT_COLORSPACE = "rec2100-hlg";
|
5759
|
+
static SDR_MULTIPLIER = 2 ** 16 - 1;
|
5760
|
+
static COLORSPACES = {
|
5761
|
+
"rec2100-hlg": "rec2100hlg",
|
5762
|
+
"display-p3": "p3",
|
5763
|
+
srgb: "sRGB",
|
5764
|
+
"rec2100-pq": "rec2100pq"
|
5765
|
+
};
|
5766
|
+
colorSpace;
|
5755
5767
|
constructor(width, height, colorspace) {
|
5756
5768
|
if (colorspace === undefined || colorspace === null) {
|
5757
5769
|
this.colorSpace = Uint16Image.DEFAULT_COLORSPACE;
|
@@ -5793,10 +5805,12 @@ class Uint16Image {
|
|
5793
5805
|
if (this.data === undefined || this.data === null) {
|
5794
5806
|
return null;
|
5795
5807
|
}
|
5796
|
-
return new ImageData(this.data, this.width, this.height, {
|
5808
|
+
return new ImageData(this.data, this.width, this.height, {
|
5809
|
+
colorSpace: this.colorSpace
|
5810
|
+
});
|
5797
5811
|
}
|
5798
5812
|
static convertPixelToRec2100_hlg(pixel) {
|
5799
|
-
const colorJScolorSpace =
|
5813
|
+
const colorJScolorSpace = Uint16Image.COLORSPACES["rec2100-hlg"];
|
5800
5814
|
const srgbColor = new Color("srgb", Array.from(pixel.slice(0, 3)).map((band) => {
|
5801
5815
|
return band / 255;
|
5802
5816
|
}), pixel[3] / 255);
|
@@ -5831,11 +5845,11 @@ class Uint16Image {
|
|
5831
5845
|
const { width, height } = bitmap;
|
5832
5846
|
const offscreen = new OffscreenCanvas(width, height);
|
5833
5847
|
const ctx = offscreen.getContext("2d");
|
5834
|
-
ctx
|
5848
|
+
ctx?.drawImage(bitmap, 0, 0);
|
5835
5849
|
return ctx;
|
5836
5850
|
})
|
5837
5851
|
.then((ctx) => {
|
5838
|
-
return ctx
|
5852
|
+
return ctx?.getImageData(0, 0, ctx?.canvas.width, ctx?.canvas.height);
|
5839
5853
|
});
|
5840
5854
|
}
|
5841
5855
|
static fromImageData(imageData) {
|
@@ -5878,22 +5892,13 @@ class Uint16Image {
|
|
5878
5892
|
return i;
|
5879
5893
|
}
|
5880
5894
|
}
|
5881
|
-
Uint16Image.DEFAULT_COLORSPACE = "rec2100-hlg";
|
5882
|
-
Uint16Image.SDR_MULTIPLIER = 2 ** 16 - 1;
|
5883
|
-
Uint16Image.COLORSPACES = {
|
5884
|
-
"rec2100-hlg": "rec2100hlg",
|
5885
|
-
"display-p3": "p3",
|
5886
|
-
srgb: "sRGB",
|
5887
|
-
"rec2100-pq": "rec2100pq",
|
5888
|
-
};
|
5889
5895
|
|
5890
5896
|
function checkHDR() {
|
5891
5897
|
try {
|
5892
5898
|
const bitsPerChannel = screen.colorDepth / 3;
|
5893
5899
|
const hdrSupported = bitsPerChannel > 8;
|
5894
5900
|
const dynamicRangeHighMQ = window.matchMedia("(dynamic-range: high)").matches;
|
5895
|
-
const colorGamutMQ = window.matchMedia("(color-gamut: rec2020)").matches ||
|
5896
|
-
window.matchMedia("(color-gamut: p3)").matches;
|
5901
|
+
const colorGamutMQ = window.matchMedia("(color-gamut: rec2020)").matches || window.matchMedia("(color-gamut: p3)").matches;
|
5897
5902
|
if (colorGamutMQ && dynamicRangeHighMQ) {
|
5898
5903
|
if (bitsPerChannel !== Math.round(bitsPerChannel)) {
|
5899
5904
|
return false;
|
@@ -5919,17 +5924,17 @@ function checkHDRCanvas() {
|
|
5919
5924
|
if (!canvas.getContext) {
|
5920
5925
|
return false;
|
5921
5926
|
}
|
5922
|
-
const ctx =
|
5927
|
+
const ctx = canvas.getContext("2d", {
|
5923
5928
|
colorSpace: colorSpace,
|
5924
|
-
pixelFormat: "float16"
|
5925
|
-
})
|
5929
|
+
pixelFormat: "float16"
|
5930
|
+
});
|
5926
5931
|
if (ctx === null) {
|
5927
5932
|
return false;
|
5928
5933
|
}
|
5929
5934
|
return true;
|
5930
5935
|
}
|
5931
5936
|
catch (e) {
|
5932
|
-
console.error("Bad canvas ColorSpace test"
|
5937
|
+
console.error("Bad canvas ColorSpace test - make sure that the Chromium browser flag 'enable-experimental-web-platform-features' has been enabled");
|
5933
5938
|
return false;
|
5934
5939
|
}
|
5935
5940
|
}
|