next-blurhash-previews 0.0.3-beta73 → 0.0.3-beta76
Sign up to get free protection for your applications and to get access to all the features.
- package/imagePreviewBootstrap.js +2 -297
- package/package.json +1 -1
- package/vite.wc.config.ts +1 -1
- package/vite.worker.config.ts +1 -1
package/imagePreviewBootstrap.js
CHANGED
@@ -6,304 +6,9 @@ export const imagePreviewBootstrap = createElement(
|
|
6
6
|
createElement("script", {
|
7
7
|
id: "next-blurhash-worker-script",
|
8
8
|
type: "javascript/worker",
|
9
|
-
dangerouslySetInnerHTML: { __html: `(() => { "use strict";
|
10
|
-
const digitCharacters = [
|
11
|
-
"0",
|
12
|
-
"1",
|
13
|
-
"2",
|
14
|
-
"3",
|
15
|
-
"4",
|
16
|
-
"5",
|
17
|
-
"6",
|
18
|
-
"7",
|
19
|
-
"8",
|
20
|
-
"9",
|
21
|
-
"A",
|
22
|
-
"B",
|
23
|
-
"C",
|
24
|
-
"D",
|
25
|
-
"E",
|
26
|
-
"F",
|
27
|
-
"G",
|
28
|
-
"H",
|
29
|
-
"I",
|
30
|
-
"J",
|
31
|
-
"K",
|
32
|
-
"L",
|
33
|
-
"M",
|
34
|
-
"N",
|
35
|
-
"O",
|
36
|
-
"P",
|
37
|
-
"Q",
|
38
|
-
"R",
|
39
|
-
"S",
|
40
|
-
"T",
|
41
|
-
"U",
|
42
|
-
"V",
|
43
|
-
"W",
|
44
|
-
"X",
|
45
|
-
"Y",
|
46
|
-
"Z",
|
47
|
-
"a",
|
48
|
-
"b",
|
49
|
-
"c",
|
50
|
-
"d",
|
51
|
-
"e",
|
52
|
-
"f",
|
53
|
-
"g",
|
54
|
-
"h",
|
55
|
-
"i",
|
56
|
-
"j",
|
57
|
-
"k",
|
58
|
-
"l",
|
59
|
-
"m",
|
60
|
-
"n",
|
61
|
-
"o",
|
62
|
-
"p",
|
63
|
-
"q",
|
64
|
-
"r",
|
65
|
-
"s",
|
66
|
-
"t",
|
67
|
-
"u",
|
68
|
-
"v",
|
69
|
-
"w",
|
70
|
-
"x",
|
71
|
-
"y",
|
72
|
-
"z",
|
73
|
-
"#",
|
74
|
-
"$",
|
75
|
-
"%",
|
76
|
-
"*",
|
77
|
-
"+",
|
78
|
-
",",
|
79
|
-
"-",
|
80
|
-
".",
|
81
|
-
":",
|
82
|
-
";",
|
83
|
-
"=",
|
84
|
-
"?",
|
85
|
-
"@",
|
86
|
-
"[",
|
87
|
-
"]",
|
88
|
-
"^",
|
89
|
-
"_",
|
90
|
-
"{",
|
91
|
-
"|",
|
92
|
-
"}",
|
93
|
-
"~"
|
94
|
-
];
|
95
|
-
const decode83 = (str) => {
|
96
|
-
let value = 0;
|
97
|
-
for (let i = 0; i < str.length; i++) {
|
98
|
-
const c = str[i];
|
99
|
-
const digit = digitCharacters.indexOf(c);
|
100
|
-
value = value * 83 + digit;
|
101
|
-
}
|
102
|
-
return value;
|
103
|
-
};
|
104
|
-
const sRGBToLinear = (value) => {
|
105
|
-
let v = value / 255;
|
106
|
-
if (v <= 0.04045) {
|
107
|
-
return v / 12.92;
|
108
|
-
} else {
|
109
|
-
return Math.pow((v + 0.055) / 1.055, 2.4);
|
110
|
-
}
|
111
|
-
};
|
112
|
-
const linearTosRGB = (value) => {
|
113
|
-
let v = Math.max(0, Math.min(1, value));
|
114
|
-
if (v <= 31308e-7) {
|
115
|
-
return Math.round(v * 12.92 * 255 + 0.5);
|
116
|
-
} else {
|
117
|
-
return Math.round((1.055 * Math.pow(v, 1 / 2.4) - 0.055) * 255 + 0.5);
|
118
|
-
}
|
119
|
-
};
|
120
|
-
const sign = (n) => n < 0 ? -1 : 1;
|
121
|
-
const signPow = (val, exp) => sign(val) * Math.pow(Math.abs(val), exp);
|
122
|
-
class ValidationError extends Error {
|
123
|
-
constructor(message) {
|
124
|
-
super(message);
|
125
|
-
this.name = "ValidationError";
|
126
|
-
this.message = message;
|
127
|
-
}
|
128
|
-
}
|
129
|
-
const validateBlurhash = (blurhash) => {
|
130
|
-
if (!blurhash || blurhash.length < 6) {
|
131
|
-
throw new ValidationError("The blurhash string must be at least 6 characters");
|
132
|
-
}
|
133
|
-
const sizeFlag = decode83(blurhash[0]);
|
134
|
-
const numY = Math.floor(sizeFlag / 9) + 1;
|
135
|
-
const numX = sizeFlag % 9 + 1;
|
136
|
-
if (blurhash.length !== 4 + 2 * numX * numY) {
|
137
|
-
throw new ValidationError(\`blurhash length mismatch: length is \${blurhash.length} but it should be \${4 + 2 * numX * numY}\`);
|
138
|
-
}
|
139
|
-
};
|
140
|
-
const decodeDC = (value) => {
|
141
|
-
const intR = value >> 16;
|
142
|
-
const intG = value >> 8 & 255;
|
143
|
-
const intB = value & 255;
|
144
|
-
return [sRGBToLinear(intR), sRGBToLinear(intG), sRGBToLinear(intB)];
|
145
|
-
};
|
146
|
-
const decodeAC = (value, maximumValue) => {
|
147
|
-
const quantR = Math.floor(value / (19 * 19));
|
148
|
-
const quantG = Math.floor(value / 19) % 19;
|
149
|
-
const quantB = value % 19;
|
150
|
-
const rgb = [
|
151
|
-
signPow((quantR - 9) / 9, 2) * maximumValue,
|
152
|
-
signPow((quantG - 9) / 9, 2) * maximumValue,
|
153
|
-
signPow((quantB - 9) / 9, 2) * maximumValue
|
154
|
-
];
|
155
|
-
return rgb;
|
156
|
-
};
|
157
|
-
const decode = (blurhash, width, height, punch) => {
|
158
|
-
validateBlurhash(blurhash);
|
159
|
-
punch = punch | 1;
|
160
|
-
const sizeFlag = decode83(blurhash[0]);
|
161
|
-
const numY = Math.floor(sizeFlag / 9) + 1;
|
162
|
-
const numX = sizeFlag % 9 + 1;
|
163
|
-
const quantisedMaximumValue = decode83(blurhash[1]);
|
164
|
-
const maximumValue = (quantisedMaximumValue + 1) / 166;
|
165
|
-
const colors = new Array(numX * numY);
|
166
|
-
for (let i = 0; i < colors.length; i++) {
|
167
|
-
if (i === 0) {
|
168
|
-
const value = decode83(blurhash.substring(2, 6));
|
169
|
-
colors[i] = decodeDC(value);
|
170
|
-
} else {
|
171
|
-
const value = decode83(blurhash.substring(4 + i * 2, 6 + i * 2));
|
172
|
-
colors[i] = decodeAC(value, maximumValue * punch);
|
173
|
-
}
|
174
|
-
}
|
175
|
-
const bytesPerRow = width * 4;
|
176
|
-
const pixels = new Uint8ClampedArray(bytesPerRow * height);
|
177
|
-
for (let y = 0; y < height; y++) {
|
178
|
-
for (let x = 0; x < width; x++) {
|
179
|
-
let r = 0;
|
180
|
-
let g = 0;
|
181
|
-
let b = 0;
|
182
|
-
for (let j = 0; j < numY; j++) {
|
183
|
-
for (let i = 0; i < numX; i++) {
|
184
|
-
const basis = Math.cos(Math.PI * x * i / width) * Math.cos(Math.PI * y * j / height);
|
185
|
-
let color = colors[i + j * numX];
|
186
|
-
r += color[0] * basis;
|
187
|
-
g += color[1] * basis;
|
188
|
-
b += color[2] * basis;
|
189
|
-
}
|
190
|
-
}
|
191
|
-
let intR = linearTosRGB(r);
|
192
|
-
let intG = linearTosRGB(g);
|
193
|
-
let intB = linearTosRGB(b);
|
194
|
-
pixels[4 * x + 0 + y * bytesPerRow] = intR;
|
195
|
-
pixels[4 * x + 1 + y * bytesPerRow] = intG;
|
196
|
-
pixels[4 * x + 2 + y * bytesPerRow] = intB;
|
197
|
-
pixels[4 * x + 3 + y * bytesPerRow] = 255;
|
198
|
-
}
|
199
|
-
}
|
200
|
-
return pixels;
|
201
|
-
};
|
202
|
-
var decode$1 = decode;
|
203
|
-
addEventListener("message", (evt) => {
|
204
|
-
console.log(evt);
|
205
|
-
const { canvas, width, height, blurhash } = evt.data;
|
206
|
-
console.log("Encoding", blurhash);
|
207
|
-
const start = +new Date();
|
208
|
-
const pixels = decode$1(blurhash, width, height);
|
209
|
-
const ctx = canvas.getContext("2d");
|
210
|
-
const imageData = ctx.createImageData(width, height);
|
211
|
-
imageData.data.set(pixels);
|
212
|
-
ctx.putImageData(imageData, 0, 0);
|
213
|
-
const end = +new Date();
|
214
|
-
console.log("Done Encoding", blurhash, end - start);
|
215
|
-
}); })();` },
|
9
|
+
dangerouslySetInnerHTML: { __html: `(() => { "use strict";const I=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],u=t=>{let n=0;for(let o=0;o<t.length;o++){const e=t[o],c=I.indexOf(e);n=n*83+c}return n},D=t=>{let n=t/255;return n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)},b=t=>{let n=Math.max(0,Math.min(1,t));return n<=.0031308?Math.round(n*12.92*255+.5):Math.round((1.055*Math.pow(n,.4166666666666667)-.055)*255+.5)},P=t=>t<0?-1:1,p=(t,n)=>P(t)*Math.pow(Math.abs(t),n);class q extends Error{constructor(n){super(n),this.name="ValidationError",this.message=n}}const v=t=>{if(!t||t.length<6)throw new q("The blurhash string must be at least 6 characters");const n=u(t[0]),o=Math.floor(n/9)+1,e=n%9+1;if(t.length!==4+2*e*o)throw new q(\`blurhash length mismatch: length is \${t.length} but it should be \${4+2*e*o}\`)},A=t=>{const n=t>>16,o=t>>8&255,e=t&255;return[D(n),D(o),D(e)]},T=(t,n)=>{const o=Math.floor(t/361),e=Math.floor(t/19)%19,c=t%19;return[p((o-9)/9,2)*n,p((e-9)/9,2)*n,p((c-9)/9,2)*n]},V=(t,n,o,e)=>{v(t),e=e|1;const c=u(t[0]),i=Math.floor(c/9)+1,l=c%9+1,h=(u(t[1])+1)/166,r=new Array(l*i);for(let s=0;s<r.length;s++)if(s===0){const a=u(t.substring(2,6));r[s]=A(a)}else{const a=u(t.substring(4+s*2,6+s*2));r[s]=T(a,h*e)}const d=n*4,g=new Uint8ClampedArray(d*o);for(let s=0;s<o;s++)for(let a=0;a<n;a++){let B=0,E=0,R=0;for(let M=0;M<i;M++)for(let f=0;f<l;f++){const w=Math.cos(Math.PI*a*f/n)*Math.cos(Math.PI*s*M/o);let x=r[f+M*l];B+=x[0]*w,E+=x[1]*w,R+=x[2]*w}let C=b(B),G=b(E),y=b(R);g[4*a+0+s*d]=C,g[4*a+1+s*d]=G,g[4*a+2+s*d]=y,g[4*a+3+s*d]=255}return g};var $=V;addEventListener("message",t=>{console.log(t);const{canvas:n,width:o,height:e,blurhash:c}=t.data;console.log("Encoding",c);const i=+new Date,l=$(c,o,e),m=n.getContext("2d"),h=m.createImageData(o,e);h.data.set(l),m.putImageData(h,0,0);const r=+new Date;console.log("Done Encoding",c,r-i)}); })();` },
|
216
10
|
}),
|
217
11
|
createElement("script", {
|
218
|
-
dangerouslySetInnerHTML: { __html: `(() => { "use strict";
|
219
|
-
class ImageWithPreview extends HTMLElement {
|
220
|
-
sd;
|
221
|
-
mo;
|
222
|
-
static observedAttributes = ["preview"];
|
223
|
-
#connected = false;
|
224
|
-
get #imgEl() {
|
225
|
-
return this.querySelector("img");
|
226
|
-
}
|
227
|
-
get #canvasEl() {
|
228
|
-
return this.querySelector("canvas");
|
229
|
-
}
|
230
|
-
constructor() {
|
231
|
-
super();
|
232
|
-
this.sd = this.attachShadow({
|
233
|
-
mode: "open"
|
234
|
-
});
|
235
|
-
this.sd.innerHTML = \`<slot name="preview"></slot>\`;
|
236
|
-
}
|
237
|
-
#checkReady = () => {
|
238
|
-
if (this.#imgEl && this.#canvasEl) {
|
239
|
-
this.mo?.disconnect();
|
240
|
-
if (this.#imgEl.complete) {
|
241
|
-
this.#imgLoad();
|
242
|
-
} else {
|
243
|
-
this.#updatePreview();
|
244
|
-
this.#imgEl.addEventListener("load", this.#imgLoad);
|
245
|
-
}
|
246
|
-
return 1;
|
247
|
-
}
|
248
|
-
};
|
249
|
-
connectedCallback() {
|
250
|
-
this.#connected = true;
|
251
|
-
if (!this.#checkReady()) {
|
252
|
-
this.mo = new MutationObserver(this.#checkReady);
|
253
|
-
this.mo.observe(this, {
|
254
|
-
subtree: true,
|
255
|
-
childList: true,
|
256
|
-
attributes: false
|
257
|
-
});
|
258
|
-
}
|
259
|
-
}
|
260
|
-
#imgLoad = () => {
|
261
|
-
this.sd.innerHTML = \`<slot name="image"></slot>\`;
|
262
|
-
};
|
263
|
-
attributeChangedCallback(name) {
|
264
|
-
if (this.#canvasEl && name === "preview") {
|
265
|
-
this.#updatePreview();
|
266
|
-
}
|
267
|
-
}
|
268
|
-
#updatePreview() {
|
269
|
-
if (!this.#connected || !this.getAttribute("preview")) {
|
270
|
-
return;
|
271
|
-
}
|
272
|
-
const previewObj = JSON.parse(this.getAttribute("preview"));
|
273
|
-
updateBlurHashPreview(this.#canvasEl, previewObj);
|
274
|
-
}
|
275
|
-
}
|
276
|
-
if (!customElements.get("blurhash-image")) {
|
277
|
-
customElements.define("blurhash-image", ImageWithPreview);
|
278
|
-
}
|
279
|
-
const workerBlob = new Blob([document.querySelector("#next-blurhash-worker-script").textContent], {
|
280
|
-
type: "text/javascript"
|
281
|
-
});
|
282
|
-
const worker = new Worker(window.URL.createObjectURL(workerBlob));
|
283
|
-
const emptyCanvas = document.createElement("canvas").transferControlToOffscreen();
|
284
|
-
worker.postMessage({
|
285
|
-
canvas: emptyCanvas,
|
286
|
-
width: 25,
|
287
|
-
height: 25,
|
288
|
-
blurhash: "L05E$[offQofoffQfQfQfQfQfQfQ"
|
289
|
-
}, [emptyCanvas]);
|
290
|
-
function updateBlurHashPreview(canvasEl, preview) {
|
291
|
-
const {
|
292
|
-
w: width,
|
293
|
-
h: height,
|
294
|
-
blurhash
|
295
|
-
} = preview;
|
296
|
-
canvasEl.width = width;
|
297
|
-
canvasEl.height = height;
|
298
|
-
{
|
299
|
-
const offscreen = canvasEl.transferControlToOffscreen();
|
300
|
-
worker.postMessage({
|
301
|
-
canvas: offscreen,
|
302
|
-
width,
|
303
|
-
height,
|
304
|
-
blurhash
|
305
|
-
}, [offscreen]);
|
306
|
-
}
|
307
|
-
} })();` },
|
12
|
+
dangerouslySetInnerHTML: { __html: `(() => { "use strict";class a extends HTMLElement{sd;mo;static observedAttributes=["preview"];#s=!1;get#e(){return this.querySelector("img")}get#t(){return this.querySelector("canvas")}constructor(){super(),this.sd=this.attachShadow({mode:"open"}),this.sd.innerHTML='<slot name="preview"></slot>'}#i=()=>{if(this.#e&&this.#t)return this.mo?.disconnect(),this.#e.complete?this.#r():(this.#n(),this.#e.addEventListener("load",this.#r)),1};connectedCallback(){this.#s=!0,this.#i()||(this.mo=new MutationObserver(this.#i),this.mo.observe(this,{subtree:!0,childList:!0,attributes:!1}))}#r=()=>{this.sd.innerHTML='<slot name="image"></slot>'};attributeChangedCallback(e){this.#t&&e==="preview"&&this.#n()}#n(){if(!this.#s||!this.getAttribute("preview"))return;const e=JSON.parse(this.getAttribute("preview"));u(this.#t,e)}}customElements.get("blurhash-image")||customElements.define("blurhash-image",a);const c=new Blob([document.querySelector("#next-blurhash-worker-script").textContent],{type:"text/javascript"}),o=new Worker(window.URL.createObjectURL(c)),n=document.createElement("canvas").transferControlToOffscreen();o.postMessage({canvas:n,width:25,height:25,blurhash:"L05E$[offQofoffQfQfQfQfQfQfQ"},[n]);function u(t,e){const{w:s,h:i,blurhash:h}=e;t.width=s,t.height=i;{const r=t.transferControlToOffscreen();o.postMessage({canvas:r,width:s,height:i,blurhash:h},[r])}} })();` },
|
308
13
|
})
|
309
14
|
);
|
package/package.json
CHANGED
package/vite.wc.config.ts
CHANGED