Fixing jpeg memory leak

This commit is contained in:
Matteo Paonessa 2023-04-08 13:22:11 +02:00
parent c22b390f34
commit 2b71a83c0b
2 changed files with 43 additions and 28 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "libcaesium"
version = "0.11.0"
version = "0.11.1"
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
edition = "2021"
categories = ["multimedia::images"]
@ -22,17 +22,17 @@ repository = "https://github.com/Lymphatus/libcaesium"
license = "Apache-2.0"
[dependencies]
mozjpeg-sys = { version = "1.0.2", optional = true }
oxipng = { version = "8.0.0", optional = true }
mozjpeg-sys = { version = "1.0", optional = true }
oxipng = { version = "8.0", optional = true }
libc = "0.2"
gifsicle = { version = "1.92.5", optional = true }
webp = { version = "0.2", optional = true }
infer = "0.12.0"
infer = "0.13.0"
image = { version = "0.24.3", default-features = false, features = ["jpeg", "png", "webp", "gif"] }
img-parts = "0.3"
bytes = "1.1"
lodepng = { version = "3.7", optional = true }
imagequant = {git = "https://github.com/Lymphatus/libimagequant", rev = "67f1686", optional = true}
imagequant = {version = "4.1", optional = true}
[features]
default = ["jpg", "png", "webp", "gif"]

View File

@ -2,10 +2,11 @@ use image::ImageOutputFormat::Jpeg;
use img_parts::{DynImage, ImageEXIF, ImageICC};
use mozjpeg_sys::*;
use std::fs;
use std::{fs, ptr};
use std::fs::File;
use std::io::Write;
use std::{io, mem};
use libc::free;
use crate::resize::resize;
use crate::CSParameters;
@ -36,23 +37,20 @@ pub fn compress_to_memory(mut in_file: Vec<u8>, parameters: &CSParameters) -> Re
}
unsafe {
let compression_buffer: (*mut u8, u64) = if parameters.optimize {
let compression_buffer = if parameters.optimize {
lossless(in_file, parameters)?
} else {
lossy(in_file, parameters)?
};
let slice = std::slice::from_raw_parts(
compression_buffer.0,
compression_buffer.1 as usize,
);
Ok(slice.to_vec())
Ok(compression_buffer)
}
}
unsafe fn lossless(
in_file: Vec<u8>,
parameters: &CSParameters,
) -> Result<(*mut u8, u64), io::Error> {
) -> Result<Vec<u8>, io::Error> {
let mut src_info: jpeg_decompress_struct = mem::zeroed();
let mut src_err = mem::zeroed();
@ -80,7 +78,7 @@ unsafe fn lossless(
let dst_coef_arrays = src_coef_arrays;
dst_info.optimize_coding = i32::from(true);
let mut buf = std::ptr::null_mut();
let mut buf = ptr::null_mut();
let mut buf_size = 0;
jpeg_mem_dest(&mut dst_info, &mut buf, &mut buf_size);
jpeg_write_coefficients(&mut dst_info, dst_coef_arrays);
@ -104,10 +102,19 @@ unsafe fn lossless(
jpeg_finish_decompress(&mut src_info);
jpeg_destroy_decompress(&mut src_info);
Ok((buf, buf_size as u64))
let slice = std::slice::from_raw_parts(
buf,
buf_size as usize,
);
let result = slice.to_vec();
free(buf as *mut c_void);
Ok(result)
}
unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<(*mut u8, u64), io::Error> {
unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<Vec<u8>, io::Error> {
let mut src_info: jpeg_decompress_struct = mem::zeroed();
let mut src_err = mem::zeroed();
let mut dst_info: jpeg_compress_struct = mem::zeroed();
@ -129,9 +136,6 @@ unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<(*mut u8,
}
jpeg_read_header(&mut src_info, true as boolean);
let mut buf = std::ptr::null_mut();
let mut buf_size = 0;
jpeg_mem_dest(&mut dst_info, &mut buf, &mut buf_size);
let width = src_info.image_width;
let height = src_info.image_height;
@ -149,9 +153,6 @@ unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<(*mut u8,
jpeg_read_scanlines(&mut src_info, jsamparray.as_mut_ptr(), 1);
}
dst_info.image_width = width;
dst_info.image_height = height;
dst_info.in_color_space = color_space;
let input_components = match color_space {
JCS_GRAYSCALE => 1,
JCS_RGB => 3,
@ -160,7 +161,14 @@ unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<(*mut u8,
JCS_YCCK => 4,
_ => 3,
};
dst_info.input_components = input_components;
let mut buf_size = 0;
let mut buf = mem::zeroed();
jpeg_mem_dest(&mut dst_info, &mut buf, &mut buf_size);
dst_info.image_width = width;
dst_info.image_height = height;
dst_info.in_color_space = color_space;
dst_info.input_components = input_components as c_int;
jpeg_set_defaults(&mut dst_info);
let row_stride = dst_info.image_width as usize * dst_info.input_components as usize;
@ -194,14 +202,21 @@ unsafe fn lossy(in_file: Vec<u8>, parameters: &CSParameters) -> Result<(*mut u8,
jpeg_write_scanlines(&mut dst_info, jsamparray.as_ptr(), 1);
}
jpeg_finish_compress(&mut dst_info);
jpeg_destroy_compress(&mut dst_info);
jpeg_finish_decompress(&mut src_info);
jpeg_destroy_decompress(&mut src_info);
jpeg_finish_compress(&mut dst_info);
jpeg_destroy_compress(&mut dst_info);
// let mut output_file_buffer = File::create(output_path)?;
// output_file_buffer.write_all(std::slice::from_raw_parts(buf, buf_size as usize))?;
Ok((buf, buf_size as u64))
let slice = std::slice::from_raw_parts(
buf,
buf_size as usize,
);
let result = slice.to_vec();
free(buf as *mut c_void);
Ok(result)
}
fn extract_metadata(image: Vec<u8>) -> (Option<img_parts::Bytes>, Option<img_parts::Bytes>) {