cross-image 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +606 -0
  3. package/esm/mod.d.ts +33 -0
  4. package/esm/mod.d.ts.map +1 -0
  5. package/esm/mod.js +31 -0
  6. package/esm/package.json +3 -0
  7. package/esm/src/formats/ascii.d.ts +27 -0
  8. package/esm/src/formats/ascii.d.ts.map +1 -0
  9. package/esm/src/formats/ascii.js +172 -0
  10. package/esm/src/formats/bmp.d.ts +19 -0
  11. package/esm/src/formats/bmp.d.ts.map +1 -0
  12. package/esm/src/formats/bmp.js +174 -0
  13. package/esm/src/formats/gif.d.ts +40 -0
  14. package/esm/src/formats/gif.d.ts.map +1 -0
  15. package/esm/src/formats/gif.js +385 -0
  16. package/esm/src/formats/jpeg.d.ts +18 -0
  17. package/esm/src/formats/jpeg.d.ts.map +1 -0
  18. package/esm/src/formats/jpeg.js +414 -0
  19. package/esm/src/formats/png.d.ts +33 -0
  20. package/esm/src/formats/png.d.ts.map +1 -0
  21. package/esm/src/formats/png.js +544 -0
  22. package/esm/src/formats/raw.d.ts +23 -0
  23. package/esm/src/formats/raw.d.ts.map +1 -0
  24. package/esm/src/formats/raw.js +98 -0
  25. package/esm/src/formats/tiff.d.ts +58 -0
  26. package/esm/src/formats/tiff.d.ts.map +1 -0
  27. package/esm/src/formats/tiff.js +791 -0
  28. package/esm/src/formats/webp.d.ts +22 -0
  29. package/esm/src/formats/webp.d.ts.map +1 -0
  30. package/esm/src/formats/webp.js +403 -0
  31. package/esm/src/image.d.ts +124 -0
  32. package/esm/src/image.d.ts.map +1 -0
  33. package/esm/src/image.js +320 -0
  34. package/esm/src/types.d.ts +167 -0
  35. package/esm/src/types.d.ts.map +1 -0
  36. package/esm/src/types.js +1 -0
  37. package/esm/src/utils/gif_decoder.d.ts +42 -0
  38. package/esm/src/utils/gif_decoder.d.ts.map +1 -0
  39. package/esm/src/utils/gif_decoder.js +374 -0
  40. package/esm/src/utils/gif_encoder.d.ts +29 -0
  41. package/esm/src/utils/gif_encoder.d.ts.map +1 -0
  42. package/esm/src/utils/gif_encoder.js +226 -0
  43. package/esm/src/utils/jpeg_decoder.d.ts +39 -0
  44. package/esm/src/utils/jpeg_decoder.d.ts.map +1 -0
  45. package/esm/src/utils/jpeg_decoder.js +580 -0
  46. package/esm/src/utils/jpeg_encoder.d.ts +33 -0
  47. package/esm/src/utils/jpeg_encoder.d.ts.map +1 -0
  48. package/esm/src/utils/jpeg_encoder.js +1017 -0
  49. package/esm/src/utils/lzw.d.ts +43 -0
  50. package/esm/src/utils/lzw.d.ts.map +1 -0
  51. package/esm/src/utils/lzw.js +309 -0
  52. package/esm/src/utils/resize.d.ts +9 -0
  53. package/esm/src/utils/resize.d.ts.map +1 -0
  54. package/esm/src/utils/resize.js +52 -0
  55. package/esm/src/utils/tiff_lzw.d.ts +44 -0
  56. package/esm/src/utils/tiff_lzw.d.ts.map +1 -0
  57. package/esm/src/utils/tiff_lzw.js +306 -0
  58. package/esm/src/utils/webp_decoder.d.ts +39 -0
  59. package/esm/src/utils/webp_decoder.d.ts.map +1 -0
  60. package/esm/src/utils/webp_decoder.js +493 -0
  61. package/esm/src/utils/webp_encoder.d.ts +72 -0
  62. package/esm/src/utils/webp_encoder.d.ts.map +1 -0
  63. package/esm/src/utils/webp_encoder.js +627 -0
  64. package/package.json +41 -0
  65. package/script/mod.d.ts +33 -0
  66. package/script/mod.d.ts.map +1 -0
  67. package/script/mod.js +43 -0
  68. package/script/package.json +3 -0
  69. package/script/src/formats/ascii.d.ts +27 -0
  70. package/script/src/formats/ascii.d.ts.map +1 -0
  71. package/script/src/formats/ascii.js +176 -0
  72. package/script/src/formats/bmp.d.ts +19 -0
  73. package/script/src/formats/bmp.d.ts.map +1 -0
  74. package/script/src/formats/bmp.js +178 -0
  75. package/script/src/formats/gif.d.ts +40 -0
  76. package/script/src/formats/gif.d.ts.map +1 -0
  77. package/script/src/formats/gif.js +389 -0
  78. package/script/src/formats/jpeg.d.ts +18 -0
  79. package/script/src/formats/jpeg.d.ts.map +1 -0
  80. package/script/src/formats/jpeg.js +451 -0
  81. package/script/src/formats/png.d.ts +33 -0
  82. package/script/src/formats/png.d.ts.map +1 -0
  83. package/script/src/formats/png.js +548 -0
  84. package/script/src/formats/raw.d.ts +23 -0
  85. package/script/src/formats/raw.d.ts.map +1 -0
  86. package/script/src/formats/raw.js +102 -0
  87. package/script/src/formats/tiff.d.ts +58 -0
  88. package/script/src/formats/tiff.d.ts.map +1 -0
  89. package/script/src/formats/tiff.js +795 -0
  90. package/script/src/formats/webp.d.ts +22 -0
  91. package/script/src/formats/webp.d.ts.map +1 -0
  92. package/script/src/formats/webp.js +440 -0
  93. package/script/src/image.d.ts +124 -0
  94. package/script/src/image.d.ts.map +1 -0
  95. package/script/src/image.js +324 -0
  96. package/script/src/types.d.ts +167 -0
  97. package/script/src/types.d.ts.map +1 -0
  98. package/script/src/types.js +2 -0
  99. package/script/src/utils/gif_decoder.d.ts +42 -0
  100. package/script/src/utils/gif_decoder.d.ts.map +1 -0
  101. package/script/src/utils/gif_decoder.js +378 -0
  102. package/script/src/utils/gif_encoder.d.ts +29 -0
  103. package/script/src/utils/gif_encoder.d.ts.map +1 -0
  104. package/script/src/utils/gif_encoder.js +230 -0
  105. package/script/src/utils/jpeg_decoder.d.ts +39 -0
  106. package/script/src/utils/jpeg_decoder.d.ts.map +1 -0
  107. package/script/src/utils/jpeg_decoder.js +584 -0
  108. package/script/src/utils/jpeg_encoder.d.ts +33 -0
  109. package/script/src/utils/jpeg_encoder.d.ts.map +1 -0
  110. package/script/src/utils/jpeg_encoder.js +1021 -0
  111. package/script/src/utils/lzw.d.ts +43 -0
  112. package/script/src/utils/lzw.d.ts.map +1 -0
  113. package/script/src/utils/lzw.js +314 -0
  114. package/script/src/utils/resize.d.ts +9 -0
  115. package/script/src/utils/resize.d.ts.map +1 -0
  116. package/script/src/utils/resize.js +56 -0
  117. package/script/src/utils/tiff_lzw.d.ts +44 -0
  118. package/script/src/utils/tiff_lzw.d.ts.map +1 -0
  119. package/script/src/utils/tiff_lzw.js +311 -0
  120. package/script/src/utils/webp_decoder.d.ts +39 -0
  121. package/script/src/utils/webp_decoder.d.ts.map +1 -0
  122. package/script/src/utils/webp_decoder.js +497 -0
  123. package/script/src/utils/webp_encoder.d.ts +72 -0
  124. package/script/src/utils/webp_encoder.d.ts.map +1 -0
  125. package/script/src/utils/webp_encoder.js +631 -0
