fix: scale thumbnails to fill the preview window
This commit is contained in:
+61
-1
@@ -95,7 +95,7 @@ impl Thumbnail {
|
||||
|
||||
let mut message = self.error.as_deref().unwrap_or("Loading thumbnail...");
|
||||
if let Some(image) = self.image.as_mut() {
|
||||
let resize = Resize::Fit(Some(FilterType::Triangle));
|
||||
let resize = Resize::Scale(Some(FilterType::Triangle));
|
||||
if let Some(size) = image.protocol.size_for(resize.clone(), area.into()) {
|
||||
frame.render_stateful_widget(
|
||||
StatefulImage::new().resize(resize),
|
||||
@@ -274,6 +274,66 @@ mod tests {
|
||||
assert!(thumbnail.error.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn small_thumbnail_fills_popup_proportionally_and_resizes() {
|
||||
use ratatui::{Terminal, backend::TestBackend, style::Color};
|
||||
use std::time::Duration;
|
||||
|
||||
let mut thumbnail = Thumbnail::new();
|
||||
let font = thumbnail.picker.font_size();
|
||||
let image = image::DynamicImage::ImageRgb8(image::RgbImage::from_pixel(
|
||||
48,
|
||||
36,
|
||||
image::Rgb([240, 40, 70]),
|
||||
));
|
||||
let (requests_tx, requests_rx) = mpsc::channel::<ResizeRequest>();
|
||||
let (replies_tx, replies_rx) = mpsc::channel();
|
||||
thumbnail.selected = Some("thumbnail".into());
|
||||
thumbnail.image = Some(ThumbnailImage {
|
||||
id: "thumbnail".into(),
|
||||
protocol: ThreadProtocol::new(
|
||||
requests_tx,
|
||||
Some(thumbnail.picker.new_resize_protocol(image)),
|
||||
),
|
||||
replies: replies_rx,
|
||||
complete: false,
|
||||
});
|
||||
let mut terminal = Terminal::new(TestBackend::new(100, 40)).unwrap();
|
||||
for area in [Rect::new(3, 2, 80, 18), Rect::new(7, 4, 30, 8)] {
|
||||
terminal.draw(|frame| thumbnail.draw(frame, area)).unwrap();
|
||||
let response = requests_rx
|
||||
.recv_timeout(Duration::from_secs(2))
|
||||
.unwrap()
|
||||
.resize_encode()
|
||||
.unwrap();
|
||||
replies_tx.send(Ok(response)).unwrap();
|
||||
terminal.draw(|frame| thumbnail.draw(frame, area)).unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
let pixels: Vec<_> = (0..40)
|
||||
.flat_map(|y| (0..100).map(move |x| (x, y)))
|
||||
.filter(|&(x, y)| {
|
||||
let cell = &buffer[(x, y)];
|
||||
matches!(cell.fg, Color::Rgb(..)) || matches!(cell.bg, Color::Rgb(..))
|
||||
})
|
||||
.collect();
|
||||
let left = pixels.iter().map(|&(x, _)| x).min().unwrap();
|
||||
let right = pixels.iter().map(|&(x, _)| x).max().unwrap() + 1;
|
||||
let top = pixels.iter().map(|&(_, y)| y).min().unwrap();
|
||||
let bottom = pixels.iter().map(|&(_, y)| y).max().unwrap() + 1;
|
||||
assert!(left >= area.x && right <= area.right());
|
||||
assert!(top >= area.y && bottom <= area.bottom());
|
||||
assert!(right - left == area.width || bottom - top == area.height);
|
||||
assert!((left - area.x).abs_diff(area.right() - right) <= 1);
|
||||
assert!((top - area.y).abs_diff(area.bottom() - bottom) <= 1);
|
||||
let width = u32::from(right - left) * u32::from(font.width);
|
||||
let height = u32::from(bottom - top) * u32::from(font.height);
|
||||
assert!(
|
||||
width.abs_diff(height * 4 / 3)
|
||||
<= u32::from(font.width) + u32::from(font.height) * 4 / 3
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resized_image_preserves_aspect_and_stays_inside_popup() {
|
||||
let picker = Picker::halfblocks();
|
||||
|
||||
Reference in New Issue
Block a user