From a67f2475a0f69a2bf5b8da27a51cd50a2c610d86 Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Sat, 20 Jul 2024 14:08:50 +0200 Subject: [PATCH] Keep original orientation while converting --- Cargo.toml | 4 +-- src/convert.rs | 79 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a81c940..d5bcaea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libcaesium" -version = "0.16.1" +version = "0.16.2" authors = ["Matteo Paonessa "] edition = "2021" categories = ["multimedia::images"] @@ -42,10 +42,10 @@ bytes = "1.6" lodepng = { version = "3.10", optional = true } imagequant = { version = "4.3", optional = true, default-features = false } tiff = { version = "0.9" } +kamadak-exif = "0.5" [dev-dependencies] dssim = { version = "3.3", default-features = false, features = ["no-macos-vimage"] } -kamadak-exif = "0.5" [[bin]] name = "main" diff --git a/src/convert.rs b/src/convert.rs index 92db831..1a2c427 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -5,16 +5,18 @@ use image::{ColorType, DynamicImage, ImageFormat}; use image::io::Reader as ImageReader; use img_parts::{DynImage, ImageEXIF, ImageICC}; -use crate::error::CaesiumError; use crate::{compress_in_memory, CSParameters, SupportedFileTypes}; +use crate::error::CaesiumError; use crate::utils::get_filetype_from_memory; pub fn convert_in_memory(in_file: Vec, format: SupportedFileTypes, parameters: &CSParameters) -> Result, CaesiumError> { + let mut iccp = None; + let mut exif = None; + let output_format = map_image_format(format)?; + let original_file_type = get_filetype_from_memory(&in_file); - let file_type = get_filetype_from_memory(&in_file); - - if file_type == format { + if original_file_type == format { return Err(CaesiumError { message: "Cannot convert to the same format".into(), code: 10407, @@ -24,14 +26,37 @@ pub fn convert_in_memory(in_file: Vec, format: SupportedFileTypes, parameter let i = in_file.as_slice(); let mut original_image = ImageReader::new(Cursor::new(i)).with_guessed_format() .map_err(|e| CaesiumError { - message: e.to_string(), - code: 10402, - })?.decode() + message: e.to_string(), + code: 10402, + })?.decode() .map_err(|e| CaesiumError { message: e.to_string(), code: 10403, })?; + if parameters.keep_metadata { + if original_file_type == SupportedFileTypes::Jpeg { + let orientation = get_jpeg_orientation(in_file.as_slice()); + original_image = match orientation { + 2 => original_image.fliph(), + 3 => original_image.rotate180(), + 4 => original_image.flipv(), + 5 => original_image.rotate90().fliph(), + 6 => original_image.rotate90(), + 7 => original_image.fliph().rotate90(), + 8 => original_image.rotate270(), + _ => original_image + } + } + + (iccp, exif) = DynImage::from_bytes(Bytes::from(in_file)) + .map_err(|e| CaesiumError { + message: e.to_string(), + code: 10401, + })? + .map_or((None, None), |dimg| (dimg.icc_profile(), dimg.exif())); + } + if format == SupportedFileTypes::Jpeg { original_image = match original_image.color() { ColorType::Rgba8 => DynamicImage::from(original_image.to_rgb8()), @@ -40,28 +65,21 @@ pub fn convert_in_memory(in_file: Vec, format: SupportedFileTypes, parameter _ => original_image, }; } - + let mut output_image: Vec = Vec::new(); original_image.write_to(&mut Cursor::new(&mut output_image), output_format) .map_err(|e| CaesiumError { - message: e.to_string(), - code: 10404, - })?; + message: e.to_string(), + code: 10404, + })?; let compressed_converted_image = compress_in_memory(output_image, parameters) .map_err(|e| CaesiumError { - message: e.to_string(), - code: 10405, - })?; + message: e.to_string(), + code: 10405, + })?; if parameters.keep_metadata { - let (iccp, exif) = DynImage::from_bytes(Bytes::from(in_file)) - .map_err(|e| CaesiumError { - message: e.to_string(), - code: 10401, - })? - .map_or((None, None), |dimg| (dimg.icc_profile(), dimg.exif())); - let dyn_image = DynImage::from_bytes(Bytes::from(compressed_converted_image.clone())) .map_err(|e| CaesiumError { message: e.to_string(), @@ -109,4 +127,21 @@ fn map_image_format(format: SupportedFileTypes) -> Result u32 { + let reader = exif::Reader::new(); + let mut cursor = Cursor::new(data); + + let exif_data = match reader.read_from_container(&mut cursor) { + Ok(v) => v, + Err(_) => return 1 + }; + + let exif_field = match exif_data.get_field(exif::Tag::Orientation, exif::In::PRIMARY) { + Some(value) => value, + None => return 1, + }; + + exif_field.value.get_uint(0).unwrap_or(1) +}