Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::slice::ChunksExact;

use quick_error::quick_error;

use crate::vp8_encoder::encode_frame_lossy;

/// Color type of the image.
///
/// Note that the WebP format doesn't have a concept of color type. All images are encoded as RGBA
Expand Down Expand Up @@ -355,22 +357,28 @@ fn write_run<W: Write>(
pub struct EncoderParams {
/// Use a predictor transform. Enabled by default.
pub use_predictor_transform: bool,
/// Use the lossy encoding to encode the image using the VP8 compression format.
pub use_lossy: bool,
/// A quality value for the lossy encoding that must be between 0 and 100. Defaults to 95.
pub lossy_quality: u8,
}

impl Default for EncoderParams {
fn default() -> Self {
Self {
use_predictor_transform: true,
use_lossy: false,
lossy_quality: 95,
}
}
}

/// Encode image data with the indicated color type.
/// Encode image data losslessly with the indicated color type.
///
/// # Panics
///
/// Panics if the image data is not of the indicated dimensions.
fn encode_frame<W: Write>(
fn encode_frame_lossless<W: Write>(
writer: W,
data: &[u8],
width: u32,
Expand Down Expand Up @@ -672,7 +680,21 @@ impl<W: Write> WebPEncoder<W> {
color: ColorType,
) -> Result<(), EncodingError> {
let mut frame = Vec::new();
encode_frame(&mut frame, data, width, height, color, self.params)?;

let frame_chunk = if self.params.use_lossy {
encode_frame_lossy(
&mut frame,
data,
width,
height,
color,
self.params.lossy_quality,
)?;
b"VP8 "
} else {
encode_frame_lossless(&mut frame, data, width, height, color, self.params)?;
b"VP8L"
};

// If the image has no metadata, it can be encoded with the "simple" WebP container format.
if self.icc_profile.is_empty()
Expand All @@ -683,7 +705,7 @@ impl<W: Write> WebPEncoder<W> {
self.writer
.write_all(&(chunk_size(frame.len()) + 4).to_le_bytes())?;
self.writer.write_all(b"WEBP")?;
write_chunk(&mut self.writer, b"VP8L", &frame)?;
write_chunk(&mut self.writer, frame_chunk, &frame)?;
} else {
let mut total_bytes = 22 + chunk_size(frame.len());
if !self.icc_profile.is_empty() {
Expand Down Expand Up @@ -725,7 +747,7 @@ impl<W: Write> WebPEncoder<W> {
write_chunk(&mut self.writer, b"ICCP", &self.icc_profile)?;
}

write_chunk(&mut self.writer, b"VP8L", &frame)?;
write_chunk(&mut self.writer, frame_chunk, &frame)?;

if !self.exif_metadata.is_empty() {
write_chunk(&mut self.writer, b"EXIF", &self.exif_metadata)?;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod transform;
mod vp8_arithmetic_decoder;
mod vp8_arithmetic_encoder;
mod vp8_common;
mod vp8_encoder;
mod vp8_prediction;
mod yuv;

Expand Down
2 changes: 0 additions & 2 deletions src/transform.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(dead_code)]

/// 16 bit fixed point version of cos(PI/8) * sqrt(2) - 1
const CONST1: i64 = 20091;
/// 16 bit fixed point version of sin(PI/8) * sqrt(2)
Expand Down
8 changes: 4 additions & 4 deletions src/vp8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ pub struct Frame {
/// Indicates whether this frame is a keyframe
pub keyframe: bool,

version: u8,
pub(crate) version: u8,

/// Indicates whether this frame is intended for display
pub for_display: bool,
Expand All @@ -157,9 +157,9 @@ pub struct Frame {
pub pixel_type: u8,

// Section 9.4 and 15
filter_type: bool, //if true uses simple filter // if false uses normal filter
filter_level: u8,
sharpness_level: u8,
pub(crate) filter_type: bool, //if true uses simple filter // if false uses normal filter
pub(crate) filter_level: u8,
pub(crate) sharpness_level: u8,
}

impl Frame {
Expand Down
2 changes: 0 additions & 2 deletions src/vp8_arithmetic_encoder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(dead_code)]

// currently just a direct translation of the encoder given in the vp8 specification
#[derive(Default)]
pub(crate) struct ArithmeticEncoder {
Expand Down
2 changes: 1 addition & 1 deletion src/vp8_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ pub(crate) const KEYFRAME_UV_MODE_TREE: [i8; 6] = [-DC_PRED, 2, -V_PRED, 4, -H_P
pub(crate) const KEYFRAME_UV_MODE_PROBS: [Prob; 3] = [142, 114, 183];

// Section 13.4
type TokenProbTables = [[[[Prob; NUM_DCT_TOKENS - 1]; 3]; 8]; 4];
pub(crate) type TokenProbTables = [[[[Prob; NUM_DCT_TOKENS - 1]; 3]; 8]; 4];

// Probabilities that a token's probability will be updated
pub(crate) const COEFF_UPDATE_PROBS: TokenProbTables = [
Expand Down
Loading
Loading