Skip to main content

arithmetic_coding/
encoder.rs

1//! The [`Encoder`] half of the arithmetic coding library.
2
3use std::{io, ops::Range};
4
5use bitstream_io::BitWrite;
6
7use crate::{
8    BitStore, Error, Model,
9    common::{self, assert_precision_sufficient},
10};
11
12// this algorithm is derived from this article - https://marknelson.us/posts/2014/10/19/data-compression-with-arithmetic-coding.html
13
14/// An arithmetic encoder
15///
16/// An arithmetic decoder converts a stream of symbols into a stream of bits,
17/// using a predictive [`Model`].
18#[derive(Debug)]
19pub struct Encoder<M, W>
20where
21    M: Model,
22    W: BitWrite,
23{
24    model: M,
25    state: State<M::B, W>,
26}
27
28impl<M, W> Encoder<M, W>
29where
30    M: Model,
31    W: BitWrite,
32{
33    /// Construct a new [`Encoder`].
34    ///
35    /// The 'precision' of the encoder is maximised, based on the number of bits
36    /// needed to represent the [`Model::denominator`]. 'precision' bits is
37    /// equal to [`BitStore::BITS`] - [`Model::denominator`] bits. If you need
38    /// to set the precision manually, use [`Encoder::with_precision`].
39    ///
40    /// # Panics
41    ///
42    /// The calculation of the number of bits used for 'precision' is subject to
43    /// the following constraints:
44    ///
45    /// - The total available bits is [`BitStore::BITS`]
46    /// - The precision must use at least 2 more bits than that needed to
47    ///   represent [`Model::denominator`]
48    ///
49    /// If these constraints cannot be satisfied this method will panic in debug
50    /// builds
51    pub fn new(model: M, bitwriter: W) -> Self {
52        let frequency_bits = model.max_denominator().log2() + 1;
53        let precision = M::B::BITS - frequency_bits;
54        Self::with_precision(model, bitwriter, precision)
55    }
56
57    /// Construct a new [`Encoder`] with a custom precision.
58    ///
59    /// # Panics
60    ///
61    /// The calculation of the number of bits used for 'precision' is subject to
62    /// the following constraints:
63    ///
64    /// - The total available bits is [`BitStore::BITS`]
65    /// - The precision must use at least 2 more bits than that needed to
66    ///   represent [`Model::denominator`]
67    ///
68    /// If these constraints cannot be satisfied this method will panic in debug
69    /// builds
70    pub fn with_precision(model: M, bitwriter: W, precision: u32) -> Self {
71        let state = State::new(precision, bitwriter);
72        Self::with_state(state, model)
73    }
74
75    /// Create an encoder from an existing [`State`].
76    ///
77    /// This is useful for manually chaining a shared buffer through multiple
78    /// encoders.
79    pub fn with_state(state: State<M::B, W>, model: M) -> Self {
80        #[cfg(debug_assertions)]
81        assert_precision_sufficient::<M>(model.max_denominator(), state.state.precision);
82        Self { model, state }
83    }
84
85    /// Encode a stream of symbols into the provided output.
86    ///
87    /// This method will encode all the symbols in the iterator, followed by EOF
88    /// (`None`), and then call [`Encoder::flush`].
89    ///
90    /// # Errors
91    ///
92    /// This method can fail if the underlying [`BitWrite`] cannot be written
93    /// to.
94    pub fn encode_all(
95        mut self,
96        symbols: impl IntoIterator<Item = M::Symbol>,
97    ) -> Result<(), Error<M::ValueError>> {
98        for symbol in symbols {
99            self.encode(Some(&symbol))?;
100        }
101        self.encode(None)?;
102        self.flush()?;
103        Ok(())
104    }
105
106    /// Encode a symbol into the provided output.
107    ///
108    /// When you finish encoding symbols, you must manually encode an EOF symbol
109    /// by calling [`Encoder::encode`] with `None`.
110    ///
111    /// The internal buffer must be manually flushed using [`Encoder::flush`].
112    ///
113    /// # Errors
114    ///
115    /// This method can fail if the underlying [`BitWrite`] cannot be written
116    /// to.
117    pub fn encode(&mut self, symbol: Option<&M::Symbol>) -> Result<(), Error<M::ValueError>> {
118        let p = self.model.probability(symbol).map_err(Error::ValueError)?;
119        let denominator = self.model.denominator();
120        debug_assert!(
121            denominator <= self.model.max_denominator(),
122            "denominator is greater than maximum!"
123        );
124
125        self.state.scale(p, denominator)?;
126        self.model.update(symbol);
127
128        Ok(())
129    }
130
131    /// Flush any pending bits from the buffer
132    ///
133    /// This method must be called when you finish writing symbols to a stream
134    /// of bits. This is called automatically when you use
135    /// [`Encoder::encode_all`].
136    ///
137    /// # Errors
138    ///
139    /// This method can fail if the underlying [`BitWrite`] cannot be written
140    /// to.
141    pub fn flush(self) -> io::Result<()> {
142        self.state.flush()
143    }
144
145    /// Return the internal model and state of the encoder.
146    pub fn into_inner(self) -> (M, State<M::B, W>) {
147        (self.model, self.state)
148    }
149
150    /// Reuse the internal state of the Encoder with a new model.
151    ///
152    /// Allows for chaining multiple sequences of symbols into a single stream
153    /// of bits
154    pub fn chain<X>(self, model: X) -> Encoder<X, W>
155    where
156        X: Model<B = M::B>,
157    {
158        Encoder::with_state(self.state, model)
159    }
160}
161
162/// A convenience struct which stores the internal state of an [`Encoder`].
163#[derive(Debug)]
164pub struct State<B, W>
165where
166    B: BitStore,
167    W: BitWrite,
168{
169    #[allow(clippy::struct_field_names)]
170    state: common::State<B>,
171    pending: u32,
172    output: W,
173}
174
175impl<B, W> State<B, W>
176where
177    B: BitStore,
178    W: BitWrite,
179{
180    /// Manually construct a [`State`].
181    ///
182    /// Normally this would be done automatically using the [`Encoder::new`]
183    /// method.
184    pub fn new(precision: u32, output: W) -> Self {
185        let state = common::State::new(precision);
186        let pending = 0;
187
188        Self {
189            state,
190            pending,
191            output,
192        }
193    }
194
195    fn scale(&mut self, p: Range<B>, denominator: B) -> io::Result<()> {
196        self.state.scale(p, denominator);
197        self.normalise()
198    }
199
200    fn normalise(&mut self) -> io::Result<()> {
201        while self.state.high < self.state.half() || self.state.low >= self.state.half() {
202            if self.state.high < self.state.half() {
203                self.emit(false)?;
204                self.state.high = (self.state.high << 1) + B::ONE;
205                self.state.low <<= 1;
206            } else {
207                self.emit(true)?;
208                self.state.low = (self.state.low - self.state.half()) << 1;
209                self.state.high = ((self.state.high - self.state.half()) << 1) + B::ONE;
210            }
211        }
212
213        while self.state.low >= self.state.quarter()
214            && self.state.high < (self.state.three_quarter())
215        {
216            self.pending += 1;
217            self.state.low = (self.state.low - self.state.quarter()) << 1;
218            self.state.high = ((self.state.high - self.state.quarter()) << 1) + B::ONE;
219        }
220
221        Ok(())
222    }
223
224    fn emit(&mut self, bit: bool) -> io::Result<()> {
225        self.output.write_bit(bit)?;
226        for _ in 0..self.pending {
227            self.output.write_bit(!bit)?;
228        }
229        self.pending = 0;
230        Ok(())
231    }
232
233    /// Flush the internal buffer and write all remaining bits to the output.
234    /// This method MUST be called when you finish writing symbols to ensure
235    /// they are fully written to the output.
236    ///
237    /// # Errors
238    ///
239    /// This method can fail if the output cannot be written to
240    pub fn flush(mut self) -> io::Result<()> {
241        self.pending += 1;
242        if self.state.low <= self.state.quarter() {
243            self.emit(false)?;
244        } else {
245            self.emit(true)?;
246        }
247
248        Ok(())
249    }
250}