Skip to content

Commit 767ae29

Browse files
committed
adding interpolate quality function to adjust quality-level in heif
1 parent c2c5434 commit 767ae29

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "kapy"
3-
version = "0.2.1"
3+
version = "0.2.2"
44
edition = "2021"
55
authors = ["Seonghwan Jeong <[email protected]>"]
66
build = "build.rs"

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ If you are not using Homebrew, please install the required packages below and se
4949
* libssh library (https://www.libssh.org/get-it/)
5050
* Provided as a package in `vcpkg` the Microsoft's package manager.
5151
* vcpkg (https://vcpkg.io/en/getting-started.html) should be installed first.
52-
* After installation, install the library: `vcpkg install libssh`
52+
* After installation, install the library: `vcpkg install --triplet=x64-windows libssh`
5353
* You need to set the following Windows environment variables:
5454
* LIBSSH_INCLUDE_DIRS={YOUR_LIBSSH_INCLUDE_DIR}
5555
* LIBSSH_LIB_DIRS={YOUR_LIBSSH_LIB_DIR}
@@ -60,6 +60,13 @@ If you are not using Homebrew, please install the required packages below and se
6060
* NASM executable (https://www.nasm.us/)
6161
* Provides pre-built binary installer and only executables
6262
* You need to add the directory where executables were installed to your PATH.
63+
* libheif library (https://github.com/strukturag/libheif)
64+
* Provided as a package in `vcpkg` the Microsoft's package manager.
65+
* vcpkg (https://vcpkg.io/en/getting-started.html) should be installed first.
66+
* After installation, install the library: `vcpkg install --triplet=x64-windows-static-md`
67+
* You need to set `vcpkg` related environment variables:
68+
* VCPKG_ROOT={YOUR_VCPKG_ROOT_DIR}
69+
* You need to append VCPKG_ROOT directory to your PATH environment.
6370

6471
### Build
6572
```shell

src/processor/heif.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn encode(wand: &mut MagickWand, quality: u8) -> Result<Vec<u8>> {
4545
let lib_heif = LibHeif::new();
4646
let mut context = HeifContext::new()?;
4747
let mut encoder = lib_heif.encoder_for_format(CompressionFormat::Hevc)?;
48-
encoder.set_quality(EncoderQuality::Lossy(quality))?;
48+
encoder.set_quality(EncoderQuality::Lossy(interpolate_quality(quality)))?;
4949
let handle = context.encode_image(&image, &mut encoder, None)?;
5050

5151
// add metadata
@@ -61,6 +61,59 @@ pub fn encode(wand: &mut MagickWand, quality: u8) -> Result<Vec<u8>> {
6161
.map_err(|e| anyhow!("Failed to write to bytes: {}", e))
6262
}
6363

64+
fn interpolate_quality(quality: u8) -> u8 {
65+
let biases = vec![
66+
(70, 50.),
67+
(85, 60.),
68+
(92, 70.),
69+
(95, 80.),
70+
(100, 100.),
71+
];
72+
73+
let tolerance = 0.1;
74+
75+
let mut lower: Option<(i32, f32)> = None;
76+
let mut upper: Option<(i32, f32)> = None;
77+
78+
for (i, &(q, biased)) in biases.iter().enumerate() {
79+
if q == quality {
80+
return biased as u8;
81+
} else if q < quality {
82+
lower = Some((i as i32, biased));
83+
} else if q > quality {
84+
upper = Some((i as i32, biased));
85+
break;
86+
}
87+
}
88+
89+
match (lower, upper) {
90+
(Some((lower_idx, lower_size)), Some((upper_idx, upper_size))) => {
91+
let lower_quality = biases[lower_idx as usize].0 as f32;
92+
let upper_quality = biases[upper_idx as usize].0 as f32;
93+
let quality_ratio = (quality as f32 - lower_quality) / (upper_quality - lower_quality);
94+
let interpolated_size = lower_size + quality_ratio * (upper_size - lower_size);
95+
96+
if (interpolated_size - lower_size).abs() < tolerance {
97+
return lower_size as u8;
98+
} else if (interpolated_size - upper_size).abs() < tolerance {
99+
return upper_size as u8;
100+
} else {
101+
return interpolated_size as u8;
102+
}
103+
}
104+
(Some((_lower_idx, lower_size)), None) => {
105+
return lower_size as u8;
106+
}
107+
(None, Some((_upper_idx, upper_size))) => {
108+
return upper_size as u8;
109+
}
110+
_ => {
111+
// never reached
112+
panic!("Unable to interpolate file size")
113+
},
114+
}
115+
}
116+
64117
fn get_image_profile<T: AsRef<str>>(wand: &mut MagickWand, name: T) -> Option<Vec<u8>> {
65118
let c_name = CString::new(name.as_ref()).unwrap();
66119
let mut n = 0;

0 commit comments

Comments
 (0)