8 个版本
0.2.4 | 2022年6月21日 |
---|---|
0.2.3 | 2021年1月2日 |
0.2.2 | 2020年12月8日 |
0.1.2 | 2019年4月15日 |
#173 在 压缩 类别中
每月下载量 723 次
740KB
756 行
Aricode
适用于 Rust 的算术编码器。
关于
这个包提供了一个高效的算术编码/解码器实现。这个包基于描述算术编码的论文,可在此处找到。这个实现具有许多可读性和性能改进,尤其是在解码方面。
这个项目的目标不是提供一个即用型的压缩解决方案。算术编码(熵编码)是几乎所有现代压缩方案的核心。这个包旨在被包含在未来的项目中,这些项目依赖于高效的熵编码器,例如 PPM,LZ77/LZ78,h265/HEVC。
核心组件
有许多结构可供使用,但对于普通用户来说,只有少数会被使用。
示例
在 git 仓库中有一个 old_complex.rs 文件,该文件根据每个字符进行上下文切换。更简单的示例可以在 new_simple.rs 中找到。
输入和输出位流
为了使算术编码工作,需要逐位读取流(用于解码和编码器的输出)。因此,需要BitBit。将输入包裹在缓冲区读取器/写入器中可以大大提高性能。
使用bitbit创建输入流。
use arcode::bitbit::{BitReader, MSB, BitWriter};
use std::io::Cursor;
fn read_example() {
// normally you would have a Read type with a BufReader
let mut source = Cursor::new(vec![0u8; 4]);
let input: BitReader<_, MSB> = BitReader::new(&mut source);
}
fn out_example() {
// once again would be Write type with a BufWriter
let compressed = Cursor::new(vec![]);
let mut compressed_writer = BitWriter::new(compressed);
}
源模型
根据您的应用,您可能有一个或多个源模型。编码器和解码器都依赖于源模型。如果解码器与编码器不同步,您将无法正确解码。
model::Builder
为了创建源模型,您需要使用model::Builder结构体。
use arcode::{EOFKind, Model};
fn source_model_example() {
// create a new model that has symbols 0-256
// 8 bit values + one EOF marker
let mut model_with_eof = Model::builder()
.num_symbols(256)
.eof(EOFKind::EndAddOne)
.build();
// model for 8 bit 0 - 255, if we arent using
// the EOF flag we can set it to NONE or let it default
// to none as in the second example below.
let model_without_eof = Model::builder()
.num_symbols(256)
.eof(EOFKind::None)
.build();
let model_without_eof = Model::builder().num_symbols(256).build();
// we can also create a model for 0-255 using num_bits
let model_8_bit = Model::builder().num_bits(8).build();
// update the probability of symbol 4.
model_with_eof.update_symbol(4);
}
编码
编码一些简单的输入
use arcode::bitbit::BitWriter;
use arcode::{ArithmeticEncoder, EOFKind, Model};
use std::io::{Cursor, Result};
/// Encodes bytes and returns the compressed form
fn encode(data: &[u8]) -> Result<Vec<u8>> {
let mut model = Model::builder()
.num_bits(8)
.eof(EOFKind::EndAddOne)
.build();
// make a stream to collect the compressed data
let compressed = Cursor::new(vec![]);
let mut compressed_writer = BitWriter::new(compressed);
let mut encoder = ArithmeticEncoder::new(48);
for &sym in data {
encoder.encode(sym as u32, &model, &mut compressed_writer)?;
model.update_symbol(sym as u32);
}
encoder.encode(model.eof(), &model, &mut compressed_writer)?;
encoder.finish_encode(&mut compressed_writer)?;
compressed_writer.pad_to_byte()?;
// retrieves the bytes from the writer. This will
// be cleaner when bitbit updates. Not necessary if
// using files or a stream
Ok(compressed_writer.get_ref().get_ref().clone())
}
解码
use arcode::bitbit::{BitReader, MSB};
use arcode::{ArithmeticDecoder, EOFKind, Model};
use std::io::{Cursor, Result};
/// Decompresses the data
fn decode(data: &[u8]) -> Result<Vec<u8>> {
let mut model = Model::builder()
.num_bits(8)
.eof(EOFKind::EndAddOne)
.build();
let mut input_reader = BitReader::<_, MSB>::new(data);
let mut decoder = ArithmeticDecoder::new(48);
let mut decompressed_data = vec![];
while !decoder.finished() {
let sym = decoder.decode(&model, &mut input_reader)?;
model.update_symbol(sym);
decompressed_data.push(sym as u8);
}
decompressed_data.pop(); // remove the EOF
Ok(decompressed_data)
}