Skip to content

Commit 4f3eba3

Browse files
committed
polish docs
1 parent 0e8c42f commit 4f3eba3

File tree

2 files changed

+94
-100
lines changed

2 files changed

+94
-100
lines changed

README.md

+91-98
Original file line numberDiff line numberDiff line change
@@ -5,72 +5,65 @@ SIXEL image decoding / encoding library for node and the browser.
55

66
### Decoding
77

8-
For decoding the library provides two decoder classes with slightly different semantics.
8+
For decoding the library provides a stream decoder, that can either be used directly or with the convenient functions.
99

10+
- `decode(data: UintTypedArray | string, opts?: IDecoderOptions): IDecodeResult`
11+
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}`.
1013

11-
#### DefaultDecoder
14+
- `decodeAsync(data: UintTypedArray | string, opts?: IDecoderOptions): Promise<IDecodeResult>`
15+
Async version of `decode`. Use this one in browser main context.
1216

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).
1517

16-
Properties of `DefaultDecoder`:
18+
#### Decoder
1719

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.
2221

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`:
2923

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`.
3427

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.
28+
- `init(fillColor?: RGBA8888, palette?: Uint32Array, paletteLimit?: number, truncate?: boolean)`
29+
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)
3736

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.
4038

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.
4342

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.
4645

47-
- `rasterRatioNumerator: number` & `rasterRatioDenominator: number`
48-
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.
4948

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.
5352

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.
5755

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).
6558

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.
6861

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).
7467

7568

7669
### Encoding
@@ -104,27 +97,30 @@ For encoding the library provides the following properties:
10497

10598
### Convenient Properties
10699

107-
Furthermore the library exposes some convenient properties:
100+
Furthermore the library exposes some general purpose properties:
108101

109102
- `function toRGBA8888(r: number, g: number, b: number, a: number = 255): RGBA8888`
110103
Converts the RGBA channel values to the native color type `RGBA8888`.
111104

112105
- `function fromRGBA8888(color: RGBA8888): number[]`
113106
Converts the native color to an array of [r, g, b, a].
114107

115-
- `PALETTE_VT340_COLOR: RGBA8888[]`
116-
16 color palette of VT340.
108+
- `PALETTE_VT340_COLOR: Uint32Array`
109+
16 color palette of VT340 (as `RGBA8888`).
117110

118-
- `PALETTE_VT340_GREY: RGBA8888[]`
119-
16 monochrome palette of VT340.
111+
- `PALETTE_VT340_GREY: Uint32Array`
112+
16 monochrome palette of VT340 (as `RGBA8888`).
120113

121-
- `PALETTE_ANSI_256: RGBA8888[]`
122-
256 ANSI color palette derived from xterm.
114+
- `PALETTE_ANSI_256: Uint32Array`
115+
256 ANSI color palette derived from xterm (as `RGBA8888`).
123116

124117

125118
### Installation
126119
Install the library with `npm install sixel`.
127120

121+
For direct usage in the browser, see under "browser bundles" below.
122+
123+
128124
### Examples and browser demo
129125
See the example files in `/examples` for decoding/encoding in nodejs. Note that the examples and the
130126
browser demo are not part of the npm package, clone the repo and run `npm install` if you want to see them in action.
@@ -136,7 +132,8 @@ Encoding can be tested in a SIXEL capable terminal with `img2sixel.js`, e.g.
136132
$> node img2sixel.js -p16 http://leeoniya.github.io/RgbQuant.js/demo/img/bluff.jpg
137133
```
138134

139-
## Benchmarks
135+
136+
### Benchmarks
140137
Performance is measured for typical actions based on 9-bit palette image:
141138
![test image](palette.png "test image")
142139

@@ -147,39 +144,39 @@ Results:
147144
Context "./lib/index.benchmark.js"
148145
Context "testimage"
149146
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
152149
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
156153
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
159156
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
179178
```
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.
183180

184181

185182
### Decoder usage
@@ -271,8 +268,8 @@ To not run into out of memory issues the decoder respects an upper memory limit
271268
The default limit is set rather high (hardcoded to 128 MB) and can be adjusted in the decoder options
272269
as `memoryLimit` in bytes. You should always adjust that value to your needs.
273270

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
276273
closer to the real usage of the decoder. Note that the decoder will try to pre-allocate the pixel array,
277274
if it can derive the dimensions early, thus `memoryUsage` might not change anymore for subsequent
278275
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.
281278
During decoding the decoder will throw an error, if the needed pixel memory exceeds `memoryLimit`.
282279

283280
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.
285282
Call `release` after decoding to explicitly free the pixel memory.
286283

287284
Rules of thumb regarding memory:
@@ -290,23 +287,17 @@ Rules of thumb regarding memory:
290287
- under memory pressure set `memoryLimit` rather low, always call `release`
291288

292289

293-
### Encoder usage
294-
295-
TODO...
296-
297-
298290
### Package format and browser bundles
299291

300292
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.
302294

303295
For easier usage in the browser the package contains several prebuilt bundles under `/dist`:
304296
- decode - color functions, default palettes and decoder
305297
- encode - color functions, default palettes and encoder
306298
- full - full package containing all definitions.
307299

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`.
310301

311302
Some usage examples:
312303
- vanilla usage with UMD version:
@@ -343,8 +334,10 @@ Some usage examples:
343334

344335

345336
### Status
346-
Currently beta, still more tests to come. Also the API might still change.
337+
Beta.
347338

339+
Automatically tested on nodejs 12, 14 and 16.
340+
Manually tested on recent versions of Chrome, Firefox and Webkit.
348341

349342
### References
350343

wasm/README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
## Sixel band decoder
33

4+
45
__Features__:
56
- written in C
67
- allocation free (single instance static memory)
@@ -153,6 +154,6 @@ There are probably more deviations from the SIXEL spec not listed here.
153154
- undecided: establish some real height accounting for M1
154155

155156

156-
### State
157+
### Status
157158

158-
Alpha, still way to go.
159+
Beta. The code is tested with unit/regression tests from the JS integration.

0 commit comments

Comments
 (0)