taro-bluetooth-print 2.8.3 → 2.9.0
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.
- package/CHANGELOG.md +28 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/types/core/BluetoothPrinter.d.ts +21 -4
- package/dist/types/errors/CommandBuildError.d.ts +40 -0
- package/dist/types/errors/ConnectionError.d.ts +45 -0
- package/dist/types/errors/PrintJobError.d.ts +42 -0
- package/dist/types/errors/index.d.ts +9 -0
- package/dist/types/factory/PrinterFactory.d.ts +108 -0
- package/dist/types/factory/index.d.ts +6 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/services/interfaces/ICommandBuilder.d.ts +123 -0
- package/dist/types/services/interfaces/IConnectionManager.d.ts +49 -0
- package/dist/types/services/interfaces/IPrintJobManager.d.ts +67 -0
- package/dist/types/services/interfaces/index.d.ts +6 -233
- package/package.json +1 -1
- package/src/core/BluetoothPrinter.ts +47 -50
- package/src/errors/CommandBuildError.ts +72 -0
- package/src/errors/ConnectionError.ts +78 -0
- package/src/errors/PrintJobError.ts +75 -0
- package/src/errors/index.ts +10 -0
- package/src/factory/PrinterFactory.ts +139 -0
- package/src/factory/index.ts +12 -0
- package/src/index.ts +11 -0
- package/src/services/interfaces/ICommandBuilder.ts +145 -0
- package/src/services/interfaces/IConnectionManager.ts +58 -0
- package/src/services/interfaces/IPrintJobManager.ts +83 -0
- package/src/services/interfaces/index.ts +5 -265
- package/src/utils/image.ts +41 -39
|
@@ -2,271 +2,11 @@
|
|
|
2
2
|
* Service Interfaces
|
|
3
3
|
*
|
|
4
4
|
* Defines the interfaces for the core services used by BluetoothPrinter
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { IAdapterOptions, IQrOptions, PrinterState, IPrinterAdapter } from '@/types';
|
|
8
|
-
import { TextAlign, TextStyle } from '@/formatter';
|
|
9
|
-
import { BarcodeOptions } from '@/barcode';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Connection Manager Interface
|
|
13
|
-
*
|
|
14
|
-
* Manages Bluetooth device connections
|
|
15
|
-
*/
|
|
16
|
-
export interface IConnectionManager {
|
|
17
|
-
/**
|
|
18
|
-
* Connects to a Bluetooth device
|
|
19
|
-
*
|
|
20
|
-
* @param deviceId - Bluetooth device ID
|
|
21
|
-
* @param options - Connection options
|
|
22
|
-
* @returns Promise<void>
|
|
23
|
-
*/
|
|
24
|
-
connect(deviceId: string, options?: { retries?: number; timeout?: number }): Promise<void>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Disconnects from the current device
|
|
28
|
-
*
|
|
29
|
-
* @returns Promise<void>
|
|
30
|
-
*/
|
|
31
|
-
disconnect(): Promise<void>;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Checks if a device is connected
|
|
35
|
-
*
|
|
36
|
-
* @returns boolean - True if connected, false otherwise
|
|
37
|
-
*/
|
|
38
|
-
isConnected(): boolean;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Gets the current device ID
|
|
42
|
-
*
|
|
43
|
-
* @returns string | null - Device ID or null if not connected
|
|
44
|
-
*/
|
|
45
|
-
getDeviceId(): string | null;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Gets the current connection state
|
|
49
|
-
*
|
|
50
|
-
* @returns PrinterState - Current state
|
|
51
|
-
*/
|
|
52
|
-
getState(): PrinterState;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Gets the printer adapter instance
|
|
56
|
-
*
|
|
57
|
-
* @returns IPrinterAdapter - Printer adapter
|
|
58
|
-
*/
|
|
59
|
-
getAdapter(): IPrinterAdapter;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Print Job Manager Interface
|
|
64
|
-
*
|
|
65
|
-
* Manages print jobs, including pause/resume/cancel functionality
|
|
66
|
-
*/
|
|
67
|
-
export interface IPrintJobManager {
|
|
68
|
-
/**
|
|
69
|
-
* Starts a print job
|
|
70
|
-
*
|
|
71
|
-
* @param buffer - Print data buffer
|
|
72
|
-
* @returns Promise<void>
|
|
73
|
-
*/
|
|
74
|
-
start(buffer: Uint8Array, options?: { jobId?: string }): Promise<void>;
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Pauses the current print job
|
|
78
|
-
*/
|
|
79
|
-
pause(): void;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Resumes a paused print job
|
|
83
|
-
*
|
|
84
|
-
* @returns Promise<void>
|
|
85
|
-
*/
|
|
86
|
-
resume(jobId?: string): Promise<void>;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Cancels the current print job
|
|
90
|
-
*/
|
|
91
|
-
cancel(): void;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Gets the number of bytes remaining to print
|
|
95
|
-
*
|
|
96
|
-
* @returns number - Bytes remaining
|
|
97
|
-
*/
|
|
98
|
-
remaining(): number;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Checks if the print job is paused
|
|
102
|
-
*
|
|
103
|
-
* @returns boolean - True if paused, false otherwise
|
|
104
|
-
*/
|
|
105
|
-
isPaused(): boolean;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Checks if a print job is in progress
|
|
109
|
-
*
|
|
110
|
-
* @returns boolean - True if in progress, false otherwise
|
|
111
|
-
*/
|
|
112
|
-
isInProgress(): boolean;
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Sets adapter options for write operations
|
|
116
|
-
*
|
|
117
|
-
* @param options - Adapter options
|
|
118
|
-
*/
|
|
119
|
-
setOptions(options: IAdapterOptions): void;
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Sets the progress callback
|
|
123
|
-
*
|
|
124
|
-
* @param callback - Progress callback function
|
|
125
|
-
*/
|
|
126
|
-
setProgressCallback(callback?: (sent: number, total: number) => void): void;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Sets the job state change callback
|
|
130
|
-
*
|
|
131
|
-
* @param callback - Job state change callback function
|
|
132
|
-
*/
|
|
133
|
-
setJobStateCallback(
|
|
134
|
-
callback?: (state: 'in-progress' | 'paused' | 'completed' | 'cancelled') => void
|
|
135
|
-
): void;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Command Builder Interface
|
|
140
5
|
*
|
|
141
|
-
*
|
|
6
|
+
* @packageDocumentation
|
|
142
7
|
*/
|
|
143
|
-
export interface ICommandBuilder {
|
|
144
|
-
/**
|
|
145
|
-
* Adds text to the print queue
|
|
146
|
-
*
|
|
147
|
-
* @param content - Text content
|
|
148
|
-
* @param encoding - Text encoding
|
|
149
|
-
* @returns this - For method chaining
|
|
150
|
-
*/
|
|
151
|
-
text(content: string, encoding?: string): this;
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Adds line feeds to the print queue
|
|
155
|
-
*
|
|
156
|
-
* @param lines - Number of lines to feed
|
|
157
|
-
* @returns this - For method chaining
|
|
158
|
-
*/
|
|
159
|
-
feed(lines?: number): this;
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Adds a paper cut command to the print queue
|
|
163
|
-
*
|
|
164
|
-
* @returns this - For method chaining
|
|
165
|
-
*/
|
|
166
|
-
cut(): this;
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Adds an image to the print queue
|
|
170
|
-
*
|
|
171
|
-
* @param data - Image data as Uint8Array
|
|
172
|
-
* @param width - Image width
|
|
173
|
-
* @param height - Image height
|
|
174
|
-
* @returns this - For method chaining
|
|
175
|
-
*/
|
|
176
|
-
image(data: Uint8Array, width: number, height: number): this;
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Adds a QR code to the print queue
|
|
180
|
-
*
|
|
181
|
-
* @param content - QR code content
|
|
182
|
-
* @param options - QR code options
|
|
183
|
-
* @returns this - For method chaining
|
|
184
|
-
*/
|
|
185
|
-
qr(content: string, options?: IQrOptions): this;
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Clears the print queue
|
|
189
|
-
*
|
|
190
|
-
* @returns this - For method chaining
|
|
191
|
-
*/
|
|
192
|
-
clear(): this;
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Sets text alignment
|
|
196
|
-
*
|
|
197
|
-
* @param alignment - Text alignment (left, center, right)
|
|
198
|
-
* @returns this - For method chaining
|
|
199
|
-
*/
|
|
200
|
-
align(alignment: TextAlign): this;
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Sets character size (width and height scale)
|
|
204
|
-
*
|
|
205
|
-
* @param width - Width scale factor (1-8)
|
|
206
|
-
* @param height - Height scale factor (1-8)
|
|
207
|
-
* @returns this - For method chaining
|
|
208
|
-
*/
|
|
209
|
-
setSize(width: number, height: number): this;
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Sets bold text mode
|
|
213
|
-
*
|
|
214
|
-
* @param enabled - Enable or disable bold
|
|
215
|
-
* @returns this - For method chaining
|
|
216
|
-
*/
|
|
217
|
-
setBold(enabled: boolean): this;
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Sets underline text mode
|
|
221
|
-
*
|
|
222
|
-
* @param enabled - Enable or disable underline
|
|
223
|
-
* @returns this - For method chaining
|
|
224
|
-
*/
|
|
225
|
-
setUnderline(enabled: boolean): this;
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Sets inverse printing mode (white on black)
|
|
229
|
-
*
|
|
230
|
-
* @param enabled - Enable or disable inverse
|
|
231
|
-
* @returns this - For method chaining
|
|
232
|
-
*/
|
|
233
|
-
setInverse(enabled: boolean): this;
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Sets multiple text style properties at once
|
|
237
|
-
*
|
|
238
|
-
* @param style - Text style configuration
|
|
239
|
-
* @returns this - For method chaining
|
|
240
|
-
*/
|
|
241
|
-
setStyle(style: TextStyle): this;
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Resets all text formatting to default
|
|
245
|
-
*
|
|
246
|
-
* @returns this - For method chaining
|
|
247
|
-
*/
|
|
248
|
-
resetStyle(): this;
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Adds a 1D barcode to the print queue
|
|
252
|
-
*
|
|
253
|
-
* @param content - Barcode content/data
|
|
254
|
-
* @param options - Barcode options
|
|
255
|
-
* @returns this - For method chaining
|
|
256
|
-
*/
|
|
257
|
-
barcode(content: string, options: BarcodeOptions): this;
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Gets the current buffer
|
|
261
|
-
*
|
|
262
|
-
* @returns Uint8Array - Current print buffer
|
|
263
|
-
*/
|
|
264
|
-
getBuffer(): Uint8Array;
|
|
265
8
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
*/
|
|
271
|
-
getTotalBytes(): number;
|
|
272
|
-
}
|
|
9
|
+
// Re-export individual interfaces for tree-shaking and clear dependencies
|
|
10
|
+
export type { IConnectionManager } from './IConnectionManager';
|
|
11
|
+
export type { IPrintJobManager } from './IPrintJobManager';
|
|
12
|
+
export type { ICommandBuilder } from './ICommandBuilder';
|
package/src/utils/image.ts
CHANGED
|
@@ -199,9 +199,9 @@ export class ImageProcessing {
|
|
|
199
199
|
const grayscale = new Float32Array(width * height);
|
|
200
200
|
for (let i = 0; i < data.length; i += 4) {
|
|
201
201
|
const idx = i >> 2;
|
|
202
|
-
const r = data[i]
|
|
203
|
-
const g = data[i + 1]
|
|
204
|
-
const b = data[i + 2]
|
|
202
|
+
const r = data[i]!;
|
|
203
|
+
const g = data[i + 1]!;
|
|
204
|
+
const b = data[i + 2]!;
|
|
205
205
|
grayscale[idx] = (r * 299 + g * 587 + b * 114) / 1000;
|
|
206
206
|
}
|
|
207
207
|
return grayscale;
|
|
@@ -215,7 +215,7 @@ export class ImageProcessing {
|
|
|
215
215
|
if (contrast === 1.0 && brightness === 0.0) return grayscale;
|
|
216
216
|
const adjusted = new Float32Array(grayscale);
|
|
217
217
|
for (let i = 0; i < adjusted.length; i++) {
|
|
218
|
-
const value = adjusted[i]
|
|
218
|
+
const value = adjusted[i]!;
|
|
219
219
|
adjusted[i] = Math.max(0, Math.min(255, (value - 128) * contrast + 128 + brightness * 255));
|
|
220
220
|
}
|
|
221
221
|
return adjusted;
|
|
@@ -292,13 +292,13 @@ export class ImageProcessing {
|
|
|
292
292
|
for (let x = 0; x < width; x++) {
|
|
293
293
|
const idx = y * width + x;
|
|
294
294
|
const oldPixel = grayscale[idx];
|
|
295
|
-
const newPixel = oldPixel < threshold ? 0 : 255;
|
|
295
|
+
const newPixel = oldPixel! < threshold ? 0 : 255;
|
|
296
296
|
if (newPixel === 0) {
|
|
297
297
|
const byteIdx = y * bytesPerLine + Math.floor(x / 8);
|
|
298
298
|
const bitIdx = 7 - (x % 8);
|
|
299
|
-
bitmap[byteIdx] = bitmap[byteIdx] | (1 << bitIdx);
|
|
299
|
+
bitmap[byteIdx] = bitmap[byteIdx]! | (1 << bitIdx);
|
|
300
300
|
}
|
|
301
|
-
const err = oldPixel - newPixel;
|
|
301
|
+
const err = oldPixel! - newPixel;
|
|
302
302
|
this.distributeErr(grayscale, width, height, x + 1, y, (err * 7) / 16);
|
|
303
303
|
this.distributeErr(grayscale, width, height, x - 1, y + 1, (err * 3) / 16);
|
|
304
304
|
this.distributeErr(grayscale, width, height, x, y + 1, (err * 5) / 16);
|
|
@@ -321,13 +321,13 @@ export class ImageProcessing {
|
|
|
321
321
|
for (let x = 0; x < width; x++) {
|
|
322
322
|
const idx = y * width + x;
|
|
323
323
|
const oldPixel = grayscale[idx];
|
|
324
|
-
const newPixel = oldPixel < threshold ? 0 : 255;
|
|
324
|
+
const newPixel = oldPixel! < threshold ? 0 : 255;
|
|
325
325
|
if (newPixel === 0) {
|
|
326
326
|
const byteIdx = y * bytesPerLine + Math.floor(x / 8);
|
|
327
327
|
const bitIdx = 7 - (x % 8);
|
|
328
|
-
bitmap[byteIdx] = bitmap[byteIdx] | (1 << bitIdx);
|
|
328
|
+
bitmap[byteIdx] = bitmap[byteIdx]! | (1 << bitIdx);
|
|
329
329
|
}
|
|
330
|
-
const err = (oldPixel - newPixel) / 8;
|
|
330
|
+
const err = (oldPixel! - newPixel) / 8;
|
|
331
331
|
this.distributeErr(grayscale, width, height, x + 1, y, err);
|
|
332
332
|
this.distributeErr(grayscale, width, height, x + 2, y, err);
|
|
333
333
|
this.distributeErr(grayscale, width, height, x - 1, y + 1, err);
|
|
@@ -364,10 +364,10 @@ export class ImageProcessing {
|
|
|
364
364
|
const bayerRow = matrix[y % matrixSize] ?? [];
|
|
365
365
|
const bayerVal = bayerRow[x % matrixSize] ?? 0;
|
|
366
366
|
const adjustedThreshold = thresholdOffset + (bayerVal / matrixMax) * 48;
|
|
367
|
-
if (pixel < adjustedThreshold) {
|
|
367
|
+
if (pixel! < adjustedThreshold) {
|
|
368
368
|
const byteIdx = y * bytesPerLine + Math.floor(x / 8);
|
|
369
369
|
const bitIdx = 7 - (x % 8);
|
|
370
|
-
bitmap[byteIdx] = bitmap[byteIdx] | (1 << bitIdx);
|
|
370
|
+
bitmap[byteIdx] = bitmap[byteIdx]! | (1 << bitIdx);
|
|
371
371
|
}
|
|
372
372
|
}
|
|
373
373
|
}
|
|
@@ -394,11 +394,11 @@ export class ImageProcessing {
|
|
|
394
394
|
const localX = x % cellSize;
|
|
395
395
|
const row = thresholds[localY] ?? [];
|
|
396
396
|
const t = row[localX] ?? 128;
|
|
397
|
-
const adjusted = t + (pixel < threshold ? -30 : 30);
|
|
398
|
-
if (pixel < adjusted) {
|
|
397
|
+
const adjusted = t + (pixel! < threshold ? -30 : 30);
|
|
398
|
+
if (pixel! < adjusted) {
|
|
399
399
|
const byteIdx = y * bytesPerLine + Math.floor(x / 8);
|
|
400
400
|
const bitIdx = 7 - (x % 8);
|
|
401
|
-
bitmap[byteIdx] = bitmap[byteIdx] | (1 << bitIdx);
|
|
401
|
+
bitmap[byteIdx] = bitmap[byteIdx]! | (1 << bitIdx);
|
|
402
402
|
}
|
|
403
403
|
}
|
|
404
404
|
}
|
|
@@ -441,13 +441,13 @@ export class ImageProcessing {
|
|
|
441
441
|
for (let x = 0; x < width; x++) {
|
|
442
442
|
const idx = y * width + x;
|
|
443
443
|
const oldPixel = grayscale[idx];
|
|
444
|
-
const newPixel = oldPixel < threshold ? 0 : 255;
|
|
444
|
+
const newPixel = oldPixel! < threshold ? 0 : 255;
|
|
445
445
|
if (newPixel === 0) {
|
|
446
446
|
const byteIdx = y * bytesPerLine + Math.floor(x / 8);
|
|
447
447
|
const bitIdx = 7 - (x % 8);
|
|
448
|
-
bitmap[byteIdx] = bitmap[byteIdx] | (1 << bitIdx);
|
|
448
|
+
bitmap[byteIdx] = bitmap[byteIdx]! | (1 << bitIdx);
|
|
449
449
|
}
|
|
450
|
-
const err = oldPixel - newPixel;
|
|
450
|
+
const err = oldPixel! - newPixel;
|
|
451
451
|
this.distributeErr(grayscale, width, height, x + 1, y, (err * 5) / 32);
|
|
452
452
|
this.distributeErr(grayscale, width, height, x - 1, y + 1, (err * 3) / 32);
|
|
453
453
|
this.distributeErr(grayscale, width, height, x, y + 1, (err * 5) / 32);
|
|
@@ -475,13 +475,13 @@ export class ImageProcessing {
|
|
|
475
475
|
for (let x = 0; x < width; x++) {
|
|
476
476
|
const idx = y * width + x;
|
|
477
477
|
const oldPixel = grayscale[idx];
|
|
478
|
-
const newPixel = oldPixel < threshold ? 0 : 255;
|
|
478
|
+
const newPixel = oldPixel! < threshold ? 0 : 255;
|
|
479
479
|
if (newPixel === 0) {
|
|
480
480
|
const byteIdx = y * bytesPerLine + Math.floor(x / 8);
|
|
481
481
|
const bitIdx = 7 - (x % 8);
|
|
482
|
-
bitmap[byteIdx] = bitmap[byteIdx] | (1 << bitIdx);
|
|
482
|
+
bitmap[byteIdx] = bitmap[byteIdx]! | (1 << bitIdx);
|
|
483
483
|
}
|
|
484
|
-
const err = oldPixel - newPixel;
|
|
484
|
+
const err = oldPixel! - newPixel;
|
|
485
485
|
this.distributeErr(grayscale, width, height, x + 1, y, (err * 8) / 42);
|
|
486
486
|
this.distributeErr(grayscale, width, height, x + 2, y, (err * 4) / 42);
|
|
487
487
|
this.distributeErr(grayscale, width, height, x - 2, y + 1, (err * 2) / 42);
|
|
@@ -512,10 +512,10 @@ export class ImageProcessing {
|
|
|
512
512
|
for (let x = 0; x < width; x++) {
|
|
513
513
|
const idx = y * width + x;
|
|
514
514
|
const pixel = grayscale[idx];
|
|
515
|
-
if (pixel < threshold) {
|
|
515
|
+
if (pixel! < threshold) {
|
|
516
516
|
const byteIdx = y * bytesPerLine + Math.floor(x / 8);
|
|
517
517
|
const bitIdx = 7 - (x % 8);
|
|
518
|
-
bitmap[byteIdx] = bitmap[byteIdx] | (1 << bitIdx);
|
|
518
|
+
bitmap[byteIdx] = bitmap[byteIdx]! | (1 << bitIdx);
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
521
|
}
|
|
@@ -534,7 +534,7 @@ export class ImageProcessing {
|
|
|
534
534
|
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
|
535
535
|
const idx = ny * width + nx;
|
|
536
536
|
const current = grayscale[idx];
|
|
537
|
-
grayscale[idx] = Math.max(0, Math.min(255, current + error));
|
|
537
|
+
grayscale[idx] = Math.max(0, Math.min(255, current! + error));
|
|
538
538
|
}
|
|
539
539
|
}
|
|
540
540
|
|
|
@@ -581,10 +581,10 @@ export class ImageProcessing {
|
|
|
581
581
|
const sjy = Math.min(srcHeight - 1, Math.round(y * sy));
|
|
582
582
|
const si = (sjy * srcWidth + sjx) * 4;
|
|
583
583
|
const di = (y * destWidth + x) * 4;
|
|
584
|
-
destData[di] = srcData[si]
|
|
585
|
-
destData[di + 1] = srcData[si + 1]
|
|
586
|
-
destData[di + 2] = srcData[si + 2]
|
|
587
|
-
destData[di + 3] = srcData[si + 3]
|
|
584
|
+
destData[di] = srcData[si]!;
|
|
585
|
+
destData[di + 1] = srcData[si + 1]!;
|
|
586
|
+
destData[di + 2] = srcData[si + 2]!;
|
|
587
|
+
destData[di + 3] = srcData[si + 3]!;
|
|
588
588
|
}
|
|
589
589
|
}
|
|
590
590
|
}
|
|
@@ -618,7 +618,8 @@ export class ImageProcessing {
|
|
|
618
618
|
const ii2 = (y1 * srcWidth + x2) * 4 + c;
|
|
619
619
|
const ii3 = (y2 * srcWidth + x1) * 4 + c;
|
|
620
620
|
const ii4 = (y2 * srcWidth + x2) * 4 + c;
|
|
621
|
-
const v =
|
|
621
|
+
const v =
|
|
622
|
+
srcData[ii1]! * w1 + srcData[ii2]! * w2 + srcData[ii3]! * w3 + srcData[ii4]! * w4;
|
|
622
623
|
destData[(y * destWidth + x) * 4 + c] = Math.round(v);
|
|
623
624
|
}
|
|
624
625
|
}
|
|
@@ -636,12 +637,12 @@ export class ImageProcessing {
|
|
|
636
637
|
const result = new Uint8Array(data.length);
|
|
637
638
|
for (let i = 0; i < data.length; i += 4) {
|
|
638
639
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- lut has 256 entries, data[i] is 0-255
|
|
639
|
-
result[i] = lut[data[i]]!;
|
|
640
|
+
result[i] = lut[data[i]!]!;
|
|
640
641
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
641
|
-
result[i + 1] = lut[data[i + 1]]!;
|
|
642
|
+
result[i + 1] = lut[data[i + 1]!]!;
|
|
642
643
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
643
|
-
result[i + 2] = lut[data[i + 2]]!;
|
|
644
|
-
result[i + 3] = data[i + 3]
|
|
644
|
+
result[i + 2] = lut[data[i + 2]!]!;
|
|
645
|
+
result[i + 3] = data[i + 3]!;
|
|
645
646
|
}
|
|
646
647
|
return result;
|
|
647
648
|
}
|
|
@@ -658,7 +659,7 @@ export class ImageProcessing {
|
|
|
658
659
|
const ny2 = Math.max(0, Math.min(height - 1, y + dy));
|
|
659
660
|
const si = (ny2 * width + nx) * 4;
|
|
660
661
|
for (let c = 0; c < 4; c++) {
|
|
661
|
-
window.push(data[si + c]);
|
|
662
|
+
window.push(data[si + c]!);
|
|
662
663
|
}
|
|
663
664
|
}
|
|
664
665
|
}
|
|
@@ -691,7 +692,7 @@ export class ImageProcessing {
|
|
|
691
692
|
const ny2 = Math.max(0, Math.min(height - 1, y + ky - kHalf));
|
|
692
693
|
const si = (ny2 * width + nx) * 4 + c;
|
|
693
694
|
const kv = kernel[ky]?.[kx] ?? 0;
|
|
694
|
-
sum += data[si] * kv;
|
|
695
|
+
sum += data[si]! * kv;
|
|
695
696
|
}
|
|
696
697
|
}
|
|
697
698
|
result[di + c] = Math.max(0, Math.min(255, Math.round(sum)));
|
|
@@ -702,14 +703,15 @@ export class ImageProcessing {
|
|
|
702
703
|
}
|
|
703
704
|
|
|
704
705
|
private static applyPosterization(data: Uint8Array, levels: number): Uint8Array {
|
|
706
|
+
if (data.length < 4) return new Uint8Array(0);
|
|
705
707
|
const lv = Math.max(1, Math.min(8, levels));
|
|
706
708
|
const step = 255 / (Math.pow(2, lv) - 1);
|
|
707
709
|
const result = new Uint8Array(data.length);
|
|
708
710
|
for (let i = 0; i < data.length; i += 4) {
|
|
709
|
-
result[i] = Math.round(Math.round(data[i] / step) * step);
|
|
710
|
-
result[i + 1] = Math.round(Math.round(data[i + 1] / step) * step);
|
|
711
|
-
result[i + 2] = Math.round(Math.round(data[i + 2] / step) * step);
|
|
712
|
-
result[i + 3] = data[i + 3]
|
|
711
|
+
result[i] = Math.round(Math.round(data[i]! / step) * step);
|
|
712
|
+
result[i + 1] = Math.round(Math.round(data[i + 1]! / step) * step);
|
|
713
|
+
result[i + 2] = Math.round(Math.round(data[i + 2]! / step) * step);
|
|
714
|
+
result[i + 3] = data[i + 3]!;
|
|
713
715
|
}
|
|
714
716
|
return result;
|
|
715
717
|
}
|