next-blurhash-previews 0.0.3-beta64 → 0.0.3-beta67
Sign up to get free protection for your applications and to get access to all the features.
- package/components/ImageWithPreview.tsx +13 -26
- package/imagePreviewBootstrap.js +16 -201
- package/package.json +1 -1
@@ -1,5 +1,3 @@
|
|
1
|
-
import { decode } from "blurhash/dist/esm";
|
2
|
-
|
3
1
|
type blurhash = { w: number; h: number; blurhash: string };
|
4
2
|
|
5
3
|
class ImageWithPreview extends HTMLElement {
|
@@ -81,28 +79,17 @@ function updateBlurHashPreview(canvasEl: HTMLCanvasElement, preview: blurhash) {
|
|
81
79
|
canvasEl.width = width;
|
82
80
|
canvasEl.height = height;
|
83
81
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
// const workerBlob = new Blob(
|
98
|
-
// [document.querySelector("#next-blurhash-worker-script")!.textContent!],
|
99
|
-
// { type: "text/javascript" }
|
100
|
-
// );
|
101
|
-
// worker = new Worker(window.URL.createObjectURL(workerBlob));
|
102
|
-
// }
|
103
|
-
// const offscreen = (canvasEl as any).transferControlToOffscreen();
|
104
|
-
// worker.postMessage({ canvas: offscreen, width, height, blurhash }, [
|
105
|
-
// offscreen,
|
106
|
-
// ]);
|
107
|
-
// }
|
82
|
+
if (true) {
|
83
|
+
if (!worker) {
|
84
|
+
const workerBlob = new Blob(
|
85
|
+
[document.querySelector("#next-blurhash-worker-script")!.textContent!],
|
86
|
+
{ type: "text/javascript" }
|
87
|
+
);
|
88
|
+
worker = new Worker(window.URL.createObjectURL(workerBlob));
|
89
|
+
}
|
90
|
+
const offscreen = (canvasEl as any).transferControlToOffscreen();
|
91
|
+
worker.postMessage({ canvas: offscreen, width, height, blurhash }, [
|
92
|
+
offscreen,
|
93
|
+
]);
|
94
|
+
}
|
108
95
|
}
|
package/imagePreviewBootstrap.js
CHANGED
@@ -5,199 +5,6 @@ export const imagePreviewBootstrap = createElement(
|
|
5
5
|
{},
|
6
6
|
createElement("script", {
|
7
7
|
dangerouslySetInnerHTML: { __html: `(() => { "use strict";
|
8
|
-
const digitCharacters = [
|
9
|
-
"0",
|
10
|
-
"1",
|
11
|
-
"2",
|
12
|
-
"3",
|
13
|
-
"4",
|
14
|
-
"5",
|
15
|
-
"6",
|
16
|
-
"7",
|
17
|
-
"8",
|
18
|
-
"9",
|
19
|
-
"A",
|
20
|
-
"B",
|
21
|
-
"C",
|
22
|
-
"D",
|
23
|
-
"E",
|
24
|
-
"F",
|
25
|
-
"G",
|
26
|
-
"H",
|
27
|
-
"I",
|
28
|
-
"J",
|
29
|
-
"K",
|
30
|
-
"L",
|
31
|
-
"M",
|
32
|
-
"N",
|
33
|
-
"O",
|
34
|
-
"P",
|
35
|
-
"Q",
|
36
|
-
"R",
|
37
|
-
"S",
|
38
|
-
"T",
|
39
|
-
"U",
|
40
|
-
"V",
|
41
|
-
"W",
|
42
|
-
"X",
|
43
|
-
"Y",
|
44
|
-
"Z",
|
45
|
-
"a",
|
46
|
-
"b",
|
47
|
-
"c",
|
48
|
-
"d",
|
49
|
-
"e",
|
50
|
-
"f",
|
51
|
-
"g",
|
52
|
-
"h",
|
53
|
-
"i",
|
54
|
-
"j",
|
55
|
-
"k",
|
56
|
-
"l",
|
57
|
-
"m",
|
58
|
-
"n",
|
59
|
-
"o",
|
60
|
-
"p",
|
61
|
-
"q",
|
62
|
-
"r",
|
63
|
-
"s",
|
64
|
-
"t",
|
65
|
-
"u",
|
66
|
-
"v",
|
67
|
-
"w",
|
68
|
-
"x",
|
69
|
-
"y",
|
70
|
-
"z",
|
71
|
-
"#",
|
72
|
-
"$",
|
73
|
-
"%",
|
74
|
-
"*",
|
75
|
-
"+",
|
76
|
-
",",
|
77
|
-
"-",
|
78
|
-
".",
|
79
|
-
":",
|
80
|
-
";",
|
81
|
-
"=",
|
82
|
-
"?",
|
83
|
-
"@",
|
84
|
-
"[",
|
85
|
-
"]",
|
86
|
-
"^",
|
87
|
-
"_",
|
88
|
-
"{",
|
89
|
-
"|",
|
90
|
-
"}",
|
91
|
-
"~"
|
92
|
-
];
|
93
|
-
const decode83 = (str) => {
|
94
|
-
let value = 0;
|
95
|
-
for (let i = 0; i < str.length; i++) {
|
96
|
-
const c = str[i];
|
97
|
-
const digit = digitCharacters.indexOf(c);
|
98
|
-
value = value * 83 + digit;
|
99
|
-
}
|
100
|
-
return value;
|
101
|
-
};
|
102
|
-
const sRGBToLinear = (value) => {
|
103
|
-
let v = value / 255;
|
104
|
-
if (v <= 0.04045) {
|
105
|
-
return v / 12.92;
|
106
|
-
} else {
|
107
|
-
return Math.pow((v + 0.055) / 1.055, 2.4);
|
108
|
-
}
|
109
|
-
};
|
110
|
-
const linearTosRGB = (value) => {
|
111
|
-
let v = Math.max(0, Math.min(1, value));
|
112
|
-
if (v <= 31308e-7) {
|
113
|
-
return Math.round(v * 12.92 * 255 + 0.5);
|
114
|
-
} else {
|
115
|
-
return Math.round((1.055 * Math.pow(v, 1 / 2.4) - 0.055) * 255 + 0.5);
|
116
|
-
}
|
117
|
-
};
|
118
|
-
const sign = (n) => n < 0 ? -1 : 1;
|
119
|
-
const signPow = (val, exp) => sign(val) * Math.pow(Math.abs(val), exp);
|
120
|
-
class ValidationError extends Error {
|
121
|
-
constructor(message) {
|
122
|
-
super(message);
|
123
|
-
this.name = "ValidationError";
|
124
|
-
this.message = message;
|
125
|
-
}
|
126
|
-
}
|
127
|
-
const validateBlurhash = (blurhash) => {
|
128
|
-
if (!blurhash || blurhash.length < 6) {
|
129
|
-
throw new ValidationError("The blurhash string must be at least 6 characters");
|
130
|
-
}
|
131
|
-
const sizeFlag = decode83(blurhash[0]);
|
132
|
-
const numY = Math.floor(sizeFlag / 9) + 1;
|
133
|
-
const numX = sizeFlag % 9 + 1;
|
134
|
-
if (blurhash.length !== 4 + 2 * numX * numY) {
|
135
|
-
throw new ValidationError(\`blurhash length mismatch: length is \${blurhash.length} but it should be \${4 + 2 * numX * numY}\`);
|
136
|
-
}
|
137
|
-
};
|
138
|
-
const decodeDC = (value) => {
|
139
|
-
const intR = value >> 16;
|
140
|
-
const intG = value >> 8 & 255;
|
141
|
-
const intB = value & 255;
|
142
|
-
return [sRGBToLinear(intR), sRGBToLinear(intG), sRGBToLinear(intB)];
|
143
|
-
};
|
144
|
-
const decodeAC = (value, maximumValue) => {
|
145
|
-
const quantR = Math.floor(value / (19 * 19));
|
146
|
-
const quantG = Math.floor(value / 19) % 19;
|
147
|
-
const quantB = value % 19;
|
148
|
-
const rgb = [
|
149
|
-
signPow((quantR - 9) / 9, 2) * maximumValue,
|
150
|
-
signPow((quantG - 9) / 9, 2) * maximumValue,
|
151
|
-
signPow((quantB - 9) / 9, 2) * maximumValue
|
152
|
-
];
|
153
|
-
return rgb;
|
154
|
-
};
|
155
|
-
const decode = (blurhash, width, height, punch) => {
|
156
|
-
validateBlurhash(blurhash);
|
157
|
-
punch = punch | 1;
|
158
|
-
const sizeFlag = decode83(blurhash[0]);
|
159
|
-
const numY = Math.floor(sizeFlag / 9) + 1;
|
160
|
-
const numX = sizeFlag % 9 + 1;
|
161
|
-
const quantisedMaximumValue = decode83(blurhash[1]);
|
162
|
-
const maximumValue = (quantisedMaximumValue + 1) / 166;
|
163
|
-
const colors = new Array(numX * numY);
|
164
|
-
for (let i = 0; i < colors.length; i++) {
|
165
|
-
if (i === 0) {
|
166
|
-
const value = decode83(blurhash.substring(2, 6));
|
167
|
-
colors[i] = decodeDC(value);
|
168
|
-
} else {
|
169
|
-
const value = decode83(blurhash.substring(4 + i * 2, 6 + i * 2));
|
170
|
-
colors[i] = decodeAC(value, maximumValue * punch);
|
171
|
-
}
|
172
|
-
}
|
173
|
-
const bytesPerRow = width * 4;
|
174
|
-
const pixels = new Uint8ClampedArray(bytesPerRow * height);
|
175
|
-
for (let y = 0; y < height; y++) {
|
176
|
-
for (let x = 0; x < width; x++) {
|
177
|
-
let r = 0;
|
178
|
-
let g = 0;
|
179
|
-
let b = 0;
|
180
|
-
for (let j = 0; j < numY; j++) {
|
181
|
-
for (let i = 0; i < numX; i++) {
|
182
|
-
const basis = Math.cos(Math.PI * x * i / width) * Math.cos(Math.PI * y * j / height);
|
183
|
-
let color = colors[i + j * numX];
|
184
|
-
r += color[0] * basis;
|
185
|
-
g += color[1] * basis;
|
186
|
-
b += color[2] * basis;
|
187
|
-
}
|
188
|
-
}
|
189
|
-
let intR = linearTosRGB(r);
|
190
|
-
let intG = linearTosRGB(g);
|
191
|
-
let intB = linearTosRGB(b);
|
192
|
-
pixels[4 * x + 0 + y * bytesPerRow] = intR;
|
193
|
-
pixels[4 * x + 1 + y * bytesPerRow] = intG;
|
194
|
-
pixels[4 * x + 2 + y * bytesPerRow] = intB;
|
195
|
-
pixels[4 * x + 3 + y * bytesPerRow] = 255;
|
196
|
-
}
|
197
|
-
}
|
198
|
-
return pixels;
|
199
|
-
};
|
200
|
-
var decode$1 = decode;
|
201
8
|
class ImageWithPreview extends HTMLElement {
|
202
9
|
sd;
|
203
10
|
mo;
|
@@ -258,6 +65,7 @@ class ImageWithPreview extends HTMLElement {
|
|
258
65
|
if (!customElements.get("blurhash-image")) {
|
259
66
|
customElements.define("blurhash-image", ImageWithPreview);
|
260
67
|
}
|
68
|
+
var worker;
|
261
69
|
function updateBlurHashPreview(canvasEl, preview) {
|
262
70
|
const {
|
263
71
|
w: width,
|
@@ -266,14 +74,21 @@ function updateBlurHashPreview(canvasEl, preview) {
|
|
266
74
|
} = preview;
|
267
75
|
canvasEl.width = width;
|
268
76
|
canvasEl.height = height;
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
77
|
+
{
|
78
|
+
if (!worker) {
|
79
|
+
const workerBlob = new Blob([document.querySelector("#next-blurhash-worker-script").textContent], {
|
80
|
+
type: "text/javascript"
|
81
|
+
});
|
82
|
+
worker = new Worker(window.URL.createObjectURL(workerBlob));
|
83
|
+
}
|
84
|
+
const offscreen = canvasEl.transferControlToOffscreen();
|
85
|
+
worker.postMessage({
|
86
|
+
canvas: offscreen,
|
87
|
+
width,
|
88
|
+
height,
|
89
|
+
blurhash
|
90
|
+
}, [offscreen]);
|
91
|
+
}
|
277
92
|
} })();` },
|
278
93
|
}),
|
279
94
|
createElement("script", {
|