You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Convenient function to decode the sixel data in `data`. Can be used for casual decoding and when you have the full image data at hand (not chunked). The function is actually a thin wrapper around the decoder, and spawns a new instance for every call.
12
+
Returns the decoding result as `{width, height, data32}`.
Async version of `decode`. Use this one in browser main context.
12
16
13
-
The `DefaultDecoder` is a general purpose decoder written in Typescript. It can decode level1 and level2
14
-
SIXEL data with reasonable speed and without any further preparations. It currently only supports _printerMode_(_terminalMode_ with proper shared/private palette semantics is planned).
15
17
16
-
Properties of `DefaultDecoder`:
18
+
#### Decoder
17
19
18
-
-`constructor(public fillColor: RGBA8888 = DEFAULT_BACKGROUND, public palette: RGBA8888[] = PALETTE_VT340_COLOR, public paletteLimit: number = 65536)`
19
-
Creates a new SIXEL image. The optional `fillColor` (default black) is used to fill
20
-
"holey pixels" with a background color during pixel transfer in `toPixelData`. Set `palette` to the
21
-
terminal's default colors (defaults to 16 VT340 colors). `paletteLimit` can be used to restrict the color registers.
20
+
The decoder uses webassembly for data decoding (see [/wasm](wasm/) for the webassembly parts), which gives a major performance improvement, compared to the old JS-based decoder.
22
21
23
-
-`width: number`
24
-
Pixel width of the image. Updates during `decode`. Other than stated in the SIXEL specification (DEC STD 070)
25
-
a width from raster attributes takes precedence, thus if a SIXEL data stream contains raster attributes
26
-
with a valid horizontal extend, width will always be set to this value, even for half transmitted images.
27
-
Also overlong sixel bands (a row of 6 vertical pixels) will be stripped to the raster attribute width.
28
-
If no raster attributes were transmitted (used in earlier SIXEL variant) width will be set to the longest sixel band width found.
22
+
Properties of `Decoder`:
29
23
30
-
-`height: number`
31
-
Pixel height of the image. Updates during `decode`. Height is either set from a valid vertical extend in
32
-
raster attributes, or grows with the number of sixel bands found in the data stream (number of bands * 6).
33
-
Raster attributes again have precedence over number of bands (also see `width`).
24
+
-`constructor(opts?: IDecoderOptions)`
25
+
Creates a new decoder instance. Spawns the internal wasm part synchronously, which will work in nodejs or a web worker context, but not in the main context of all browsers. Use the promisified constructor function `DecoderAsync` there instead.
26
+
Override default decoder options with `opts`. The options are used as default settings during image decoding and can be further overridden at individual images with `init`.
34
27
35
-
-`realWidth: number`
36
-
Other than `width` contains the real width of image data derived from longest SIXEL band found. For spec conform output use this.
Initialize the decoder for the next image. This must be called before doing any decoding.
30
+
The arguments can be used to override decoder default options. if omitted the default options will be used.
31
+
32
+
The `palette` argument is somewhat special, as it respects a 3-way handling:
33
+
- explicitly set: applies values from your palette
34
+
- set to `undefined`: applies values from default decoder palette
35
+
- set to `null`: no palette changes applied (leaves color registers from previous decoding untouched)
37
36
38
-
-`realHeight: number`
39
-
Contains the real height of the image data, which might be greater or lesser than `height`. For spec conform output use this.
37
+
The `truncate` settings indicates, whether the decoder should limit image dimensions to found raster attributes. While this is not 100% spec-conform, it is what most people would expect and how modern sixel encoder will encode the data. Therefore is set by default.
40
38
41
-
-`rasterWidth: number`
42
-
Contains width from raster attributes. 0 if no raster attributes were found.
39
+
-`decode(data: UintTypedArray, start: number = 0, end: number = data.length): void`
40
+
Decode sixel data provided in `data` from `start` to `end` (exclusive). `data` must be a typed array containing single byte values at the index positions.
41
+
The decoding is stream aware, thus can be fed with chunks of data until all image data was consumed.
43
42
44
-
-`rasterHeight: number`
45
-
Contains height from raster attributes. 0 if no raster attributes were found.
43
+
-`decodeString(data: string, start: number = 0, end: number = data.length): void`
44
+
Same as `decode`, but with string data. Do not use this method, if performance matters.
Contains the pixel ratio numerator and denominator given by raster attributes. Note that `toPixelData` does not evaluate these settings and always assumes 1:1.
46
+
-`release(): void`
47
+
Release internally held image ressources to free memory. This may be needed after decoding a rather big image consuming a lot of memory. The decoder will not free the memory on its own, instead tries to re-use ressources for the next image by default. Also see below about memory handling.
49
48
50
-
-`fillColor: RGBA8888`
51
-
Number respresenting the background fill color. A value of 0 will leave background pixels untouched.
52
-
The number depends on endianess of the architecture, create it with `toRGBA8888(r, g, b, a)`.
49
+
-`data32: Uint32Array`
50
+
Getter of the pixel data as 32-bit data (RGBA8888). The pixel array will always be sized as full image of the currently reported `width` and `height` dimensions (with `fillColor` applied). Note that the array is only borrowed in most cases and you may want to copy it before doing further processing.
51
+
It is possible to grab the pixels of partially transmitted images during chunk decoding. Here image dimensions may not be final yet and keep shifting until all data was processed.
53
52
54
-
-`memoryUsage: number`
55
-
Get current memory usage of the image data in bytes. Can be used to restrict image handling if memory is limited.
56
-
Note: This only accounts the image pixel data storage, the real value will be slightly higher due to some JS object overhead.
53
+
-`width: number`
54
+
Reports the current width of the current image. For `truncate=true` this may report the raster width, if a valid raster attribute was found. Otherwise reports rightmost band cursor advance seen so far.
57
55
58
-
-`decode(data: UintTypedArray, start: number = 0, end: number = data.length): void`
59
-
Decodes SIXEL bytes and updates the image data. This is done as a stream,
60
-
therefore it is possible to grab partly transmitted images (see "Simulate slow chunks" in browser example).
61
-
`data` can be any array like type with single byte values per index position.
62
-
Note: Normally SIXEL data is embedded in a DCS escape sequence. To properly handle the full sequence with introducer
63
-
and finalizer you should to use an escape sequence parser (like `node-ansiparser` or the parser found in `xterm.js`).
64
-
Note that this method is only meant for the data part of a SIXEL sequence (also see example `node_example_decode_full_sequence.js`).
56
+
-`height: number`
57
+
Reports the current height of the current image. Note that for `trancate=true` this may report the raster height, if a valid raster attribute was found. Otherwise reports the height in multiple of 6 pixels (seen sixel bands).
65
58
66
-
-`decodeString(data: string, start: number = 0, end: number = data.length): void`
67
-
Same as `decode` but with string data instead. For better performance use `decode`.
59
+
-`memoryUsage: number`
60
+
Reports the current memory usage of the decoder for wasm module memory and allocated pixel buffer.
68
61
69
-
-`toPixelData(target: Uint8ClampedArray, width: number, height: number, dx: number = 0, dy: number = 0, sx: number = 0, sy: number = 0, swidth: number = this.width, sheight: number = this.height, fillColor: RGBA8888 = this.fillColor): Uint8ClampedArray`
70
-
Writes pixel data to pixel array `target`. A pixel array can be obtained from `ImageData.data`, e.g. from a canvas.
71
-
`width` and `height` must contain the full dimension of the target. Use `dx`, `dy` (offset in target) and
72
-
`sx`, `sy` (offset in source) and `swidth`, `sheight` (area in source) for cropping/clipping. `fillColor` has the same
73
-
meaning as in the constructor, explicit setting it to 0 will leave non encoded pixels unaltered (pixels, that were not colored in the SIXEL data). This can be used for a transparency like effect (background/previous pixel value will remain). Returns the altered `target`.
62
+
-`properties: IDecoderProperties`
63
+
Reports various properties of the current decoder state.
64
+
65
+
-`palette: Uint32Array`
66
+
Returns the currently loaded palette (borrowed).
74
67
75
68
76
69
### Encoding
@@ -104,27 +97,30 @@ For encoding the library provides the following properties:
104
97
105
98
### Convenient Properties
106
99
107
-
Furthermore the library exposes some convenient properties:
100
+
Furthermore the library exposes some general purpose properties:
Performance is measured for typical actions based on 9-bit palette image:
141
138

142
139
@@ -147,39 +144,39 @@ Results:
147
144
Context "./lib/index.benchmark.js"
148
145
Context "testimage"
149
146
Context "pixel transfer"
150
-
Case "toPixelData - with fillColor" : 20 runs - average runtime: 1.42 ms
151
-
Case "toPixelData - without fillColor" : 20 runs - average runtime: 1.12 ms
147
+
Case "toPixelData - with fillColor" : 20 runs - average runtime: 1.38 ms
148
+
Case "toPixelData - without fillColor" : 20 runs - average runtime: 1.06 ms
152
149
Context "decode (DefaultDecoder)"
153
-
Case "decode" : 20 runs - average runtime: 4.34 ms
154
-
Case "decodeString" : 20 runs - average runtime: 4.62 ms
155
-
Case "decode + pixel transfer" : 20 runs - average runtime: 3.39 ms
150
+
Case "decode" : 20 runs - average runtime: 4.15 ms
151
+
Case "decodeString" : 20 runs - average runtime: 5.18 ms
152
+
Case "decode + pixel transfer" : 20 runs - average runtime: 3.17 ms
156
153
Context "decode (WasmDecoder)"
157
-
Case "decode" : 20 runs - average runtime: 1.35 ms
158
-
Case "decodeString" : 20 runs - average runtime: 1.81 ms
154
+
Case "decode" : 20 runs - average runtime: 1.27 ms
155
+
Case "decodeString" : 20 runs - average runtime: 1.66 ms
159
156
Context "encode"
160
-
Case "sixelEncode" : 20 runs - average runtime: 25.10 ms
161
-
Context "decode - testfiles (DefaultDecoder)"
162
-
Case "test1_clean.sixel" : 20 runs - average runtime: 16.75 ms
163
-
Case "test1_clean.sixel" : 20 runs - average throughput: 37.70 MB/s
164
-
Case "test2_clean.sixel" : 20 runs - average runtime: 7.23 ms
165
-
Case "test2_clean.sixel" : 20 runs - average throughput: 45.48 MB/s
166
-
Case "sampsa_reencoded_clean.six" : 20 runs - average runtime: 16.53 ms
167
-
Case "sampsa_reencoded_clean.six" : 20 runs - average throughput: 39.57 MB/s
168
-
Case "FullHD 12bit noise" : 20 runs - average runtime: 228.52 ms
169
-
Case "FullHD 12bit noise" : 20 runs - average throughput: 67.84 MB/s
170
-
Context "decode - testfiles (WasmDecoder)"
171
-
Case "test1_clean.sixel" : 20 runs - average runtime: 9.99 ms
172
-
Case "test1_clean.sixel" : 20 runs - average throughput: 61.25 MB/s
173
-
Case "test2_clean.sixel" : 20 runs - average runtime: 4.16 ms
174
-
Case "test2_clean.sixel" : 20 runs - average throughput: 76.79 MB/s
175
-
Case "sampsa_reencoded_clean.six" : 20 runs - average runtime: 10.54 ms
176
-
Case "sampsa_reencoded_clean.six" : 20 runs - average throughput: 61.23 MB/s
177
-
Case "FullHD 12bit noise" : 20 runs - average runtime: 100.77 ms
178
-
Case "FullHD 12bit noise" : 20 runs - average throughput: 153.86 MB/s
157
+
Case "sixelEncode" : 20 runs - average runtime: 22.23 ms
158
+
Context "decode - testfiles (SixelDecoder - old decoder)"
159
+
Case "test1_clean.sixel" : 20 runs - average runtime: 15.64 ms
160
+
Case "test1_clean.sixel" : 20 runs - average throughput: 41.48 MB/s
161
+
Case "test2_clean.sixel" : 20 runs - average runtime: 6.53 ms
162
+
Case "test2_clean.sixel" : 20 runs - average throughput: 48.90 MB/s
163
+
Case "sampsa_reencoded_clean.six" : 20 runs - average runtime: 15.23 ms
164
+
Case "sampsa_reencoded_clean.six" : 20 runs - average throughput: 42.46 MB/s
165
+
Case "FullHD 12bit noise" : 20 runs - average runtime: 215.23 ms
166
+
Case "FullHD 12bit noise" : 20 runs - average throughput: 72.03 MB/s
167
+
Context "decode - testfiles (Decoder - new decoder)"
168
+
Case "test1_clean.sixel" : 20 runs - average runtime: 4.30 ms
169
+
Case "test1_clean.sixel" : 20 runs - average throughput: 138.79 MB/s
170
+
Case "test2_clean.sixel" : 20 runs - average runtime: 2.25 ms
171
+
Case "test2_clean.sixel" : 20 runs - average throughput: 140.65 MB/s
172
+
Case "sampsa_reencoded_clean.six" : 20 runs - average runtime: 4.40 ms
173
+
Case "sampsa_reencoded_clean.six" : 20 runs - average throughput: 147.16 MB/s
174
+
Case "FullHD 12bit noise" : 20 runs - average runtime: 48.82 ms
175
+
Case "FullHD 12bit noise" : 20 runs - average throughput: 317.88 MB/s
176
+
Case "640x480 9bit tiles" : 20 runs - average runtime: 0.65 ms
177
+
Case "640x480 9bit tiles" : 20 runs - average throughput: 154.89 MB/s
179
178
```
180
-
`WasmDecoder` is roughly 1.5x - 2.3x faster than `DefaultDecoder`.
181
-
TODO...
182
-
179
+
Note that the new decoder is roughly 3-4 times faster than the old one. Therefore the old decoder will be removed with one of the next releases.
183
180
184
181
185
182
### Decoder usage
@@ -271,8 +268,8 @@ To not run into out of memory issues the decoder respects an upper memory limit
271
268
The default limit is set rather high (hardcoded to 128 MB) and can be adjusted in the decoder options
272
269
as `memoryLimit` in bytes. You should always adjust that value to your needs.
273
270
274
-
During chunk decoding the memory usage can be tracked with `memoryUsage`. Other than `memoryLimit`,
275
-
this value also accounts the static memory taken by the wasm module, thus is slightly higher and
271
+
During chunk decoding the memory usage can be further tracked with `memoryUsage`. Other than `memoryLimit`,
272
+
this value also accounts the static memory taken by the wasm instance, thus is slightly higher and
276
273
closer to the real usage of the decoder. Note that the decoder will try to pre-allocate the pixel array,
277
274
if it can derive the dimensions early, thus `memoryUsage` might not change anymore for subsequent
278
275
chunks after an initial jump. If re-allocation is needed during decoding, the decoder will hold up to twice
@@ -281,7 +278,7 @@ of `memoryLimit` for a short amount of time.
281
278
During decoding the decoder will throw an error, if the needed pixel memory exceeds `memoryLimit`.
282
279
283
280
Between multiple images the decoder will not free the pixel memory of the previous image.
284
-
This is an optimization to lower allocation and GC pressure of the decoder.
281
+
This is an optimization to lower allocation and GC pressure.
285
282
Call `release` after decoding to explicitly free the pixel memory.
286
283
287
284
Rules of thumb regarding memory:
@@ -290,23 +287,17 @@ Rules of thumb regarding memory:
290
287
- under memory pressure set `memoryLimit` rather low, always call `release`
291
288
292
289
293
-
### Encoder usage
294
-
295
-
TODO...
296
-
297
-
298
290
### Package format and browser bundles
299
291
300
292
The node package comes as CommonJS and can be used as usual.
301
-
An ESM package version is planned for a later release.
293
+
An ESM package version for nodejs is planned for a later release.
302
294
303
295
For easier usage in the browser the package contains several prebuilt bundles under `/dist`:
304
296
- decode - color functions, default palettes and decoder
305
297
- encode - color functions, default palettes and encoder
306
298
- full - full package containing all definitions.
307
299
308
-
The browser bundles come in UMD and ESM flavors. Note that the UMD bundles export
309
-
the symbols under `sixel`.
300
+
The browser bundles come in UMD and ESM flavors. At the current stage the ESM builds are mostly untested (treat them as alpha, bug reports are more than welcome). Note that the UMD bundles export the symbols under the name `sixel`.
310
301
311
302
Some usage examples:
312
303
- vanilla usage with UMD version:
@@ -343,8 +334,10 @@ Some usage examples:
343
334
344
335
345
336
### Status
346
-
Currently beta, still more tests to come. Also the API might still change.
337
+
Beta.
347
338
339
+
Automatically tested on nodejs 12, 14 and 16.
340
+
Manually tested on recent versions of Chrome, Firefox and Webkit.
0 commit comments