-
Notifications
You must be signed in to change notification settings - Fork 655
Fix preview of images with non srgb icc profile #3358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
By the way, it was a headache to deal with jemalloc in nix-shell, no idea why it does not compile. I had to disable it while making the PR and then enable it again before pushing. |
c506e93 to
db3a79e
Compare
|
This change looks reasonable to me, thank you for the patch! I don't know Nix well, so would like someone else to review the Nix-related change some, would you like to pull it out to a separate PR so it won't block this one? |
sxyazi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit
yazi-adapter/src/image.rs
Outdated
| impl Image { | ||
| pub async fn precache(src: PathBuf, cache: &Path) -> Result<()> { | ||
| let (mut img, orientation, icc) = Self::decode_from(src).await?; | ||
| let (mut img, orientation, icc) = Self::decode_from(src.clone()).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let (mut img, orientation, icc) = Self::decode_from(src.clone()).await?; | |
| let (mut img, orientation, icc) = Self::decode_from(src).await?; |
yazi-adapter/src/image.rs
Outdated
| icc.map(|b| encoder.set_icc_profile(b)); | ||
| encoder.encode_image(&img.into_rgb8())?; | ||
|
|
||
| let mut data = img.to_rgb8().into_raw(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let mut data = img.to_rgb8().into_raw(); | |
| let mut data = img.into_rgb8().into_raw(); |
yazi-adapter/src/image.rs
Outdated
| // If ICC profile is present and it's not srgb, perform color transformation | ||
| if let Some(ref icc_profile) = icc | ||
| && let Some(input) = Profile::new_from_slice(icc_profile, false) | ||
| && !input.is_sRGB() | ||
| { | ||
| let mut output = Profile::new_sRGB(); | ||
| output.precache_output_transform(); | ||
|
|
||
| let xfm = Transform::new(&input, &output, qcms::DataType::RGB8, qcms::Intent::default()) | ||
| .context("Failed creating the ICC transformer")?; | ||
| xfm.apply(&mut data); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please pull these out into a new function called apply_profile
The thing is that without this change I can't build in the nix shell, cargo fails to build jemalloc. The change is only to tell jemalloc-sys where to find the pre built one. |
|
That sounds like a problem specific to your environment since our CI passed the build and other people seem not to have reported similar issues. CC @XYenon who is the maintainer of Yazi's Nix package - do you think that change makes sense? |
In CI it uses |
db3a79e to
f65ce08
Compare
41034d0 to
449450d
Compare
f65ce08 to
66464e6
Compare
What error message occurred on which platform? |
In nix develop / nix-shell / direnv, I'm in nixos btw. |
|
I found the issue because |
|
Ok, then I will rebase the PR and remove the commit for the jemalloc thingy as soon as the one from @XYenon gets merged. |
66464e6 to
0b88073
Compare
yazi-adapter/src/image.rs
Outdated
| let rgba = img.into_rgba8(); | ||
| let mut encoder = PngEncoder::new(&mut buf); | ||
| icc.map(|b| encoder.set_icc_profile(b)); | ||
| encoder.write_image(&rgba, rgba.width(), rgba.height(), ExtendedColorType::Rgba8)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the same process of sRGB to RGB(A) conversion be applied to the PNG encoder as well for transparent images?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't do it there as I don't know of a case where that affects images with alpha, therefore I don't have how to test it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I found some, I'll give it a try.
yazi-adapter/src/image.rs
Outdated
| let width = img.width(); | ||
| let height = img.height(); | ||
| let mut data = img.into_rgb8().into_raw(); | ||
| Self::apply_profile(icc, &mut data)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that apply_profile only applied to the precache function, which means it will only work if the user doesn't disable the image preloader and the image has generated a cache at the time, which is problematic as image preview should behave the same way regardless of whether it has cached, i.e. it should also be implemented for downscale which is directlly called by image_show (instead of image_precache), maybe this process should placed under decode_from which precache and downscale both call
0b88073 to
81e218d
Compare
|
I don't like the |
81e218d to
ae5e3fc
Compare
Which issue does this PR resolve?
Currently yazi can't correctly preview images that are not srgb, this PRs transforms the colorspace while making the cache entry so they work fine.
Rationale of this PR
It reads the icc of the image, checks if it's not srgb and if that's the case, makes it into srgb before writing to the cache folder.
This is an example of an image that works fine after the change and didn't before: