Fix resize on PNG to size compression

This commit is contained in:
Matteo Paonessa 2025-02-21 13:35:34 +01:00
parent d49ebd9a79
commit ea8b3f95a9
23 changed files with 407 additions and 385 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "libcaesium" name = "libcaesium"
version = "0.17.2" version = "0.17.3"
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"] authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
edition = "2021" edition = "2021"
categories = ["multimedia::images"] categories = ["multimedia::images"]
@ -43,9 +43,12 @@ img-parts = "0.3.3"
bytes = "1.7" bytes = "1.7"
lodepng = { version = "3.10", optional = true } lodepng = { version = "3.10", optional = true }
imagequant = { version = "4.3", optional = true, default-features = false } imagequant = { version = "4.3", optional = true, default-features = false }
tiff = { version = "0.9" } tiff = "0.9"
kamadak-exif = "0.6" kamadak-exif = "0.6"
[target.wasm32-unknown-emscripten.dependencies]
libwebp-sys = "=0.9.5"
[dev-dependencies] [dev-dependencies]
dssim = { version = "3.3", default-features = false, features = ["no-macos-vimage"] } dssim = { version = "3.3", default-features = false, features = ["no-macos-vimage"] }

View File

@ -1,5 +1,5 @@
use caesium::parameters::CSParameters;
use caesium::compress; use caesium::compress;
use caesium::parameters::CSParameters;
use std::env; use std::env;
use std::process::ExitCode; use std::process::ExitCode;

View File

@ -1,5 +1,5 @@
use caesium::parameters::CSParameters;
use caesium::convert; use caesium::convert;
use caesium::parameters::CSParameters;
use std::env; use std::env;
use std::process::ExitCode; use std::process::ExitCode;
@ -13,7 +13,12 @@ fn main() -> ExitCode {
parameters.keep_metadata = true; parameters.keep_metadata = true;
parameters.webp.quality = 60; parameters.webp.quality = 60;
match convert(input, output, &parameters, caesium::SupportedFileTypes::WebP) { match convert(
input,
output,
&parameters,
caesium::SupportedFileTypes::WebP,
) {
Ok(_) => ExitCode::SUCCESS, Ok(_) => ExitCode::SUCCESS,
Err(e) => { Err(e) => {
eprintln!("{}", e); eprintln!("{}", e);

View File

@ -1,5 +1,5 @@
use caesium::parameters::CSParameters;
use caesium::compress; use caesium::compress;
use caesium::parameters::CSParameters;
use std::env; use std::env;
use std::process::ExitCode; use std::process::ExitCode;

View File

@ -4,11 +4,15 @@ use bytes::Bytes;
use image::{ColorType, DynamicImage, ImageFormat, ImageReader}; use image::{ColorType, DynamicImage, ImageFormat, ImageReader};
use img_parts::{DynImage, ImageEXIF, ImageICC}; use img_parts::{DynImage, ImageEXIF, ImageICC};
use crate::{compress_in_memory, CSParameters, SupportedFileTypes};
use crate::error::CaesiumError; use crate::error::CaesiumError;
use crate::utils::{get_filetype_from_memory, get_jpeg_orientation}; use crate::utils::{get_filetype_from_memory, get_jpeg_orientation};
use crate::{compress_in_memory, CSParameters, SupportedFileTypes};
pub fn convert_in_memory(in_file: Vec<u8>, format: SupportedFileTypes, parameters: &CSParameters) -> Result<Vec<u8>, CaesiumError> { pub fn convert_in_memory(
in_file: Vec<u8>,
format: SupportedFileTypes,
parameters: &CSParameters,
) -> Result<Vec<u8>, CaesiumError> {
let mut iccp = None; let mut iccp = None;
let mut exif = None; let mut exif = None;
@ -23,11 +27,13 @@ pub fn convert_in_memory(in_file: Vec<u8>, format: SupportedFileTypes, parameter
} }
let i = in_file.as_slice(); let i = in_file.as_slice();
let mut original_image = ImageReader::new(Cursor::new(i)).with_guessed_format() let mut original_image = ImageReader::new(Cursor::new(i))
.with_guessed_format()
.map_err(|e| CaesiumError { .map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 10402, code: 10402,
})?.decode() })?
.decode()
.map_err(|e| CaesiumError { .map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 10403, code: 10403,
@ -44,7 +50,7 @@ pub fn convert_in_memory(in_file: Vec<u8>, format: SupportedFileTypes, parameter
6 => original_image.rotate90(), 6 => original_image.rotate90(),
7 => original_image.fliph().rotate90(), 7 => original_image.fliph().rotate90(),
8 => original_image.rotate270(), 8 => original_image.rotate270(),
_ => original_image _ => original_image,
} }
} }
@ -66,14 +72,15 @@ pub fn convert_in_memory(in_file: Vec<u8>, format: SupportedFileTypes, parameter
} }
let mut output_image: Vec<u8> = Vec::new(); let mut output_image: Vec<u8> = Vec::new();
original_image.write_to(&mut Cursor::new(&mut output_image), output_format) original_image
.write_to(&mut Cursor::new(&mut output_image), output_format)
.map_err(|e| CaesiumError { .map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 10404, code: 10404,
})?; })?;
let compressed_converted_image = compress_in_memory(output_image, parameters) let compressed_converted_image =
.map_err(|e| CaesiumError { compress_in_memory(output_image, parameters).map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 10405, code: 10405,
})?; })?;
@ -103,9 +110,7 @@ pub fn convert_in_memory(in_file: Vec<u8>, format: SupportedFileTypes, parameter
Ok(output_image_with_metadata) Ok(output_image_with_metadata)
} }
None => { None => Ok(compressed_converted_image),
Ok(compressed_converted_image)
}
} }
} else { } else {
Ok(compressed_converted_image) Ok(compressed_converted_image)
@ -119,10 +124,12 @@ fn map_image_format(format: SupportedFileTypes) -> Result<ImageFormat, CaesiumEr
SupportedFileTypes::Gif => ImageFormat::Gif, SupportedFileTypes::Gif => ImageFormat::Gif,
SupportedFileTypes::WebP => ImageFormat::WebP, SupportedFileTypes::WebP => ImageFormat::WebP,
SupportedFileTypes::Tiff => ImageFormat::Tiff, SupportedFileTypes::Tiff => ImageFormat::Tiff,
_ => return Err(CaesiumError { _ => {
return Err(CaesiumError {
message: "Output format is unknown".into(), message: "Output format is unknown".into(),
code: 10400, code: 10400,
}) })
}
}; };
Ok(image_format) Ok(image_format)

