Keep original orientation while converting

This commit is contained in:
Matteo Paonessa 2024-07-20 14:08:50 +02:00
parent ef402d1a1d
commit a67f2475a0
2 changed files with 59 additions and 24 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "libcaesium"
version = "0.16.1"
version = "0.16.2"
authors = ["Matteo Paonessa <matteo.paonessa@gmail.com>"]
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"

View File

@ -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<u8>, format: SupportedFileTypes, parameters: &CSParameters) -> Result<Vec<u8>, 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,
@ -32,6 +34,29 @@ pub fn convert_in_memory(in_file: Vec<u8>, format: SupportedFileTypes, parameter
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()),
@ -55,13 +80,6 @@ pub fn convert_in_memory(in_file: Vec<u8>, format: SupportedFileTypes, parameter
})?;
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(),
@ -110,3 +128,20 @@ fn map_image_format(format: SupportedFileTypes) -> Result<ImageFormat, CaesiumEr
Ok(image_format)
}
fn get_jpeg_orientation(data: &[u8]) -> 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)
}