image: Move background color guess to other thread

Also, skip it completely for JPEG and BMP

Issue #111
This commit is contained in:
Sophie Herold 2023-04-03 17:39:02 +02:00 • committed by Christopher Davis
parent 114c292225
commit 1b18486826
2 changed files with 71 additions and 43 deletions

View file

@ -31,6 +31,13 @@ impl ImageFormat {
pub fn is_svg(&self) -> bool { pub fn is_svg(&self) -> bool {
matches!(self, Self::Svg) matches!(self, Self::Svg)
} }
pub fn is_potentially_transparent(&self) -> bool {
!matches!(
self,
Self::ImageRs(image_rs::ImageFormat::Bmp) | Self::ImageRs(image_rs::ImageFormat::Jpeg)
)
}
} }
impl std::fmt::Display for ImageFormat { impl std::fmt::Display for ImageFormat {

View file

@ -810,8 +810,14 @@ impl LpImage {
new_tiles.cleanup(imp.zoom_target.get(), self.viewport()); new_tiles.cleanup(imp.zoom_target.get(), self.viewport());
new_tiles new_tiles
}); });
if self.imp().background_color.borrow().is_none() { if imp.background_color.borrow().is_none() {
self.set_background_color(self.background_color_guess()); spawn!(glib::clone!(@weak self as obj => async move {
let color = obj.background_color_guess().await;
obj.set_background_color(color);
if obj.is_mapped() {
obj.queue_draw();
}
}));
} }
} }
DecoderUpdate::Error(err) => { DecoderUpdate::Error(err) => {
@ -1635,7 +1641,16 @@ impl LpImage {
/// Returns a background color that should give suitable contrast with transparent images /// Returns a background color that should give suitable contrast with transparent images
/// ///
/// For non-transparent images this always returns `BACKGROUND_COLOR_DEFAULT` /// For non-transparent images this always returns `BACKGROUND_COLOR_DEFAULT`
pub fn background_color_guess(&self) -> Option<gdk::RGBA> { pub async fn background_color_guess(&self) -> Option<gdk::RGBA> {
// Shortcut for formats that don't support transparency
if !self
.format()
.map_or(true, |x| x.is_potentially_transparent())
{
log::debug!("This format does not support transparency");
return Some(*BACKGROUND_COLOR_DEFAULT);
}
let (width, height) = self.original_dimensions(); let (width, height) = self.original_dimensions();
let max_size = i32::max(width, height); let max_size = i32::max(width, height);
@ -1660,14 +1675,17 @@ impl LpImage {
return None; return None;
} }
// Render the small version of the image and download to RAM
let texture = renderer.render_texture(node, None); let texture = renderer.render_texture(node, None);
let mut downloader = gdk::TextureDownloader::new(&texture); let mut downloader = gdk::TextureDownloader::new(&texture);
downloader.set_format(gdk::MemoryFormat::R8g8b8a8); downloader.set_format(gdk::MemoryFormat::R8g8b8a8);
let (bytes, stride) = downloader.download_bytes(); let (bytes, stride) = downloader.download_bytes();
gio::spawn_blocking(move || {
let mut bytes_iter = bytes.iter(); let mut bytes_iter = bytes.iter();
// Number of transparent pixels
let mut transparent = 0; let mut transparent = 0;
// Number of non-transparent pixels with bad contrast
let mut bad_contrast = 0; let mut bad_contrast = 0;
'img: loop { 'img: loop {
for _ in 0..texture.width() { for _ in 0..texture.width() {
@ -1713,5 +1731,8 @@ impl LpImage {
} else { } else {
Some(*BACKGROUND_COLOR_DEFAULT) Some(*BACKGROUND_COLOR_DEFAULT)
} }
})
.await
.ok()?
} }
} }