View File

@ -1,8 +1,8 @@
use std::ffi::CString; use std::ffi::CString;
use std::os::raw::{c_int, c_void}; use std::os::raw::{c_int, c_void};
use crate::CSParameters;
use crate::error::CaesiumError; use crate::error::CaesiumError;
use crate::CSParameters;
pub fn compress( pub fn compress(
input_path: String, input_path: String,

View File

@ -1,9 +1,11 @@
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::os::raw::c_char; use std::os::raw::c_char;
use crate::{compress, compress_to_size, convert, CSParameters, error, SupportedFileTypes, TiffDeflateLevel};
use crate::parameters::ChromaSubsampling; use crate::parameters::ChromaSubsampling;
use crate::parameters::TiffCompression::{Deflate, Lzw, Packbits, Uncompressed}; use crate::parameters::TiffCompression::{Deflate, Lzw, Packbits, Uncompressed};
use crate::{
compress, compress_to_size, convert, error, CSParameters, SupportedFileTypes, TiffDeflateLevel,
};
#[repr(C)] #[repr(C)]
pub struct CCSParameters { pub struct CCSParameters {
@ -80,7 +82,7 @@ pub unsafe extern "C" fn c_convert(
CStr::from_ptr(input_path).to_str().unwrap().to_string(), CStr::from_ptr(input_path).to_str().unwrap().to_string(),
CStr::from_ptr(output_path).to_str().unwrap().to_string(), CStr::from_ptr(output_path).to_str().unwrap().to_string(),
&parameters, &parameters,
format format,
)) ))
} }
@ -137,13 +139,13 @@ fn c_set_parameters(params: CCSParameters) -> CSParameters {
1 => Lzw, 1 => Lzw,
2 => Deflate, 2 => Deflate,
3 => Packbits, 3 => Packbits,
_ => Uncompressed _ => Uncompressed,
}; };
parameters.tiff.deflate_level = match params.tiff_deflate_level { parameters.tiff.deflate_level = match params.tiff_deflate_level {
1 => TiffDeflateLevel::Fast, 1 => TiffDeflateLevel::Fast,
6 => TiffDeflateLevel::Balanced, 6 => TiffDeflateLevel::Balanced,
_ => TiffDeflateLevel::Best _ => TiffDeflateLevel::Best,
}; };
parameters parameters

View File

@ -1,20 +1,20 @@
use std::{fs, ptr}; use image::ImageFormat::Jpeg;
use img_parts::jpeg::Jpeg as PartsJpeg;
use img_parts::{ImageEXIF, ImageICC};
use libc::free;
use mozjpeg_sys::*;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use std::mem; use std::mem;
use std::panic::catch_unwind; use std::panic::catch_unwind;
use std::ptr::null; use std::ptr::null;
use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::atomic::{AtomicI32, Ordering};
use image::ImageFormat::Jpeg; use std::{fs, ptr};
use img_parts::{ImageEXIF, ImageICC};
use img_parts::jpeg::Jpeg as PartsJpeg;
use libc::free;
use mozjpeg_sys::*;
use crate::{CSParameters};
use crate::error::CaesiumError; use crate::error::CaesiumError;
use crate::parameters::ChromaSubsampling; use crate::parameters::ChromaSubsampling;
use crate::resize::resize; use crate::resize::resize;
use crate::CSParameters;
static JPEG_ERROR: AtomicI32 = AtomicI32::new(0); static JPEG_ERROR: AtomicI32 = AtomicI32::new(0);

View File