@@ -0,0 +1,1021 @@
1
+ "use strict";
2
+ /**
3
+ * Basic baseline JPEG encoder implementation
4
+ * Produces valid baseline DCT JPEG images
5
+ *
6
+ * This is a simplified implementation focusing on correctness over performance.
7
+ * For production use with better quality/size, the OffscreenCanvas API is preferred.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.JPEGEncoder = void 0;
11
+ // Standard JPEG quantization tables
12
+ const STANDARD_LUMINANCE_QUANT_TABLE = [
13
+ 16,
14
+ 11,
15
+ 10,
16
+ 16,
17
+ 24,
18
+ 40,
19
+ 51,
20
+ 61,
21
+ 12,
22
+ 12,
23
+ 14,
24
+ 19,
25
+ 26,
26
+ 58,
27
+ 60,
28
+ 55,
29
+ 14,
30
+ 13,
31
+ 16,
32
+ 24,
33
+ 40,
34
+ 57,
35
+ 69,
36
+ 56,
37
+ 14,
38
+ 17,
39
+ 22,
40
+ 29,
41
+ 51,
42
+ 87,
43
+ 80,
44
+ 62,
45
+ 18,
46
+ 22,
47
+ 37,
48
+ 56,
49
+ 68,
50
+ 109,
51
+ 103,
52
+ 77,
53
+ 24,
54
+ 35,
55
+ 55,
56
+ 64,
57
+ 81,
58
+ 104,
59
+ 113,
60
+ 92,
61
+ 49,
62
+ 64,
63
+ 78,
64
+ 87,
65
+ 103,
66
+ 121,
67
+ 120,
68
+ 101,
69
+ 72,
70
+ 92,
71
+ 95,
72
+ 98,
73
+ 112,
74
+ 100,
75
+ 103,
76
+ 99,
77
+ ];
78
+ const STANDARD_CHROMINANCE_QUANT_TABLE = [
79
+ 17,
80
+ 18,
81
+ 24,
82
+ 47,
83
+ 99,
84
+ 99,
85
+ 99,
86
+ 99,
87
+ 18,
88
+ 21,
89
+ 26,
90
+ 66,
91
+ 99,
92
+ 99,
93
+ 99,
94
+ 99,
95
+ 24,
96
+ 26,
97
+ 56,
98
+ 99,
99
+ 99,
100
+ 99,
101
+ 99,
102
+ 99,
103
+ 47,
104
+ 66,
105
+ 99,
106
+ 99,
107
+ 99,
108
+ 99,
109
+ 99,
110
+ 99,
111
+ 99,
112
+ 99,
113
+ 99,
114
+ 99,
115
+ 99,
116
+ 99,
117
+ 99,
118
+ 99,
119
+ 99,
120
+ 99,
121
+ 99,
122
+ 99,
123
+ 99,
124
+ 99,
125
+ 99,
126
+ 99,
127
+ 99,
128
+ 99,
129
+ 99,
130
+ 99,
131
+ 99,
132
+ 99,
133
+ 99,
134
+ 99,
135
+ 99,
136
+ 99,
137
+ 99,
138
+ 99,
139
+ 99,
140
+ 99,
141
+ 99,
142
+ 99,
143
+ ];
144
+ // Zigzag order for DCT coefficients
145
+ const ZIGZAG = [
146
+ 0,
147
+ 1,
148
+ 8,
149
+ 16,
150
+ 9,
151
+ 2,
152
+ 3,
153
+ 10,
154
+ 17,
155
+ 24,
156
+ 32,
157
+ 25,
158
+ 18,
159
+ 11,
160
+ 4,
161
+ 5,
162
+ 12,
163
+ 19,
164
+ 26,
165
+ 33,
166
+ 40,
167
+ 48,
168
+ 41,
169
+ 34,
170
+ 27,
171
+ 20,
172
+ 13,
173
+ 6,
174
+ 7,
175
+ 14,
176
+ 21,
177
+ 28,
178
+ 35,
179
+ 42,
180
+ 49,
181
+ 56,
182
+ 57,
183
+ 50,
184
+ 43,
185
+ 36,
186
+ 29,
187
+ 22,
188
+ 15,
189
+ 23,
190
+ 30,
191
+ 37,
192
+ 44,
193
+ 51,
194
+ 58,
195
+ 59,
196
+ 52,
197
+ 45,
198
+ 38,
199
+ 31,
200
+ 39,
201
+ 46,
202
+ 53,
203
+ 60,
204
+ 61,
205
+ 54,
206
+ 47,
207
+ 55,
208
+ 62,
209
+ 63,
210
+ ];
211
+ // Standard Huffman tables for DC coefficients (luminance)
212
+ const STD_DC_LUMINANCE_NRCODES = [
213
+ 0,
214
+ 0,
215
+ 1,
216
+ 5,
217
+ 1,
218
+ 1,
219
+ 1,
220
+ 1,
221
+ 1,
222
+ 1,
223
+ 0,
224
+ 0,
225
+ 0,
226
+ 0,
227
+ 0,
228
+ 0,
229
+ 0,
230
+ ];
231
+ const STD_DC_LUMINANCE_VALUES = [
232
+ 0,
233
+ 1,
234
+ 2,
235
+ 3,
236
+ 4,
237
+ 5,
238
+ 6,
239
+ 7,
240
+ 8,
241
+ 9,
242
+ 10,
243
+ 11,
244
+ ];
245
+ // Standard Huffman tables for AC coefficients (luminance)
246
+ const STD_AC_LUMINANCE_NRCODES = [
247
+ 0,
248
+ 0,
249
+ 2,
250
+ 1,
251
+ 3,
252
+ 3,
253
+ 2,
254
+ 4,
255
+ 3,
256
+ 5,
257
+ 5,
258
+ 4,
259
+ 4,
260
+ 0,
261
+ 0,
262
+ 1,
263
+ 0x7d,
264
+ ];
265
+ const STD_AC_LUMINANCE_VALUES = [
266
+ 0x01,
267
+ 0x02,
268
+ 0x03,
269
+ 0x00,
270
+ 0x04,
271
+ 0x11,
272
+ 0x05,
273
+ 0x12,
274
+ 0x21,
275
+ 0x31,
276
+ 0x41,
277
+ 0x06,
278
+ 0x13,
279
+ 0x51,
280
+ 0x61,
281
+ 0x07,
282
+ 0x22,
283
+ 0x71,
284
+ 0x14,
285
+ 0x32,
286
+ 0x81,
287
+ 0x91,
288
+ 0xa1,
289
+ 0x08,
290
+ 0x23,
291
+ 0x42,
292
+ 0xb1,
293
+ 0xc1,
294
+ 0x15,
295
+ 0x52,
296
+ 0xd1,
297
+ 0xf0,
298
+ 0x24,
299
+ 0x33,
300
+ 0x62,
301
+ 0x72,
302
+ 0x82,
303
+ 0x09,
304
+ 0x0a,
305
+ 0x16,
306
+ 0x17,
307
+ 0x18,
308
+ 0x19,
309
+ 0x1a,
310
+ 0x25,
311
+ 0x26,
312
+ 0x27,
313
+ 0x28,
314
+ 0x29,
315
+ 0x2a,
316
+ 0x34,
317
+ 0x35,
318
+ 0x36,
319
+ 0x37,
320
+ 0x38,
321
+ 0x39,
322
+ 0x3a,
323
+ 0x43,
324
+ 0x44,
325
+ 0x45,
326
+ 0x46,
327
+ 0x47,
328
+ 0x48,
329
+ 0x49,
330
+ 0x4a,
331
+ 0x53,
332
+ 0x54,
333
+ 0x55,
334
+ 0x56,
335
+ 0x57,
336
+ 0x58,
337
+ 0x59,
338
+ 0x5a,
339
+ 0x63,
340
+ 0x64,
341
+ 0x65,
342
+ 0x66,
343
+ 0x67,
344
+ 0x68,
345
+ 0x69,
346
+ 0x6a,
347
+ 0x73,
348
+ 0x74,
349
+ 0x75,
350
+ 0x76,
351
+ 0x77,
352
+ 0x78,
353
+ 0x79,
354
+ 0x7a,
355
+ 0x83,
356
+ 0x84,
357
+ 0x85,
358
+ 0x86,
359
+ 0x87,
360
+ 0x88,
361
+ 0x89,
362
+ 0x8a,
363
+ 0x92,
364
+ 0x93,
365
+ 0x94,
366
+ 0x95,
367
+ 0x96,
368
+ 0x97,
369
+ 0x98,
370
+ 0x99,
371
+ 0x9a,
372
+ 0xa2,
373
+ 0xa3,
374
+ 0xa4,
375
+ 0xa5,
376
+ 0xa6,
377
+ 0xa7,
378
+ 0xa8,
379
+ 0xa9,
380
+ 0xaa,
381
+ 0xb2,
382
+ 0xb3,
383
+ 0xb4,
384
+ 0xb5,
385
+ 0xb6,
386
+ 0xb7,
387
+ 0xb8,
388
+ 0xb9,
389
+ 0xba,
390
+ 0xc2,
391
+ 0xc3,
392
+ 0xc4,
393
+ 0xc5,
394
+ 0xc6,
395
+ 0xc7,
396
+ 0xc8,
397
+ 0xc9,
398
+ 0xca,
399
+ 0xd2,
400
+ 0xd3,
401
+ 0xd4,
402
+ 0xd5,
403
+ 0xd6,
404
+ 0xd7,
405
+ 0xd8,
406
+ 0xd9,
407
+ 0xda,
408
+ 0xe1,
409
+ 0xe2,
410
+ 0xe3,
411
+ 0xe4,
412
+ 0xe5,
413
+ 0xe6,
414
+ 0xe7,
415
+ 0xe8,
416
+ 0xe9,
417
+ 0xea,
418
+ 0xf1,
419
+ 0xf2,
420
+ 0xf3,
421
+ 0xf4,
422
+ 0xf5,
423
+ 0xf6,
424
+ 0xf7,
425
+ 0xf8,
426
+ 0xf9,
427
+ 0xfa,
428
+ ];
429
+ // Standard Huffman tables for DC coefficients (chrominance)
430
+ const STD_DC_CHROMINANCE_NRCODES = [
431
+ 0,
432
+ 0,
433
+ 3,
434
+ 1,
435
+ 1,
436
+ 1,
437
+ 1,
438
+ 1,
439
+ 1,
440
+ 1,
441
+ 1,
442
+ 1,
443
+ 0,
444
+ 0,
445
+ 0,
446
+ 0,
447
+ 0,
448
+ ];
449
+ const STD_DC_CHROMINANCE_VALUES = [
450
+ 0,
451
+ 1,
452
+ 2,
453
+ 3,
454
+ 4,
455
+ 5,
456
+ 6,
457
+ 7,
458
+ 8,
459
+ 9,
460
+ 10,
461
+ 11,
462
+ ];
463
+ // Standard Huffman tables for AC coefficients (chrominance)
464
+ const STD_AC_CHROMINANCE_NRCODES = [
465
+ 0,
466
+ 0,
467
+ 2,
468
+ 1,
469
+ 2,
470
+ 4,
471
+ 4,
472
+ 3,
473
+ 4,
474
+ 7,
475
+ 5,
476
+ 4,
477
+ 4,
478
+ 0,
479
+ 1,
480
+ 2,
481
+ 0x77,
482
+ ];
483
+ const STD_AC_CHROMINANCE_VALUES = [
484
+ 0x00,
485
+ 0x01,
486
+ 0x02,
487
+ 0x03,
488
+ 0x11,
489
+ 0x04,
490
+ 0x05,
491
+ 0x21,
492
+ 0x31,
493
+ 0x06,
494
+ 0x12,
495
+ 0x41,
496
+ 0x51,
497
+ 0x07,
498
+ 0x61,
499
+ 0x71,
500
+ 0x13,
501
+ 0x22,
502
+ 0x32,
503
+ 0x81,
504
+ 0x08,
505
+ 0x14,
506
+ 0x42,
507
+ 0x91,
508
+ 0xa1,
509
+ 0xb1,
510
+ 0xc1,
511
+ 0x09,
512
+ 0x23,
513
+ 0x33,
514
+ 0x52,
515
+ 0xf0,
516
+ 0x15,
517
+ 0x62,
518
+ 0x72,
519
+ 0xd1,
520
+ 0x0a,
521
+ 0x16,
522
+ 0x24,
523
+ 0x34,
524
+ 0xe1,
525
+ 0x25,
526
+ 0xf1,
527
+ 0x17,
528
+ 0x18,
529
+ 0x19,
530
+ 0x1a,
531
+ 0x26,
532
+ 0x27,
533
+ 0x28,
534
+ 0x29,
535
+ 0x2a,
536
+ 0x35,
537
+ 0x36,
538
+ 0x37,
539
+ 0x38,
540
+ 0x39,
541
+ 0x3a,
542
+ 0x43,
543
+ 0x44,
544
+ 0x45,
545
+ 0x46,
546
+ 0x47,
547
+ 0x48,
548
+ 0x49,
549
+ 0x4a,
550
+ 0x53,
551
+ 0x54,
552
+ 0x55,
553
+ 0x56,
554
+ 0x57,
555
+ 0x58,
556
+ 0x59,
557
+ 0x5a,
558
+ 0x63,
559
+ 0x64,
560
+ 0x65,
561
+ 0x66,
562
+ 0x67,
563
+ 0x68,
564
+ 0x69,
565
+ 0x6a,
566
+ 0x73,
567
+ 0x74,
568
+ 0x75,
569
+ 0x76,
570
+ 0x77,
571
+ 0x78,
572
+ 0x79,
573
+ 0x7a,
574
+ 0x82,
575
+ 0x83,
576
+ 0x84,
577
+ 0x85,
578
+ 0x86,
579
+ 0x87,
580
+ 0x88,
581
+ 0x89,
582
+ 0x8a,
583
+ 0x92,
584
+ 0x93,
585
+ 0x94,
586
+ 0x95,
587
+ 0x96,
588
+ 0x97,
589
+ 0x98,
590
+ 0x99,
591
+ 0x9a,
592
+ 0xa2,
593
+ 0xa3,
594
+ 0xa4,
595
+ 0xa5,
596
+ 0xa6,
597
+ 0xa7,
598
+ 0xa8,
599
+ 0xa9,
600
+ 0xaa,
601
+ 0xb2,
602
+ 0xb3,
603
+ 0xb4,
604
+ 0xb5,
605
+ 0xb6,
606
+ 0xb7,
607
+ 0xb8,
608
+ 0xb9,
609
+ 0xba,
610
+ 0xc2,
611
+ 0xc3,
612
+ 0xc4,
613
+ 0xc5,
614
+ 0xc6,
615
+ 0xc7,
616
+ 0xc8,
617
+ 0xc9,
618
+ 0xca,
619
+ 0xd2,
620
+ 0xd3,
621
+ 0xd4,
622
+ 0xd5,
623
+ 0xd6,
624
+ 0xd7,
625
+ 0xd8,
626
+ 0xd9,
627
+ 0xda,
628
+ 0xe2,
629
+ 0xe3,
630
+ 0xe4,
631
+ 0xe5,
632
+ 0xe6,
633
+ 0xe7,
634
+ 0xe8,
635
+ 0xe9,
636
+ 0xea,
637
+ 0xf2,
638
+ 0xf3,
639
+ 0xf4,
640
+ 0xf5,
641
+ 0xf6,
642
+ 0xf7,
643
+ 0xf8,
644
+ 0xf9,
645
+ 0xfa,
646
+ ];
647
+ class BitWriter {
648
+ constructor() {
649
+ Object.defineProperty(this, "buffer", {
650
+ enumerable: true,
651
+ configurable: true,
652
+ writable: true,
653
+ value: []
654
+ });
655
+ Object.defineProperty(this, "bitBuffer", {
656
+ enumerable: true,
657
+ configurable: true,
658
+ writable: true,
659
+ value: 0
660
+ });
661
+ Object.defineProperty(this, "bitCount", {
662
+ enumerable: true,
663
+ configurable: true,
664
+ writable: true,
665
+ value: 0
666
+ });
667
+ }
668
+ writeBits(value, length) {
669
+ this.bitBuffer = (this.bitBuffer << length) | value;
670
+ this.bitCount += length;
671
+ while (this.bitCount >= 8) {
672
+ this.bitCount -= 8;
673
+ const byte = (this.bitBuffer >> this.bitCount) & 0xff;
674
+ this.buffer.push(byte);
675
+ // Byte stuffing: insert 0x00 after 0xFF
676
+ if (byte === 0xff) {
677
+ this.buffer.push(0x00);
678
+ }
679
+ }
680
+ }
681
+ flush() {
682
+ if (this.bitCount > 0) {
683
+ const byte = (this.bitBuffer << (8 - this.bitCount)) & 0xff;
684
+ this.buffer.push(byte);
685
+ if (byte === 0xff) {
686
+ this.buffer.push(0x00);
687
+ }
688
+ }
689
+ this.bitBuffer = 0;
690
+ this.bitCount = 0;
691
+ }
692
+ getBytes() {
693
+ return new Uint8Array(this.buffer);
694
+ }
695
+ }
696
+ class JPEGEncoder {
697
+ constructor(quality = 85) {
698
+ Object.defineProperty(this, "quality", {
699
+ enumerable: true,
700
+ configurable: true,
701
+ writable: true,
702
+ value: void 0
703
+ });
704
+ Object.defineProperty(this, "luminanceQuantTable", {
705
+ enumerable: true,
706
+ configurable: true,
707
+ writable: true,
708
+ value: []
709
+ });
710
+ Object.defineProperty(this, "chrominanceQuantTable", {
711
+ enumerable: true,
712
+ configurable: true,
713
+ writable: true,
714
+ value: []
715
+ });
716
+ Object.defineProperty(this, "dcLuminanceHuffman", {
717
+ enumerable: true,
718
+ configurable: true,
719
+ writable: true,
720
+ value: void 0
721
+ });
722
+ Object.defineProperty(this, "acLuminanceHuffman", {
723
+ enumerable: true,
724
+ configurable: true,
725
+ writable: true,
726
+ value: void 0
727
+ });
728
+ Object.defineProperty(this, "dcChrominanceHuffman", {
729
+ enumerable: true,
730
+ configurable: true,
731
+ writable: true,
732
+ value: void 0
733
+ });
734
+ Object.defineProperty(this, "acChrominanceHuffman", {
735
+ enumerable: true,
736
+ configurable: true,
737
+ writable: true,
738
+ value: void 0
739
+ });
740
+ this.quality = Math.max(1, Math.min(100, quality));
741
+ this.initQuantizationTables();
742
+ this.initHuffmanTables();
743
+ }
744
+ initQuantizationTables() {
745
+ const scaleFactor = this.quality < 50
746
+ ? 5000 / this.quality
747
+ : 200 - this.quality * 2;
748
+ for (let i = 0; i < 64; i++) {
749
+ let lumVal = Math.floor((STANDARD_LUMINANCE_QUANT_TABLE[i] * scaleFactor + 50) / 100);
750
+ let chromVal = Math.floor((STANDARD_CHROMINANCE_QUANT_TABLE[i] * scaleFactor + 50) / 100);
751
+ lumVal = Math.max(1, Math.min(255, lumVal));
752
+ chromVal = Math.max(1, Math.min(255, chromVal));
753
+ this.luminanceQuantTable[i] = lumVal;
754
+ this.chrominanceQuantTable[i] = chromVal;
755
+ }
756
+ }
757
+ initHuffmanTables() {
758
+ this.dcLuminanceHuffman = this.buildHuffmanTable(STD_DC_LUMINANCE_NRCODES, STD_DC_LUMINANCE_VALUES);
759
+ this.acLuminanceHuffman = this.buildHuffmanTable(STD_AC_LUMINANCE_NRCODES, STD_AC_LUMINANCE_VALUES);
760
+ this.dcChrominanceHuffman = this.buildHuffmanTable(STD_DC_CHROMINANCE_NRCODES, STD_DC_CHROMINANCE_VALUES);
761
+ this.acChrominanceHuffman = this.buildHuffmanTable(STD_AC_CHROMINANCE_NRCODES, STD_AC_CHROMINANCE_VALUES);
762
+ }
763
+ buildHuffmanTable(nrcodes, values) {
764
+ const codes = new Array(256).fill(0);
765
+ const sizes = new Array(256).fill(0);
766
+ let code = 0;
767
+ let valueIndex = 0;
768
+ for (let length = 1; length <= 16; length++) {
769
+ for (let i = 0; i < nrcodes[length]; i++) {
770
+ const value = values[valueIndex];
771
+ codes[value] = code;
772
+ sizes[value] = length;
773
+ code++;
774
+ valueIndex++;
775
+ }
776
+ code <<= 1;
777
+ }
778
+ return { codes, sizes };
779
+ }
780
+ encode(width, height, rgba, dpiX = 72, dpiY = 72) {
781
+ const output = [];
782
+ // SOI (Start of Image)
783
+ output.push(0xff, 0xd8);
784
+ // APP0 (JFIF marker)
785
+ this.writeAPP0(output, dpiX, dpiY);
786
+ // DQT (Define Quantization Tables)
787
+ this.writeDQT(output);
788
+ // SOF0 (Start of Frame - Baseline DCT)
789
+ this.writeSOF0(output, width, height);
790
+ // DHT (Define Huffman Tables)
791
+ this.writeDHT(output);
792
+ // SOS (Start of Scan)
793
+ this.writeSOS(output);
794
+ // Encode scan data
795
+ const scanData = this.encodeScan(width, height, rgba);
796
+ for (let i = 0; i < scanData.length; i++) {
797
+ output.push(scanData[i]);
798
+ }
799
+ // EOI (End of Image)
800
+ output.push(0xff, 0xd9);
801
+ return new Uint8Array(output);
802
+ }
803
+ writeAPP0(output, dpiX, dpiY) {
804
+ output.push(0xff, 0xe0); // APP0 marker
805
+ output.push(0x00, 0x10); // Length (16 bytes)
806
+ output.push(0x4a, 0x46, 0x49, 0x46, 0x00); // "JFIF\0"
807
+ output.push(0x01, 0x01); // Version 1.1
808
+ output.push(0x01); // Density units (1 = dots per inch)
809
+ output.push((dpiX >> 8) & 0xff, dpiX & 0xff); // X density
810
+ output.push((dpiY >> 8) & 0xff, dpiY & 0xff); // Y density
811
+ output.push(0x00, 0x00); // Thumbnail dimensions (none)
812
+ }
813
+ writeDQT(output) {
814
+ // Luminance table
815
+ output.push(0xff, 0xdb); // DQT marker
816
+ output.push(0x00, 0x43); // Length (67 bytes)
817
+ output.push(0x00); // Table 0, 8-bit precision
818
+ for (let i = 0; i < 64; i++) {
819
+ output.push(this.luminanceQuantTable[ZIGZAG[i]]);
820
+ }
821
+ // Chrominance table
822
+ output.push(0xff, 0xdb); // DQT marker
823
+ output.push(0x00, 0x43); // Length (67 bytes)
824
+ output.push(0x01); // Table 1, 8-bit precision
825
+ for (let i = 0; i < 64; i++) {
826
+ output.push(this.chrominanceQuantTable[ZIGZAG[i]]);
827
+ }
828
+ }
829
+ writeSOF0(output, width, height) {
830
+ output.push(0xff, 0xc0); // SOF0 marker
831
+ output.push(0x00, 0x11); // Length (17 bytes)
832
+ output.push(0x08); // Precision (8 bits)
833
+ output.push((height >> 8) & 0xff, height & 0xff); // Height
834
+ output.push((width >> 8) & 0xff, width & 0xff); // Width
835
+ output.push(0x03); // Number of components (3 = YCbCr)
836
+ // Y component
837
+ output.push(0x01); // Component ID
838
+ output.push(0x11); // Sampling factors (1x1)
839
+ output.push(0x00); // Quantization table 0
840
+ // Cb component
841
+ output.push(0x02); // Component ID
842
+ output.push(0x11); // Sampling factors (1x1)
843
+ output.push(0x01); // Quantization table 1
844
+ // Cr component
845
+ output.push(0x03); // Component ID
846
+ output.push(0x11); // Sampling factors (1x1)
847
+ output.push(0x01); // Quantization table 1
848
+ }
849
+ writeDHT(output) {
850
+ // DC Luminance
851
+ this.writeHuffmanTable(output, 0x00, STD_DC_LUMINANCE_NRCODES, STD_DC_LUMINANCE_VALUES);
852
+ // AC Luminance
853
+ this.writeHuffmanTable(output, 0x10, STD_AC_LUMINANCE_NRCODES, STD_AC_LUMINANCE_VALUES);
854
+ // DC Chrominance
855
+ this.writeHuffmanTable(output, 0x01, STD_DC_CHROMINANCE_NRCODES, STD_DC_CHROMINANCE_VALUES);
856
+ // AC Chrominance
857
+ this.writeHuffmanTable(output, 0x11, STD_AC_CHROMINANCE_NRCODES, STD_AC_CHROMINANCE_VALUES);
858
+ }
859
+ writeHuffmanTable(output, classId, nrcodes, values) {
860
+ output.push(0xff, 0xc4); // DHT marker
861
+ let length = 19;
862
+ for (let i = 1; i <= 16; i++) {
863
+ length += nrcodes[i];
864
+ }
865
+ output.push((length >> 8) & 0xff, length & 0xff); // Length
866
+ output.push(classId); // Class and ID
867
+ // Number of codes for each length
868
+ for (let i = 1; i <= 16; i++) {
869
+ output.push(nrcodes[i]);
870
+ }
871
+ // Values
872
+ let valueIndex = 0;
873
+ for (let i = 1; i <= 16; i++) {
874
+ for (let j = 0; j < nrcodes[i]; j++) {
875
+ output.push(values[valueIndex++]);
876
+ }
877
+ }
878
+ }
879
+ writeSOS(output) {
880
+ output.push(0xff, 0xda); // SOS marker
881
+ output.push(0x00, 0x0c); // Length (12 bytes)
882
+ output.push(0x03); // Number of components
883
+ // Y component
884
+ output.push(0x01); // Component ID
885
+ output.push(0x00); // DC table 0, AC table 0
886
+ // Cb component
887
+ output.push(0x02); // Component ID
888
+ output.push(0x11); // DC table 1, AC table 1
889
+ // Cr component
890
+ output.push(0x03); // Component ID
891
+ output.push(0x11); // DC table 1, AC table 1
892
+ output.push(0x00); // Start of spectral selection
893
+ output.push(0x3f); // End of spectral selection
894
+ output.push(0x00); // Successive approximation
895
+ }
896
+ encodeScan(width, height, rgba) {
897
+ const bitWriter = new BitWriter();
898
+ // Convert RGBA to YCbCr and encode MCUs
899
+ let dcY = 0, dcCb = 0, dcCr = 0;
900
+ const mcuWidth = Math.ceil(width / 8);
901
+ const mcuHeight = Math.ceil(height / 8);
902
+ for (let mcuY = 0; mcuY < mcuHeight; mcuY++) {
903
+ for (let mcuX = 0; mcuX < mcuWidth; mcuX++) {
904
+ const yBlock = new Array(64).fill(0);
905
+ const cbBlock = new Array(64).fill(0);
906
+ const crBlock = new Array(64).fill(0);
907
+ // Extract 8x8 block and convert RGB to YCbCr
908
+ for (let y = 0; y < 8; y++) {
909
+ for (let x = 0; x < 8; x++) {
910
+ const px = mcuX * 8 + x;
911
+ const py = mcuY * 8 + y;
912
+ if (px < width && py < height) {
913
+ const offset = (py * width + px) * 4;
914
+ const r = rgba[offset];
915
+ const g = rgba[offset + 1];
916
+ const b = rgba[offset + 2];
917
+ // RGB to YCbCr conversion
918
+ const yVal = 0.299 * r + 0.587 * g + 0.114 * b;
919
+ const cbVal = -0.168736 * r - 0.331264 * g + 0.5 * b + 128;
920
+ const crVal = 0.5 * r - 0.418688 * g - 0.081312 * b + 128;
921
+ yBlock[y * 8 + x] = yVal - 128; // Level shift
922
+ cbBlock[y * 8 + x] = cbVal - 128;
923
+ crBlock[y * 8 + x] = crVal - 128;
924
+ }
925
+ }
926
+ }
927
+ // Process Y, Cb, Cr blocks
928
+ dcY = this.encodeBlock(yBlock, this.luminanceQuantTable, dcY, this.dcLuminanceHuffman, this.acLuminanceHuffman, bitWriter);
929
+ dcCb = this.encodeBlock(cbBlock, this.chrominanceQuantTable, dcCb, this.dcChrominanceHuffman, this.acChrominanceHuffman, bitWriter);
930
+ dcCr = this.encodeBlock(crBlock, this.chrominanceQuantTable, dcCr, this.dcChrominanceHuffman, this.acChrominanceHuffman, bitWriter);
931
+ }
932
+ }
933
+ bitWriter.flush();
934
+ return Array.from(bitWriter.getBytes());
935
+ }
936
+ encodeBlock(block, quantTable, prevDC, dcTable, acTable, bitWriter) {
937
+ // Apply DCT
938
+ this.forwardDCT(block);
939
+ // Quantize and reorder to zigzag
940
+ const quantized = new Array(64);
941
+ for (let i = 0; i < 64; i++) {
942
+ const zigzagIndex = ZIGZAG[i];
943
+ quantized[i] = Math.round(block[zigzagIndex] / quantTable[zigzagIndex]);
944
+ }
945
+ // Encode DC coefficient
946
+ const dcDiff = quantized[0] - prevDC;
947
+ this.encodeDC(dcDiff, dcTable, bitWriter);
948
+ // Encode AC coefficients
949
+ this.encodeAC(quantized, acTable, bitWriter);
950
+ return quantized[0];
951
+ }
952
+ forwardDCT(block) {
953
+ // Simplified 2D DCT
954
+ const temp = new Array(64);
955
+ // 1D DCT on rows
956
+ for (let i = 0; i < 8; i++) {
957
+ const offset = i * 8;
958
+ for (let u = 0; u < 8; u++) {
959
+ let sum = 0;
960
+ for (let x = 0; x < 8; x++) {
961
+ sum += block[offset + x] * Math.cos(((2 * x + 1) * u * Math.PI) / 16);
962
+ }
963
+ const cu = u === 0 ? 1 / Math.sqrt(2) : 1;
964
+ temp[offset + u] = 0.5 * cu * sum;
965
+ }
966
+ }
967
+ // 1D DCT on columns
968
+ for (let j = 0; j < 8; j++) {
969
+ for (let v = 0; v < 8; v++) {
970
+ let sum = 0;
971
+ for (let y = 0; y < 8; y++) {
972
+ sum += temp[y * 8 + j] * Math.cos(((2 * y + 1) * v * Math.PI) / 16);
973
+ }
974
+ const cv = v === 0 ? 1 / Math.sqrt(2) : 1;
975
+ block[v * 8 + j] = 0.5 * cv * sum;
976
+ }
977
+ }
978
+ }
979
+ encodeDC(value, huffTable, bitWriter) {
980
+ const absValue = Math.abs(value);
981
+ let size = 0;
982
+ if (absValue > 0) {
983
+ size = Math.floor(Math.log2(absValue)) + 1;
984
+ }
985
+ // Write Huffman code for size
986
+ bitWriter.writeBits(huffTable.codes[size], huffTable.sizes[size]);
987
+ // Write magnitude
988
+ if (size > 0) {
989
+ const magnitude = value < 0 ? value + (1 << size) - 1 : value;
990
+ bitWriter.writeBits(magnitude, size);
991
+ }
992
+ }
993
+ encodeAC(block, huffTable, bitWriter) {
994
+ let zeroCount = 0;
995
+ for (let i = 1; i < 64; i++) {
996
+ const coef = block[i];
997
+ if (coef === 0) {
998
+ zeroCount++;
999
+ }
1000
+ else {
1001
+ // Write any pending zero runs
1002
+ while (zeroCount >= 16) {
1003
+ bitWriter.writeBits(huffTable.codes[0xf0], huffTable.sizes[0xf0]);
1004
+ zeroCount -= 16;
1005
+ }
1006
+ const absCoef = Math.abs(coef);
1007
+ const size = Math.floor(Math.log2(absCoef)) + 1;
1008
+ const symbol = (zeroCount << 4) | size;
1009
+ bitWriter.writeBits(huffTable.codes[symbol], huffTable.sizes[symbol]);
1010
+ const magnitude = coef < 0 ? coef + (1 << size) - 1 : coef;
1011
+ bitWriter.writeBits(magnitude, size);
1012
+ zeroCount = 0;
1013
+ }
1014
+ }
1015
+ // Write EOB if there are trailing zeros
1016
+ if (zeroCount > 0) {
1017
+ bitWriter.writeBits(huffTable.codes[0x00], huffTable.sizes[0x00]);
1018
+ }
1019
+ }
1020
+ }
1021
+ exports.JPEGEncoder = JPEGEncoder;