use crate::common::error::Result;
use crate::common::types::{CropRegion, DensityInfo, PixelFormat, Subsampling};
use crate::decode::pipeline::{Decoder, Image};
use crate::encode::pipeline as encoder;
pub fn decompress(data: &[u8]) -> Result<Image> {
Decoder::decode(data)
}
pub fn decompress_to(data: &[u8], format: PixelFormat) -> Result<Image> {
Decoder::decode_to(data, format)
}
pub fn decompress_lenient(data: &[u8]) -> Result<Image> {
let mut decoder = Decoder::new(data)?;
decoder.set_lenient(true);
decoder.decode_image()
}
pub fn decompress_cropped(data: &[u8], region: CropRegion) -> Result<Image> {
let mut decoder = Decoder::new(data)?;
let header = decoder.header();
let img_w = header.width as usize;
let img_h = header.height as usize;
let x = region.x.min(img_w);
let y = region.y.min(img_h);
let w = region.width.min(img_w.saturating_sub(x));
let h = region.height.min(img_h.saturating_sub(y));
if w == 0 || h == 0 {
return Ok(Image {
width: w,
height: h,
pixel_format: PixelFormat::Rgb,
precision: 8,
data: Vec::new(),
icc_profile: None,
exif_data: None,
comment: None,
density: DensityInfo::default(),
saved_markers: Vec::new(),
warnings: Vec::new(),
});
}
decoder.set_crop_region(x, y, w, h);
let full = decoder.decode_image()?;
let bpp = full.pixel_format.bytes_per_pixel();
let mut cropped_data = Vec::with_capacity(w * h * bpp);
for row in y..y + h {
let start = (row * full.width + x) * bpp;
cropped_data.extend_from_slice(&full.data[start..start + w * bpp]);
}
Ok(Image {
width: w,
height: h,
pixel_format: full.pixel_format,
precision: 8,
data: cropped_data,
icc_profile: full.icc_profile,
exif_data: full.exif_data,
comment: full.comment,
density: full.density,
saved_markers: full.saved_markers,
warnings: full.warnings,
})
}
pub fn compress(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
quality: u8,
subsampling: Subsampling,
) -> Result<Vec<u8>> {
encoder::compress(
pixels,
width,
height,
pixel_format,
quality,
subsampling,
crate::common::types::DctMethod::IsLow,
)
}
pub fn compress_optimized(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
quality: u8,
subsampling: Subsampling,
) -> Result<Vec<u8>> {
encoder::compress_optimized(pixels, width, height, pixel_format, quality, subsampling)
}
pub fn compress_progressive(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
quality: u8,
subsampling: Subsampling,
) -> Result<Vec<u8>> {
encoder::compress_progressive(pixels, width, height, pixel_format, quality, subsampling)
}
#[allow(clippy::too_many_arguments)]
pub fn compress_with_metadata(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
quality: u8,
subsampling: Subsampling,
icc_profile: Option<&[u8]>,
exif_data: Option<&[u8]>,
) -> Result<Vec<u8>> {
encoder::compress_with_metadata(
pixels,
width,
height,
pixel_format,
quality,
subsampling,
icc_profile,
exif_data,
)
}
pub fn compress_lossless(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
) -> Result<Vec<u8>> {
encoder::compress_lossless(pixels, width, height, pixel_format)
}
pub fn compress_lossless_extended(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
predictor: u8,
point_transform: u8,
) -> Result<Vec<u8>> {
encoder::compress_lossless_extended(
pixels,
width,
height,
pixel_format,
predictor,
point_transform,
)
}
pub fn compress_arithmetic_progressive(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
quality: u8,
subsampling: Subsampling,
) -> Result<Vec<u8>> {
encoder::compress_arithmetic_progressive(
pixels,
width,
height,
pixel_format,
quality,
subsampling,
)
}
pub fn compress_lossless_arithmetic(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
predictor: u8,
point_transform: u8,
) -> Result<Vec<u8>> {
encoder::compress_lossless_arithmetic(
pixels,
width,
height,
pixel_format,
predictor,
point_transform,
)
}
pub fn compress_into(
buf: &mut [u8],
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
quality: u8,
subsampling: Subsampling,
) -> Result<usize> {
let jpeg_data: Vec<u8> = encoder::compress(
pixels,
width,
height,
pixel_format,
quality,
subsampling,
crate::common::types::DctMethod::IsLow,
)?;
if jpeg_data.len() > buf.len() {
return Err(crate::common::error::JpegError::BufferTooSmall {
need: jpeg_data.len(),
got: buf.len(),
});
}
buf[..jpeg_data.len()].copy_from_slice(&jpeg_data);
Ok(jpeg_data.len())
}
pub fn compress_arithmetic(
pixels: &[u8],
width: usize,
height: usize,
pixel_format: PixelFormat,
quality: u8,
subsampling: Subsampling,
) -> Result<Vec<u8>> {
encoder::compress_arithmetic(pixels, width, height, pixel_format, quality, subsampling)
}