@ -4,17 +4,19 @@ use std::fs;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use error::CaesiumError;
use crate::parameters::{CSParameters, TiffDeflateLevel};
use crate::parameters::TiffCompression::{Deflate, Lzw, Packbits}; use crate::parameters::TiffCompression::{Deflate, Lzw, Packbits};
use crate::parameters::{CSParameters, TiffDeflateLevel};
use crate::utils::{get_filetype_from_memory, get_filetype_from_path}; use crate::utils::{get_filetype_from_memory, get_filetype_from_path};
use error::CaesiumError;
mod convert;
pub mod error; pub mod error;
#[cfg(feature = "gif")] #[cfg(feature = "gif")]
mod gif; mod gif;
mod interface; mod interface;
#[cfg(feature = "jpg")] #[cfg(feature = "jpg")]
mod jpeg; mod jpeg;
pub mod parameters;
#[cfg(feature = "png")] #[cfg(feature = "png")]
mod png; mod png;
mod resize; mod resize;
@ -23,8 +25,6 @@ mod tiff;
mod utils; mod utils;
#[cfg(feature = "webp")] #[cfg(feature = "webp")]
mod webp; mod webp;
mod convert;
pub mod parameters;
/// Compresses an image file from the input path and writes the compressed image to the output path. /// Compresses an image file from the input path and writes the compressed image to the output path.
/// ///
@ -87,10 +87,7 @@ pub fn compress(
/// # Returns /// # Returns
/// ///
/// * `Result<Vec<u8>, CaesiumError>` - Returns a vector of bytes representing the compressed image if successful, otherwise returns a `CaesiumError`. /// * `Result<Vec<u8>, CaesiumError>` - Returns a vector of bytes representing the compressed image if successful, otherwise returns a `CaesiumError`.
pub fn compress_in_memory( pub fn compress_in_memory(in_file: Vec<u8>, parameters: &CSParameters) -> error::Result<Vec<u8>> {
in_file: Vec<u8>,
parameters: &CSParameters,
) -> error::Result<Vec<u8>> {
let file_type = get_filetype_from_memory(in_file.as_slice()); let file_type = get_filetype_from_memory(in_file.as_slice());
let compressed_file = match file_type { let compressed_file = match file_type {
#[cfg(feature = "jpg")] #[cfg(feature = "jpg")]
@ -124,7 +121,6 @@ pub fn compress_in_memory(
/// # Returns /// # Returns
/// ///
/// * `Result<Vec<u8>, CaesiumError>` - Returns a vector of bytes representing the compressed image if successful, otherwise returns a `CaesiumError`. /// * `Result<Vec<u8>, CaesiumError>` - Returns a vector of bytes representing the compressed image if successful, otherwise returns a `CaesiumError`.
pub fn compress_to_size_in_memory( pub fn compress_to_size_in_memory(
in_file: Vec<u8>, in_file: Vec<u8>,
parameters: &mut CSParameters, parameters: &mut CSParameters,
@ -136,7 +132,7 @@ pub fn compress_to_size_in_memory(
let tolerance_percentage = 2; let tolerance_percentage = 2;
let tolerance = max_output_size * tolerance_percentage / 100; let tolerance = max_output_size * tolerance_percentage / 100;
let mut quality = 80; let mut quality = 80;
let mut last_less = 1; let mut last_less = 0;
let mut last_high = 101; let mut last_high = 101;
let max_tries: u32 = 10; let max_tries: u32 = 10;
let mut tries: u32 = 0; let mut tries: u32 = 0;
@ -144,10 +140,7 @@ pub fn compress_to_size_in_memory(
let compressed_file = match file_type { let compressed_file = match file_type {
#[cfg(feature = "tiff")] #[cfg(feature = "tiff")]
SupportedFileTypes::Tiff => { SupportedFileTypes::Tiff => {
let algorithms = [ let algorithms = [Lzw, Packbits];
Lzw,
Packbits
];
parameters.tiff.deflate_level = TiffDeflateLevel::Best; parameters.tiff.deflate_level = TiffDeflateLevel::Best;
parameters.tiff.algorithm = Deflate; parameters.tiff.algorithm = Deflate;
let mut smallest_result = tiff::compress_in_memory(in_file.clone(), parameters)?; //TODO clone let mut smallest_result = tiff::compress_in_memory(in_file.clone(), parameters)?; //TODO clone
@ -261,13 +254,16 @@ pub fn compress_to_size(
code: 10201, code: 10201,
})?; })?;
let original_size = in_file.len(); let original_size = in_file.len();
if original_size <= max_output_size {
// If we resize, we should always go for at least a round of compression
if !(parameters.width > 0 || parameters.height > 0) && original_size <= max_output_size {
fs::copy(input_path, output_path).map_err(|e| CaesiumError { fs::copy(input_path, output_path).map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 10202, code: 10202,
})?; })?;
return Ok(()); return Ok(());
} }
let compressed_file = let compressed_file =
compress_to_size_in_memory(in_file, parameters, max_output_size, return_smallest)?; compress_to_size_in_memory(in_file, parameters, max_output_size, return_smallest)?;
let mut out_file = File::create(output_path).map_err(|e| CaesiumError { let mut out_file = File::create(output_path).map_err(|e| CaesiumError {
@ -296,9 +292,12 @@ pub fn compress_to_size(
/// # Returns /// # Returns
/// ///
/// * `Result<(), CaesiumError>` - Returns `Ok(())` if conversion is successful, otherwise returns a `CaesiumError`. /// * `Result<(), CaesiumError>` - Returns `Ok(())` if conversion is successful, otherwise returns a `CaesiumError`.
pub fn convert(
pub fn convert(input_path: String, output_path: String, parameters: &CSParameters, format: SupportedFileTypes) -> error::Result<()> { input_path: String,
output_path: String,
parameters: &CSParameters,
format: SupportedFileTypes,
) -> error::Result<()> {
let file_type = get_filetype_from_path(&input_path); let file_type = get_filetype_from_path(&input_path);
if file_type == format { if file_type == format {
@ -312,7 +311,8 @@ pub fn convert(input_path: String, output_path: String, parameters: &CSParameter
message: e.to_string(), message: e.to_string(),
code: 10410, code: 10410,
})?; })?;
let output_buffer = convert_in_memory(in_file, parameters, format).map_err(|e| CaesiumError { let output_buffer =
convert_in_memory(in_file, parameters, format).map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 10411, code: 10411,
})?; })?;
@ -322,7 +322,9 @@ pub fn convert(input_path: String, output_path: String, parameters: &CSParameter
code: 10412, code: 10412,
})?; })?;
out_file.write_all(&output_buffer).map_err(|e| CaesiumError { out_file
.write_all(&output_buffer)
.map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 10413, code: 10413,
})?; })?;
@ -341,7 +343,11 @@ pub fn convert(input_path: String, output_path: String, parameters: &CSParameter
/// # Returns /// # Returns
/// ///
/// * `Result<Vec<u8>, CaesiumError>` - Returns a vector of bytes representing the converted image if successful, otherwise returns a `CaesiumError`. /// * `Result<Vec<u8>, CaesiumError>` - Returns a vector of bytes representing the converted image if successful, otherwise returns a `CaesiumError`.
pub fn convert_in_memory(in_file: Vec<u8>, parameters: &CSParameters, format: SupportedFileTypes) -> Result<Vec<u8>, CaesiumError> { pub fn convert_in_memory(
in_file: Vec<u8>,
parameters: &CSParameters,
format: SupportedFileTypes,
) -> Result<Vec<u8>, CaesiumError> {
convert::convert_in_memory(in_file, format, parameters) convert::convert_in_memory(in_file, format, parameters)
} }

View File

@ -119,7 +119,7 @@ pub struct CSParameters {
pub keep_metadata: bool, pub keep_metadata: bool,
pub optimize: bool, pub optimize: bool,
pub width: u32, pub width: u32,
pub height: u32 pub height: u32,
} }
impl Default for CSParameters { impl Default for CSParameters {
fn default() -> Self { fn default() -> Self {
@ -137,7 +137,7 @@ fn initialize_parameters() -> CSParameters {
let jpeg = JpegParameters { let jpeg = JpegParameters {
quality: 80, quality: 80,
chroma_subsampling: ChromaSubsampling::Auto, chroma_subsampling: ChromaSubsampling::Auto,
progressive: true progressive: true,
}; };
let png = PngParameters { let png = PngParameters {
quality: 80, quality: 80,
@ -160,6 +160,6 @@ fn initialize_parameters() -> CSParameters {
keep_metadata: false, keep_metadata: false,
optimize: false, optimize: false,
width: 0, width: 0,
height: 0 height: 0,
} }
} }

View File

@ -6,9 +6,9 @@ use std::num::NonZeroU8;
use image::ImageFormat; use image::ImageFormat;
use oxipng::Deflaters::Zopfli; use oxipng::Deflaters::Zopfli;
use crate::CSParameters;
use crate::error::CaesiumError; use crate::error::CaesiumError;
use crate::resize::resize; use crate::resize::resize;
use crate::CSParameters;
pub fn compress( pub fn compress(
input_path: String, input_path: String,
@ -48,10 +48,21 @@ pub fn compress_in_memory(
in_file: Vec<u8>, in_file: Vec<u8>,
parameters: &CSParameters, parameters: &CSParameters,
) -> Result<Vec<u8>, CaesiumError> { ) -> Result<Vec<u8>, CaesiumError> {
let optimized_png: Vec<u8> = if parameters.optimize { let input = if parameters.width > 0 || parameters.height > 0 {
lossless(in_file, parameters)? resize(
in_file,
parameters.width,
parameters.height,
ImageFormat::Png,
)?
} else { } else {
lossy(in_file, parameters)? in_file
};
let optimized_png = if parameters.optimize {
lossless(input, parameters)?
} else {
lossy(input, parameters)?
}; };
Ok(optimized_png) Ok(optimized_png)

View File

@ -34,7 +34,8 @@ pub fn resize(
code: 10301, code: 10301,
})?; })?;
let dimensions = compute_dimensions(image.width(), image.height(), desired_width, desired_height); let dimensions =
compute_dimensions(image.width(), image.height(), desired_width, desired_height);
image = image.resize_exact(dimensions.0, dimensions.1, FilterType::Lanczos3); image = image.resize_exact(dimensions.0, dimensions.1, FilterType::Lanczos3);
let mut resized_file: Vec<u8> = vec![]; let mut resized_file: Vec<u8> = vec![];

View File

@ -7,10 +7,10 @@ use tiff::encoder::colortype::{RGB8, RGBA8};
use tiff::encoder::compression::{Deflate, DeflateLevel, Lzw, Packbits, Uncompressed}; use tiff::encoder::compression::{Deflate, DeflateLevel, Lzw, Packbits, Uncompressed};
use tiff::encoder::TiffEncoder; use tiff::encoder::TiffEncoder;
use crate::{CSParameters, TiffDeflateLevel};
use crate::error::CaesiumError; use crate::error::CaesiumError;
use crate::parameters::TiffCompression; use crate::parameters::TiffCompression;
use crate::resize::resize_image; use crate::resize::resize_image;
use crate::{CSParameters, TiffDeflateLevel};
pub fn compress( pub fn compress(
input_path: String, input_path: String,

View File

@ -1,6 +1,6 @@
use std::io::Cursor;
use infer::Type;
use crate::SupportedFileTypes; use crate::SupportedFileTypes;
use infer::Type;
use std::io::Cursor;
pub fn get_filetype_from_path(file_path: &str) -> SupportedFileTypes { pub fn get_filetype_from_path(file_path: &str) -> SupportedFileTypes {
match infer::get_from_path(file_path) { match infer::get_from_path(file_path) {
@ -25,7 +25,7 @@ pub fn get_jpeg_orientation(data: &[u8]) -> u32 {
let exif_data = match reader.read_from_container(&mut cursor) { let exif_data = match reader.read_from_container(&mut cursor) {
Ok(v) => v, Ok(v) => v,
Err(_) => return 1 Err(_) => return 1,
}; };
let exif_field = match exif_data.get_field(exif::Tag::Orientation, exif::In::PRIMARY) { let exif_field = match exif_data.get_field(exif::Tag::Orientation, exif::In::PRIMARY) {
@ -36,7 +36,6 @@ pub fn get_jpeg_orientation(data: &[u8]) -> u32 {
exif_field.value.get_uint(0).unwrap_or(1) exif_field.value.get_uint(0).unwrap_or(1)
} }
fn match_supported_filetypes(ft: Type) -> SupportedFileTypes { fn match_supported_filetypes(ft: Type) -> SupportedFileTypes {
match ft.mime_type() { match ft.mime_type() {
"image/jpeg" => SupportedFileTypes::Jpeg, "image/jpeg" => SupportedFileTypes::Jpeg,

View File

@ -4,13 +4,13 @@ use std::ops::Deref;
use bytes::Bytes; use bytes::Bytes;
use image::{DynamicImage, ImageBuffer}; use image::{DynamicImage, ImageBuffer};
use img_parts::{DynImage, ImageEXIF, ImageICC};
use img_parts::webp::WebP as PartsWebp; use img_parts::webp::WebP as PartsWebp;
use img_parts::{DynImage, ImageEXIF, ImageICC};
use webp::{AnimDecoder, AnimEncoder, AnimFrame, WebPConfig}; use webp::{AnimDecoder, AnimEncoder, AnimFrame, WebPConfig};
use crate::CSParameters;
use crate::error::CaesiumError; use crate::error::CaesiumError;
use crate::resize::resize_image; use crate::resize::resize_image;
use crate::CSParameters;
pub fn compress( pub fn compress(
input_path: String, input_path: String,
@ -59,7 +59,9 @@ pub fn compress_in_memory(
message: e.to_string(), message: e.to_string(),
code: 20306, code: 20306,
})? })?
.map_or((None, None), |dyn_img| (dyn_img.icc_profile(), dyn_img.exif())); .map_or((None, None), |dyn_img| {
(dyn_img.icc_profile(), dyn_img.exif())
});
} }
let must_resize = parameters.width > 0 || parameters.height > 0; let must_resize = parameters.width > 0 || parameters.height > 0;
@ -85,7 +87,6 @@ pub fn compress_in_memory(
config.alpha_compression = if parameters.optimize { 0 } else { 1 }; config.alpha_compression = if parameters.optimize { 0 } else { 1 };
config.quality = parameters.webp.quality as f32; config.quality = parameters.webp.quality as f32;
let mut images_data = vec![]; let mut images_data = vec![];
let mut width = 0; let mut width = 0;
let mut height = 0; let mut height = 0;
@ -118,11 +119,14 @@ pub fn compress_in_memory(
if must_resize { if must_resize {
if images_data.get(i).is_some() { if images_data.get(i).is_some() {
encoder.add_frame(AnimFrame::from_image(images_data.get(i).unwrap(), last_ms) encoder.add_frame(
.map_err(|e| CaesiumError { AnimFrame::from_image(images_data.get(i).unwrap(), last_ms).map_err(
|e| CaesiumError {
message: e.to_string(), message: e.to_string(),
code: 20310, code: 20310,
})?); },
)?,
);
} }
} else { } else {
encoder.add_frame(f); encoder.add_frame(f);
@ -138,7 +142,7 @@ pub fn compress_in_memory(
code: 20311, code: 20311,
}); });
} }
Some(f) => f Some(f) => f,
}; };
let mut input_image = (&first_frame).into(); let mut input_image = (&first_frame).into();
if must_resize { if must_resize {
@ -173,11 +177,12 @@ pub fn compress_in_memory(
let mut image_with_metadata: Vec<u8> = vec![]; let mut image_with_metadata: Vec<u8> = vec![];
let mut dyn_img = match PartsWebp::from_bytes(encoded_image.clone().into()) { let mut dyn_img = match PartsWebp::from_bytes(encoded_image.clone().into()) {
Ok(d) => d, Ok(d) => d,
Err(_) => return Ok(encoded_image) Err(_) => return Ok(encoded_image),
}; };
dyn_img.set_icc_profile(iccp); dyn_img.set_icc_profile(iccp);
dyn_img.set_exif(exif); dyn_img.set_exif(exif);
dyn_img.encoder() dyn_img
.encoder()
.write_to(&mut image_with_metadata) .write_to(&mut image_with_metadata)
.map_err(|e| CaesiumError { .map_err(|e| CaesiumError {
message: e.to_string(), message: e.to_string(),

View File

@ -1,7 +1,7 @@
use crate::cleanup::remove_compressed_test_file; use crate::cleanup::remove_compressed_test_file;
use caesium::parameters::CSParameters;
use std::fs::File; use std::fs::File;
use std::sync::Once; use std::sync::Once;
use caesium::parameters::CSParameters;
mod cleanup; mod cleanup;
@ -99,3 +99,28 @@ fn compress_to_range() {
remove_compressed_test_file(output); remove_compressed_test_file(output);
} }
} }
#[test]
fn compress_to_higher_size_and_resize() {
let output = "tests/samples/output/compressed_10mb.jpg";
let max_output_size = 100_000_000;
initialize(output);
let mut pars = CSParameters::new();
pars.width = 800;
pars.height = 600;
caesium::compress_to_size(
String::from("tests/samples/uncompressed_드림캐쳐.jpg"),
String::from(output),
&mut pars,
max_output_size,
false,
)
.unwrap();
assert!(std::path::Path::new(output).exists());
assert!(File::open(output).unwrap().metadata().unwrap().len() < max_output_size as u64);
let kind = infer::get_from_path(output).unwrap().unwrap();
assert_eq!(kind.mime_type(), "image/jpeg");
assert_eq!(image::image_dimensions(output).unwrap(), (800, 600));
remove_compressed_test_file(output)
}

View File

@ -1,9 +1,9 @@
use caesium::parameters::CSParameters;
use caesium::SupportedFileTypes;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use std::sync::Once; use std::sync::Once;
use caesium::parameters::CSParameters;
use caesium::SupportedFileTypes;
use crate::cleanup::remove_compressed_test_file; use crate::cleanup::remove_compressed_test_file;
@ -23,15 +23,15 @@ fn convert_jpg_to_png() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.keep_metadata = true; params.keep_metadata = true;
caesium::convert(String::from("tests/samples/uncompressed_드림캐쳐.jpg"), caesium::convert(
String::from("tests/samples/uncompressed_드림캐쳐.jpg"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Png).expect("Image converted successfully"); SupportedFileTypes::Png,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
);
assert!(metadata_is_equal( assert!(metadata_is_equal(
Path::new("tests/samples/uncompressed_드림캐쳐.jpg"), Path::new("tests/samples/uncompressed_드림캐쳐.jpg"),
Path::new(output) Path::new(output)
@ -44,15 +44,15 @@ fn convert_jpg_to_webp() {
let output = "tests/samples/output/jpg.to.webp"; let output = "tests/samples/output/jpg.to.webp";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/uncompressed_드림캐쳐.jpg"), caesium::convert(
String::from("tests/samples/uncompressed_드림캐쳐.jpg"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::WebP).expect("Image converted successfully"); SupportedFileTypes::WebP,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -61,15 +61,15 @@ fn convert_jpg_to_tiff() {
let output = "tests/samples/output/jpg.to.tiff"; let output = "tests/samples/output/jpg.to.tiff";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/uncompressed_드림캐쳐.jpg"), caesium::convert(
String::from("tests/samples/uncompressed_드림캐쳐.jpg"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Tiff).expect("Image converted successfully"); SupportedFileTypes::Tiff,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -79,15 +79,15 @@ fn convert_png_to_jpg() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.keep_metadata = true; params.keep_metadata = true;
caesium::convert(String::from("tests/samples/uncompressed_드림캐쳐.png"), caesium::convert(
String::from("tests/samples/uncompressed_드림캐쳐.png"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Jpeg).expect("Image converted successfully"); SupportedFileTypes::Jpeg,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/jpeg");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/jpeg"
);
// assert!(metadata_is_equal( // assert!(metadata_is_equal(
// Path::new("tests/samples/uncompressed_드림캐쳐.png"), // Path::new("tests/samples/uncompressed_드림캐쳐.png"),
// Path::new(output) // Path::new(output)
@ -100,15 +100,15 @@ fn convert_png_to_webp() {
let output = "tests/samples/output/png.to.webp"; let output = "tests/samples/output/png.to.webp";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/uncompressed_드림캐쳐.png"), caesium::convert(
String::from("tests/samples/uncompressed_드림캐쳐.png"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::WebP).expect("Image converted successfully"); SupportedFileTypes::WebP,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -117,15 +117,15 @@ fn convert_png_to_tiff() {
let output = "tests/samples/output/png.to.tiff"; let output = "tests/samples/output/png.to.tiff";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/uncompressed_드림캐쳐.png"), caesium::convert(
String::from("tests/samples/uncompressed_드림캐쳐.png"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Tiff).expect("Image converted successfully"); SupportedFileTypes::Tiff,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -135,15 +135,15 @@ fn convert_webp_to_jpg() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.keep_metadata = true; params.keep_metadata = true;
caesium::convert(String::from("tests/samples/uncompressed_家.webp"), caesium::convert(
String::from("tests/samples/uncompressed_家.webp"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Jpeg).expect("Image converted successfully"); SupportedFileTypes::Jpeg,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/jpeg");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/jpeg"
);
// assert!(metadata_is_equal( // assert!(metadata_is_equal(
// Path::new("tests/samples/uncompressed_家.webp"), // Path::new("tests/samples/uncompressed_家.webp"),
// Path::new(output) // Path::new(output)
@ -156,15 +156,15 @@ fn convert_webp_to_png() {
let output = "tests/samples/output/webp.to.png"; let output = "tests/samples/output/webp.to.png";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/uncompressed_家.webp"), caesium::convert(
String::from("tests/samples/uncompressed_家.webp"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Png).expect("Image converted successfully"); SupportedFileTypes::Png,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -173,15 +173,15 @@ fn convert_webp_to_tiff() {
let output = "tests/samples/output/webp.to.tiff"; let output = "tests/samples/output/webp.to.tiff";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/uncompressed_家.webp"), caesium::convert(
String::from("tests/samples/uncompressed_家.webp"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Tiff).expect("Image converted successfully"); SupportedFileTypes::Tiff,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -190,15 +190,15 @@ fn convert_tiff_to_jpg() {
let output = "tests/samples/output/tiff.to.jpg"; let output = "tests/samples/output/tiff.to.jpg";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/rgba8.tif"), caesium::convert(
String::from("tests/samples/rgba8.tif"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Jpeg).expect("Image converted successfully"); SupportedFileTypes::Jpeg,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/jpeg");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/jpeg"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -207,15 +207,15 @@ fn convert_tiff_to_png() {
let output = "tests/samples/output/tiff.to.png"; let output = "tests/samples/output/tiff.to.png";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/rgba8.tif"), caesium::convert(
String::from("tests/samples/rgba8.tif"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::Png).expect("Image converted successfully"); SupportedFileTypes::Png,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -224,15 +224,15 @@ fn convert_tiff_to_webp() {
let output = "tests/samples/output/tiff.to.webp"; let output = "tests/samples/output/tiff.to.webp";
initialize(output); initialize(output);
let params = CSParameters::new(); let params = CSParameters::new();
caesium::convert(String::from("tests/samples/rgba8.tif"), caesium::convert(
String::from("tests/samples/rgba8.tif"),
String::from(output), String::from(output),
&params, &params,
SupportedFileTypes::WebP).expect("Image converted successfully"); SupportedFileTypes::WebP,
)
.expect("Image converted successfully");
assert!(Path::new(output).exists()); assert!(Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }

View File

@ -1,7 +1,7 @@
use crate::cleanup::remove_compressed_test_file; use crate::cleanup::remove_compressed_test_file;
use dssim::Val;
use std::sync::Once;
use caesium::parameters::CSParameters; use caesium::parameters::CSParameters;
use dssim::Val;
use std::{fs::File, sync::Once};
mod cleanup; mod cleanup;
@ -103,12 +103,7 @@ fn compress_corrupted_lossy() {
initialize(output); initialize(output);
let mut pars = CSParameters::new(); let mut pars = CSParameters::new();
pars.jpeg.quality = 50; pars.jpeg.quality = 50;
assert!(caesium::compress( assert!(caesium::compress(String::from("tests/samples/corrupted.jpg"), String::from(output), &pars,).is_err())
String::from("tests/samples/corrupted.jpg"),
String::from(output),
&pars,
)
.is_err())
} }
#[test] #[test]
@ -140,12 +135,31 @@ fn compress_corrupted_lossless() {
initialize(output); initialize(output);
let mut pars = CSParameters::new(); let mut pars = CSParameters::new();
pars.optimize = true; pars.optimize = true;
assert!(caesium::compress( assert!(caesium::compress(String::from("tests/samples/corrupted.jpg"), String::from(output), &pars,).is_err());
String::from("tests/samples/corrupted.jpg"), }
#[test]
fn downscale_to_size() {
let max_output_size = 2_000_000;
let output = "tests/samples/output/downscale_800_600_to_size.jpg";
initialize(output);
let mut pars = CSParameters::new();
pars.width = 800;
pars.height = 600;
caesium::compress_to_size(
String::from("tests/samples/uncompressed_드림캐쳐.jpg"),
String::from(output), String::from(output),
&pars, &mut pars,
max_output_size,
false,
) )
.is_err()); .unwrap();
assert!(std::path::Path::new(output).exists());
let kind = infer::get_from_path(output).unwrap().unwrap();
assert_eq!(kind.mime_type(), "image/jpeg");
assert!(File::open(output).unwrap().metadata().unwrap().len() < max_output_size as u64);
assert_eq!(image::image_dimensions(output).unwrap(), (800, 600));
remove_compressed_test_file(output)
} }
#[test] #[test]

View File

@ -1,9 +1,9 @@
use crate::cleanup::remove_compressed_test_file;
use caesium::parameters::CSParameters;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use std::sync::Once; use std::sync::Once;
use caesium::parameters::CSParameters;
use crate::cleanup::remove_compressed_test_file;
mod cleanup; mod cleanup;
static INIT: Once = Once::new(); static INIT: Once = Once::new();

View File

@ -1,6 +1,6 @@
use crate::cleanup::remove_compressed_test_file; use crate::cleanup::remove_compressed_test_file;
use std::sync::Once;
use caesium::parameters::CSParameters; use caesium::parameters::CSParameters;
use std::{fs::File, sync::Once};
mod cleanup; mod cleanup;
@ -23,10 +23,7 @@ fn standard_compress_png() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
);
assert_eq!(image::image_dimensions(output).unwrap(), (380, 287)); assert_eq!(image::image_dimensions(output).unwrap(), (380, 287));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -44,31 +41,29 @@ fn standard_compress_png_with_optimize_flag() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
);
assert_eq!(image::image_dimensions(output).unwrap(), (380, 287)); assert_eq!(image::image_dimensions(output).unwrap(), (380, 287));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
// #[test] #[test]
// fn zopfli_compress_png() { fn zopfli_compress_png() {
// let output = "tests/samples/output/optimized.png"; let output = "tests/samples/output/optimized.png";
// initialize(output); initialize(output);
// let mut params = CSParameters::new(); let mut params = CSParameters::new();
// params.png.level = 3; params.optimize = true;
// params.optimize = true; params.png.force_zopfli = true;
// params.png.force_zopfli = true; caesium::compress(
// caesium::compress(String::from("tests/samples/uncompressed_드림캐쳐.png"), String::from("tests/samples/uncompressed_드림캐쳐.png"),
// String::from(output), String::from(output),
// params) &params,
// .unwrap(); )
// assert!(std::path::Path::new(output).exists()); .unwrap();
// assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png"); assert!(std::path::Path::new(output).exists());
// assert_eq!(image::image_dimensions(output).unwrap(), (380, 287)); assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
// remove_compressed_test_file(output) assert_eq!(image::image_dimensions(output).unwrap(), (380, 287));
// } remove_compressed_test_file(output)
}
#[test] #[test]
fn downscale_standard_compress_png() { fn downscale_standard_compress_png() {
@ -84,10 +79,7 @@ fn downscale_standard_compress_png() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
);
assert_eq!(image::image_dimensions(output).unwrap(), (150, 150)); assert_eq!(image::image_dimensions(output).unwrap(), (150, 150));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -107,10 +99,7 @@ fn downscale_standard_compress_png_with_optimize_flag() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
);
assert_eq!(image::image_dimensions(output).unwrap(), (150, 150)); assert_eq!(image::image_dimensions(output).unwrap(), (150, 150));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -132,10 +121,31 @@ fn downscale_zopfli_compress_png() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/png");
infer::get_from_path(output).unwrap().unwrap().mime_type(), assert_eq!(image::image_dimensions(output).unwrap(), (150, 150));
"image/png" remove_compressed_test_file(output)
); }
#[test]
fn downscale_to_size() {
let max_output_size = 20_000;
let output = "tests/samples/output/downscale_to_size.png";
initialize(output);
let mut pars = CSParameters::new();
pars.width = 150;
pars.height = 150;
caesium::compress_to_size(
String::from("tests/samples/uncompressed_드림캐쳐.png"),
String::from(output),
&mut pars,
max_output_size,
false,
)
.unwrap();
assert!(std::path::Path::new(output).exists());
let kind = infer::get_from_path(output).unwrap().unwrap();
assert_eq!(kind.mime_type(), "image/png");
assert!(File::open(output).unwrap().metadata().unwrap().len() < max_output_size as u64);
assert_eq!(image::image_dimensions(output).unwrap(), (150, 150)); assert_eq!(image::image_dimensions(output).unwrap(), (150, 150));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }

1
tests/rustfmt.toml Normal file
View File

@ -0,0 +1 @@
max_width = 120

View File

@ -1,6 +1,6 @@
use std::sync::Once;
use caesium::parameters::{CSParameters, TiffCompression, TiffDeflateLevel};
use crate::cleanup::remove_compressed_test_file; use crate::cleanup::remove_compressed_test_file;
use caesium::parameters::{CSParameters, TiffCompression, TiffDeflateLevel};
use std::{fs::File, sync::Once};
mod cleanup; mod cleanup;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
@ -17,17 +17,9 @@ fn rgb8_uncompressed() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Uncompressed; params.tiff.algorithm = TiffCompression::Uncompressed;
caesium::compress( caesium::compress(String::from("tests/samples/rgb8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgb8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -37,17 +29,9 @@ fn rgba8_uncompressed() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Uncompressed; params.tiff.algorithm = TiffCompression::Uncompressed;
caesium::compress( caesium::compress(String::from("tests/samples/rgba8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgba8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -58,17 +42,9 @@ fn rgb8_deflate() {
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Deflate; params.tiff.algorithm = TiffCompression::Deflate;
params.tiff.deflate_level = TiffDeflateLevel::Balanced; params.tiff.deflate_level = TiffDeflateLevel::Balanced;
caesium::compress( caesium::compress(String::from("tests/samples/rgb8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgb8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -79,17 +55,9 @@ fn rgba8_deflate() {
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Deflate; params.tiff.algorithm = TiffCompression::Deflate;
params.tiff.deflate_level = TiffDeflateLevel::Balanced; params.tiff.deflate_level = TiffDeflateLevel::Balanced;
caesium::compress( caesium::compress(String::from("tests/samples/rgba8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgba8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -99,17 +67,9 @@ fn rgb8_lzw() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Lzw; params.tiff.algorithm = TiffCompression::Lzw;
caesium::compress( caesium::compress(String::from("tests/samples/rgb8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgb8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -119,17 +79,9 @@ fn rgba8_lzw() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Lzw; params.tiff.algorithm = TiffCompression::Lzw;
caesium::compress( caesium::compress(String::from("tests/samples/rgba8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgba8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -139,17 +91,9 @@ fn rgb8_packbits() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Packbits; params.tiff.algorithm = TiffCompression::Packbits;
caesium::compress( caesium::compress(String::from("tests/samples/rgb8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgb8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -159,17 +103,9 @@ fn rgba8_packbits() {
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Packbits; params.tiff.algorithm = TiffCompression::Packbits;
caesium::compress( caesium::compress(String::from("tests/samples/rgba8.tif"), String::from(output), &params).unwrap();
String::from("tests/samples/rgba8.tif"),
String::from(output),
&params,
)
.unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -181,17 +117,33 @@ fn rgb8_downscale() {
params.tiff.algorithm = TiffCompression::Lzw; params.tiff.algorithm = TiffCompression::Lzw;
params.width = 50; params.width = 50;
params.height = 20; params.height = 20;
caesium::compress( caesium::compress(String::from("tests/samples/rgb8.tif"), String::from(output), &params).unwrap();
assert!(std::path::Path::new(output).exists());
assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
assert_eq!(image::image_dimensions(output).unwrap(), (50, 20));
remove_compressed_test_file(output)
}
#[test]
fn rgb8_downscale_to_size() {
let max_output_size = 10_000;
let output = "tests/samples/output/downscale_rgb8_to_size.tif";
initialize(output);
let mut params = CSParameters::new();
params.tiff.algorithm = TiffCompression::Lzw;
params.width = 50;
params.height = 20;
caesium::compress_to_size(
String::from("tests/samples/rgb8.tif"), String::from("tests/samples/rgb8.tif"),
String::from(output), String::from(output),
&params, &mut params,
max_output_size,
false,
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/tiff");
infer::get_from_path(output).unwrap().unwrap().mime_type(), assert!(File::open(output).unwrap().metadata().unwrap().len() < max_output_size as u64);
"image/tiff"
);
assert_eq!(image::image_dimensions(output).unwrap(), (50, 20)); assert_eq!(image::image_dimensions(output).unwrap(), (50, 20));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -206,7 +158,8 @@ fn unsupported() {
String::from("tests/samples/unsupported.tif"), String::from("tests/samples/unsupported.tif"),
String::from(output), String::from(output),
&params, &params,
).is_err()); )
.is_err());
} }
#[test] #[test]
@ -219,5 +172,6 @@ fn prevent_panic() {
String::from("tests/samples/unsupported.tif"), String::from("tests/samples/unsupported.tif"),
String::from(output), String::from(output),
&params, &params,
).is_err()); )
.is_err());
} }

View File

@ -1,6 +1,6 @@
use std::sync::Once;
use caesium::parameters::CSParameters;
use crate::cleanup::remove_compressed_test_file; use crate::cleanup::remove_compressed_test_file;
use caesium::parameters::CSParameters;
use std::{fs::File, sync::Once};
mod cleanup; mod cleanup;
@ -25,10 +25,7 @@ fn compress_20() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -45,10 +42,7 @@ fn compress_50() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -65,10 +59,7 @@ fn compress_80() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -85,10 +76,7 @@ fn compress_100() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -105,32 +93,29 @@ fn optimize() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
#[test] #[test]
fn downscale_compress_80() { fn downscale_to_size() {
let output = "tests/samples/output/downscale_compressed_80.webp"; let max_output_size = 100_000;
let output = "tests/samples/output/downscale_to_size.webp";
initialize(output); initialize(output);
let mut params = CSParameters::new(); let mut params = CSParameters::new();
params.webp.quality = 80;
params.width = 150; params.width = 150;
params.height = 100; params.height = 100;
caesium::compress( caesium::compress_to_size(
String::from("tests/samples/uncompressed_家.webp"), String::from("tests/samples/uncompressed_家.webp"),
String::from(output), String::from(output),
&params, &mut params,
max_output_size,
false,
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(), assert!(File::open(output).unwrap().metadata().unwrap().len() < max_output_size as u64);
"image/webp"
);
assert_eq!(image::image_dimensions(output).unwrap(), (150, 100)); assert_eq!(image::image_dimensions(output).unwrap(), (150, 100));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -150,10 +135,7 @@ fn downscale_optimize() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
assert_eq!(image::image_dimensions(output).unwrap(), (150, 100)); assert_eq!(image::image_dimensions(output).unwrap(), (150, 100));
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }
@ -171,9 +153,6 @@ fn compress_animated_80() {
) )
.unwrap(); .unwrap();
assert!(std::path::Path::new(output).exists()); assert!(std::path::Path::new(output).exists());
assert_eq!( assert_eq!(infer::get_from_path(output).unwrap().unwrap().mime_type(), "image/webp");
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
);
remove_compressed_test_file(output) remove_compressed_test_file(output)
} }