Progressive/baseline JPEG switch while optimizing

This commit is contained in:
Matteo Paonessa 2024-10-10 21:24:35 +02:00
parent ba31f9d7c6
commit c912159261
5 changed files with 37 additions and 27 deletions

View File

@ -4,6 +4,7 @@ use std::io::Write;
use std::mem;
use std::panic::catch_unwind;
use std::ptr::null;
use std::sync::atomic::{AtomicI32, Ordering};
use image::ImageFormat::Jpeg;
use img_parts::{ImageEXIF, ImageICC};
use img_parts::jpeg::Jpeg as PartsJpeg;
@ -15,7 +16,7 @@ use crate::error::CaesiumError;
use crate::parameters::ChromaSubsampling;
use crate::resize::resize;
static mut JPEG_ERROR: c_int = 0;
static JPEG_ERROR: AtomicI32 = AtomicI32::new(0);
pub fn compress(
input_path: String,
@ -63,7 +64,7 @@ pub fn compress_in_memory(
})
.unwrap_or_else(|_| {
Err(CaesiumError {
message: format!("Internal JPEG error: {}", JPEG_ERROR),
message: format!("Internal JPEG error: {}", JPEG_ERROR.load(Ordering::SeqCst)),
code: 20104,
})
})
@ -107,6 +108,9 @@ unsafe fn lossless(in_file: Vec<u8>, parameters: &CSParameters) -> Result<Vec<u8
let mut buf = ptr::null_mut();
let mut buf_size = 0;
jpeg_mem_dest(&mut dst_info, &mut buf, &mut buf_size);
if !parameters.jpeg.progressive {
dst_info.scan_info = null();
}
jpeg_write_coefficients(&mut dst_info, dst_coef_arrays);
if parameters.keep_metadata {
@ -312,8 +316,8 @@ unsafe fn set_chroma_subsampling(
}
unsafe extern "C-unwind" fn error_handler(cinfo: &mut jpeg_common_struct) {
JPEG_ERROR = (*cinfo.err).msg_code;
panic!("Internal JPEG error: {}", JPEG_ERROR);
JPEG_ERROR.store((*cinfo.err).msg_code, Ordering::SeqCst);
panic!("Internal JPEG error: {}", JPEG_ERROR.load(Ordering::SeqCst));
}
unsafe extern "C-unwind" fn error_message_handler(_cinfo: &mut jpeg_common_struct) {}
unsafe extern "C-unwind" fn error_message_handler(_cinfo: &mut jpeg_common_struct) {}

View File

@ -1,6 +1,6 @@
extern crate alloc;
use std::{cmp, fs};
use std::fs;
use std::fs::File;
use std::io::Write;
@ -14,12 +14,12 @@ pub mod error;
mod gif;
mod interface;
#[cfg(feature = "jpg")]
pub mod jpeg;
mod jpeg;
#[cfg(feature = "png")]
mod png;
mod resize;
#[cfg(feature = "tiff")]
pub mod tiff;
mod tiff;
mod utils;
#[cfg(feature = "webp")]
mod webp;
@ -179,7 +179,7 @@ pub fn compress_to_size_in_memory(
last_high = quality;
}
let last_quality = quality;
quality = cmp::max(1, cmp::min(100, (last_high + last_less) / 2));
quality = ((last_high + last_less) / 2).clamp(1, 100);
if last_quality == quality {
if quality == 1 && last_high == 1 {
return if return_smallest {

View File

@ -66,13 +66,19 @@ pub struct CSParameters {
pub height: u32,
pub output_size: u32,
}
impl Default for CSParameters {
fn default() -> Self {
Self::new()
}
}
impl CSParameters {
pub fn new() -> CSParameters {
initialize_parameters()
}
}
pub fn initialize_parameters() -> CSParameters {
fn initialize_parameters() -> CSParameters {
let jpeg = JpegParameters {
quality: 80,
chroma_subsampling: ChromaSubsampling::Auto,

View File

@ -59,7 +59,7 @@ pub fn compress_in_memory(
message: e.to_string(),
code: 20306,
})?
.map_or((None, None), |dimg| (dimg.icc_profile(), dimg.exif()));
.map_or((None, None), |dyn_img| (dyn_img.icc_profile(), dyn_img.exif()));
}
let must_resize = parameters.width > 0 || parameters.height > 0;
@ -171,13 +171,13 @@ pub fn compress_in_memory(
if iccp.is_some() || exif.is_some() {
let mut image_with_metadata: Vec<u8> = vec![];
let mut dimg = match PartsWebp::from_bytes(encoded_image.clone().into()) {
let mut dyn_img = match PartsWebp::from_bytes(encoded_image.clone().into()) {
Ok(d) => d,
Err(_) => return Ok(encoded_image)
};
dimg.set_icc_profile(iccp);
dimg.set_exif(exif);
dimg.encoder()
dyn_img.set_icc_profile(iccp);
dyn_img.set_exif(exif);
dyn_img.encoder()
.write_to(&mut image_with_metadata)
.map_err(|e| CaesiumError {
message: e.to_string(),

View File

@ -27,7 +27,7 @@ fn convert_jpg_to_png() {
String::from(output),
&params,
SupportedFileTypes::Png).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
@ -48,7 +48,7 @@ fn convert_jpg_to_webp() {
String::from(output),
&params,
SupportedFileTypes::WebP).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
@ -65,7 +65,7 @@ fn convert_jpg_to_tiff() {
String::from(output),
&params,
SupportedFileTypes::Tiff).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
@ -83,7 +83,7 @@ fn convert_png_to_jpg() {
String::from(output),
&params,
SupportedFileTypes::Jpeg).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/jpeg"
@ -104,7 +104,7 @@ fn convert_png_to_webp() {
String::from(output),
&params,
SupportedFileTypes::WebP).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"
@ -121,7 +121,7 @@ fn convert_png_to_tiff() {
String::from(output),
&params,
SupportedFileTypes::Tiff).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
@ -139,7 +139,7 @@ fn convert_webp_to_jpg() {
String::from(output),
&params,
SupportedFileTypes::Jpeg).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/jpeg"
@ -160,7 +160,7 @@ fn convert_webp_to_png() {
String::from(output),
&params,
SupportedFileTypes::Png).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
@ -177,7 +177,7 @@ fn convert_webp_to_tiff() {
String::from(output),
&params,
SupportedFileTypes::Tiff).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/tiff"
@ -194,7 +194,7 @@ fn convert_tiff_to_jpg() {
String::from(output),
&params,
SupportedFileTypes::Jpeg).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/jpeg"
@ -211,7 +211,7 @@ fn convert_tiff_to_png() {
String::from(output),
&params,
SupportedFileTypes::Png).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/png"
@ -228,7 +228,7 @@ fn convert_tiff_to_webp() {
String::from(output),
&params,
SupportedFileTypes::WebP).expect("Image converted successfully");
assert!(std::path::Path::new(output).exists());
assert!(Path::new(output).exists());
assert_eq!(
infer::get_from_path(output).unwrap().unwrap().mime_type(),
"image/webp"