|
37 | 37 | //! let mut pixels = decoder.decode().unwrap(); |
38 | 38 | //! ``` |
39 | 39 | //! |
| 40 | +//! ## Incremental input |
| 41 | +//! |
| 42 | +//! `JpegDecoder` can be retried on the same decoder when the underlying reader can |
| 43 | +//! see more bytes later. Callers should treat `DecodeErrors::is_recoverable_eof()` |
| 44 | +//! as the signal to feed more input and retry; any other error is a hard decode |
| 45 | +//! failure. |
| 46 | +//! |
| 47 | +//! After `decode_headers()` succeeds, `info()` and `output_buffer_size()` are |
| 48 | +//! available. During `decode_into()`, the same decoder and output buffer must be |
| 49 | +//! kept across retries. If scan decoding returns recoverable EOF, |
| 50 | +//! `decoded_output_bytes()` and `decoded_scanlines()` report the stable prefix of |
| 51 | +//! the output buffer that can be displayed or copied before retrying. |
| 52 | +//! |
| 53 | +//! By default, row checkpoints are recorded only after a previous scan decode |
| 54 | +//! attempt, so one-shot decoding keeps the lowest-overhead path. Call |
| 55 | +//! `set_incremental_mode(true)` before the first `decode_into()` attempt when the |
| 56 | +//! caller expects input to arrive incrementally; this records checkpoints during |
| 57 | +//! the first baseline Huffman scan attempt and can reduce replay work on the next |
| 58 | +//! retry. |
| 59 | +//! |
| 60 | +//! ```no_run |
| 61 | +//! use zune_core::bytestream::ZCursor; |
| 62 | +//! use zune_jpeg::errors::DecodeErrors; |
| 63 | +//! use zune_jpeg::JpegDecoder; |
| 64 | +//! |
| 65 | +//! fn decode_incremental(jpeg_bytes: &[u8]) -> Result<Vec<u8>, DecodeErrors> { |
| 66 | +//! let mut decoder = JpegDecoder::new(ZCursor::new(jpeg_bytes)); |
| 67 | +//! |
| 68 | +//! loop { |
| 69 | +//! match decoder.decode_headers() { |
| 70 | +//! Ok(()) => break, |
| 71 | +//! Err(error) if error.is_recoverable_eof() => { |
| 72 | +//! // Make more input bytes visible to the same reader, then retry. |
| 73 | +//! } |
| 74 | +//! Err(error) => return Err(error) |
| 75 | +//! } |
| 76 | +//! } |
| 77 | +//! |
| 78 | +//! let mut pixels = vec![0; decoder.output_buffer_size().unwrap()]; |
| 79 | +//! decoder.set_incremental_mode(true); |
| 80 | +//! |
| 81 | +//! loop { |
| 82 | +//! match decoder.decode_into(&mut pixels) { |
| 83 | +//! Ok(()) => break, |
| 84 | +//! Err(error) if error.is_recoverable_eof() => { |
| 85 | +//! let stable_bytes = decoder.decoded_output_bytes().unwrap_or(0); |
| 86 | +//! let stable_scanlines = decoder.decoded_scanlines().unwrap_or(0); |
| 87 | +//! // Display or copy the stable prefix, feed more input, then retry |
| 88 | +//! // with the same decoder and `pixels` buffer. |
| 89 | +//! } |
| 90 | +//! Err(error) => return Err(error) |
| 91 | +//! } |
| 92 | +//! } |
| 93 | +//! |
| 94 | +//! Ok(pixels) |
| 95 | +//! } |
| 96 | +//! ``` |
| 97 | +//! |
40 | 98 | //! ## Migrating from version 0.4-- |
41 | 99 | //! |
42 | 100 | //! ### Motivation |
|
0 commit comments