mirror of
https://libwebsockets.org/repo/libwebsockets
synced 2024-12-04 13:57:15 +00:00
1d3ec6a3a1
Introduce a rewritten picojpeg that is able to operate statefully and rasterize into an internal line ringbuffer, emitting a line of pixels at a time to the caller. This is the JPEG equivalent of the lws PNG decoder. JPEG is based around 8- or 16- line height MCU blocks, depending on the chroma coding, mandating a corresponding internal line buffer requirement. Example total heap requirement for various kinds of 600px width jpeg decoding: Grayscale: 6.5KB RGB 4:4:4: 16.4KB RGB 4:2:2v: 16.4KB RGB 4:4:2h: 31KB RGB 4:4:0: 31KB No other allocations occur during decode. Stateful stream parsing means decode can be paused for lack of input at any time and resumed seamlessly when more input becomes available.
78 lines
2.9 KiB
Markdown
78 lines
2.9 KiB
Markdown
# lws_jpeg stateful JPEG decoder
|
|
|
|
Lws includes a rewrite of picojpeg that performs stateful, line-at-a-time decoding.
|
|
|
|
The heap memory requirement is 2.1KB plus an internally-allocated either 8 or 16-line
|
|
pixel buffer, the width of the image, and with either Y (for grayscale jpeg) or RGB
|
|
bytes per pixel. Eg for a 600px wide image
|
|
|
|
|Type|Heap requirement|
|
|
|---|---|
|
|
|Grayscale|6.5KB|
|
|
|RGB 4:4:4|16.4KB|
|
|
|RGB 4:2:2v|16.4KB|
|
|
|RGB 4:4:2h|31KB|
|
|
|RGB 4:4:0|31KB|
|
|
|
|
No other allocations occur during decode.
|
|
|
|
|
|
In particular the input JPEG data is stream parsed into the JPEG MCU buffer, so there
|
|
is no requirement for it all to be in memory at the same time, and there is no
|
|
framebuffer required, only a line of pixels is processed in isolation at a time.
|
|
|
|
The results in an extremely tight decoder suitable for microcontroller type
|
|
platforms that lack enough memory to hold a framebuffer, but can stream the
|
|
rendered data out over SPI or i2c to a display device that does have its own
|
|
(usually write-only) framebuffer memory.
|
|
|
|
## Creating and destroying the decoding context
|
|
|
|
The apis to create and destroy a decoding context are very simple...
|
|
|
|
```
|
|
LWS_VISIBLE LWS_EXTERN lws_jpeg_t *
|
|
lws_jpeg_new(void);
|
|
|
|
LWS_VISIBLE LWS_EXTERN void
|
|
lws_jpeg_free(lws_jpeg_t **jpeg);
|
|
```
|
|
|
|
## Performing the decoding
|
|
|
|
The only decoding API provides input PNG data which may or may not be partly or
|
|
wholly consumed, to produce a line of output pixels that can be found at `*ppix`.
|
|
|
|
```
|
|
LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
|
|
lws_jpeg_emit_next_line(lws_jpeg_t *jpeg, const uint8_t **ppix,
|
|
const uint8_t **buf, size_t *size);
|
|
```
|
|
If input data is consumed, `*buf` and `*size` are adjusted accordingly.
|
|
This api returns a bitfield consisting of:
|
|
|
|
|Return value bit|Meaning|
|
|
|---|---|
|
|
|`LWS_SRET_OK` (0, no bits set)|Completed|
|
|
|`LWS_SRET_WANT_INPUT`|Decoder needs to be called again with more PNG input before it can produce a line of pixels|
|
|
|`LWS_SRET_WANT_OUTPUT`|Decoder has paused to emit a line of pixels, and can resume|
|
|
|`LWS_SRET_FATAL`|Decoder has encountered a fatal error, any return greater than `LWS_SRET_FATAL` indicates the type of error|
|
|
|`LWS_SRET_NO_FURTHER_IN`|Indicate no further new input will be used|
|
|
|`LWS_SRET_NO_FURTHER_OUT`|Indicate no further output is forthcoming|
|
|
|
|
To get early information about the dimensions and colourspace of the JPEG, you
|
|
can call this api initially with restricted chunk size (eg, 128 bytes) until
|
|
`lws_jpeg_get_components()` returns nonzero. You can continue where you left off
|
|
later when you want to receive the result pixels.
|
|
|
|
## Output format
|
|
|
|
To minimize the internal buffer, the provided line of pixels is either just a Y
|
|
grayscale byte per pixel if a grayscale JPEG, or 3 RGB bytes per pixel. You can
|
|
query which by using `lws_jpeg_get_components()` to find out how many bytes per
|
|
pixel.
|
|
|
|
Although 4:4:4, 4:2:2 of both orientations, and 4:2:0 are handled differently
|
|
internally, they all present 3-byte RGB output of the full width at `*ppix`.
|
|
|