Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Resize images to columns #258

Merged
merged 8 commits into from
Apr 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ Use `cargo release` to create a new release.

## [Unreleased]

### Changed
- mdcat now uses the kitty protocol to render images on WezTerm (see [GH-258]).
- mdcat now downscales images to the column limit if rendering with the kitty protocol (see [GH-258]).
Previously mdcat scaled down to the window size, which looked strange if a given `--columns` was much smaller than the window size.

[GH-258]: https://github.com/swsnr/mdcat/pull/258

## [2.0.2] – 2023-04-19

### Changed
Expand Down
16 changes: 8 additions & 8 deletions pulldown-cmark-mdcat/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ pub fn write_event<'a, W: Write>(
writer,
&settings.terminal_capabilities,
&settings.theme,
settings.terminal_size.columns - (attrs.indent as usize),
settings.terminal_size.columns - attrs.indent,
)?;
writeln!(writer)?;
stack
Expand Down Expand Up @@ -286,7 +286,7 @@ pub fn write_event<'a, W: Write>(
InlineAttrs { style, indent },
))
.and_data(data.current_line(CurrentLine {
length: indent as usize,
length: indent,
trailing_space: None,
}))
.ok()
Expand Down Expand Up @@ -320,7 +320,7 @@ pub fn write_event<'a, W: Write>(
writer,
&settings.terminal_capabilities,
&settings.theme,
settings.terminal_size.columns - (attrs.indent as usize),
settings.terminal_size.columns - attrs.indent,
)?;
writeln!(writer)?;
stack
Expand Down Expand Up @@ -476,7 +476,7 @@ pub fn write_event<'a, W: Write>(
&settings.terminal_capabilities,
&settings.theme.code_style.on_top_of(&attrs.style),
settings.terminal_size.columns,
attrs.indent as usize,
attrs.indent,
data.current_line,
code,
)?;
Expand All @@ -494,7 +494,7 @@ pub fn write_event<'a, W: Write>(
&attrs.style,
marker,
)?;
let length = data.current_line.length + display_width(marker);
let length = data.current_line.length + display_width(marker) as u16;
Ok(stack
.current(Inline(ListItem(kind, state), attrs))
.and_data(data.current_line(CurrentLine {
Expand Down Expand Up @@ -530,7 +530,7 @@ pub fn write_event<'a, W: Write>(
&settings.terminal_capabilities,
&attrs.style,
settings.terminal_size.columns,
attrs.indent as usize,
attrs.indent,
data.current_line,
text,
)?;
Expand All @@ -552,7 +552,7 @@ pub fn write_event<'a, W: Write>(
&settings.terminal_capabilities,
&attrs.style,
settings.terminal_size.columns,
attrs.indent as usize,
attrs.indent,
data.current_line,
text,
)?;
Expand Down Expand Up @@ -689,7 +689,7 @@ pub fn write_event<'a, W: Write>(
let image_state = match (settings.terminal_capabilities.image, resolved_link) {
(Some(capability), Some(ref url)) => capability
.image_protocol()
.write_inline_image(writer, &resource_handler, url, &settings.terminal_size)
.write_inline_image(writer, &resource_handler, url, settings.terminal_size)
.map_err(|error| {
event!(Level::ERROR, ?error, %url, "failed to render image with capability {:?}: {:#}", capability, error);
error
Expand Down
2 changes: 1 addition & 1 deletion pulldown-cmark-mdcat/src/render/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct LinkReferenceDefinition<'a> {
#[derive(Debug)]
pub struct CurrentLine {
/// The line length
pub(super) length: usize,
pub(super) length: u16,
/// Trailing space to add before continuing this line.
pub(super) trailing_space: Option<String>,
}
Expand Down
30 changes: 16 additions & 14 deletions pulldown-cmark-mdcat/src/render/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ fn write_remaining_lines<W: Write>(
writer: &mut W,
capabilities: &TerminalCapabilities,
style: &Style,
indent: usize,
indent: u16,
mut buffer: String,
next_lines: &[&[Word]],
last_line: &[Word],
) -> Result<CurrentLine> {
// Finish the previous line
writeln!(writer)?;
write_indent(writer, indent as u16)?;
write_indent(writer, indent)?;
// Now write all lines up to the last
for line in next_lines {
match line.split_last() {
Expand All @@ -65,7 +65,7 @@ fn write_remaining_lines<W: Write>(
buffer.push_str(last.word);
write_styled(writer, capabilities, style, &buffer)?;
writeln!(writer)?;
write_indent(writer, indent as u16)?;
write_indent(writer, indent)?;
buffer.clear();
}
};
Expand All @@ -85,7 +85,7 @@ fn write_remaining_lines<W: Write>(
buffer.push_str(last.word);
write_styled(writer, capabilities, style, &buffer)?;
Ok(CurrentLine {
length: textwrap::core::display_width(&buffer),
length: textwrap::core::display_width(&buffer) as u16,
trailing_space: Some(last.whitespace.to_owned()),
})
}
Expand All @@ -96,8 +96,8 @@ pub fn write_styled_and_wrapped<W: Write, S: AsRef<str>>(
writer: &mut W,
capabilities: &TerminalCapabilities,
style: &Style,
max_width: usize,
indent: usize,
max_width: u16,
indent: u16,
current_line: CurrentLine,
text: S,
) -> Result<CurrentLine> {
Expand All @@ -113,14 +113,16 @@ pub fn write_styled_and_wrapped<W: Write, S: AsRef<str>>(
+ current_line
.trailing_space
.as_ref()
.map_or(0, |s| display_width(s.as_ref()));
.map_or(0, |s| display_width(s.as_ref()) as u16);

// If the current line is not empty and we can't even add the first first word of the text to it
// then lets finish the line and start over. If the current line is empty the word simply doesn't
// fit into the terminal size so we must print it anyway.
if 0 < current_line.length && max_width < current_width + display_width(first_word) {
if 0 < current_line.length
&& max_width < current_width + display_width(first_word) as u16
{
writeln!(writer)?;
write_indent(writer, indent as u16)?;
write_indent(writer, indent)?;
return write_styled_and_wrapped(
writer,
capabilities,
Expand All @@ -146,7 +148,7 @@ pub fn write_styled_and_wrapped<W: Write, S: AsRef<str>>(
Ok(current_line)
}
Some((first_line, tails)) => {
let mut buffer = String::with_capacity(max_width);
let mut buffer = String::with_capacity(max_width as usize);

// Finish the current line
let new_current_line = match first_line.split_last() {
Expand All @@ -164,7 +166,7 @@ pub fn write_styled_and_wrapped<W: Write, S: AsRef<str>>(
}
buffer.push_str(last.word);
let length =
current_line.length + textwrap::core::display_width(&buffer);
current_line.length + textwrap::core::display_width(&buffer) as u16;
write_styled(writer, capabilities, style, &buffer)?;
buffer.clear();
CurrentLine {
Expand Down Expand Up @@ -214,9 +216,9 @@ pub fn write_rule<W: Write>(
writer: &mut W,
capabilities: &TerminalCapabilities,
theme: &Theme,
length: usize,
length: u16,
) -> std::io::Result<()> {
let rule = "\u{2550}".repeat(length);
let rule = "\u{2550}".repeat(length as usize);
write_styled(
writer,
capabilities,
Expand All @@ -231,7 +233,7 @@ pub fn write_code_block_border<W: Write>(
capabilities: &TerminalCapabilities,
terminal_size: &TerminalSize,
) -> std::io::Result<()> {
let separator = "\u{2500}".repeat(terminal_size.columns.min(20));
let separator = "\u{2500}".repeat(terminal_size.columns.min(20) as usize);
write_styled(
writer,
capabilities,
Expand Down
2 changes: 1 addition & 1 deletion pulldown-cmark-mdcat/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use mime::Mime;
use url::Url;

mod file;
mod image;
pub(crate) mod image;

pub(crate) mod svg;

Expand Down
34 changes: 33 additions & 1 deletion pulldown-cmark-mdcat/src/resources/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,38 @@ pub trait InlineImageProtocol {
writer: &mut dyn Write,
resource_handler: &dyn ResourceUrlHandler,
url: &Url,
terminal_size: &TerminalSize,
terminal_size: TerminalSize,
) -> std::io::Result<()>;
}

/// Downsize an image to the given terminal size.
///
/// If the `image` is larger than the amount of columns in the given terminal `size` attempt to
/// downsize the image to fit into the given columns.
///
/// Return the downsized image if `image` was larger than the column limit and `size` defined the
/// terminal size in pixels.
///
/// Return `None` if `size` does not specify the cell size, or if `image` is already smaller than
/// the column limit.
#[cfg(feature = "image-processing")]
pub fn downsize_to_columns(
image: &image::DynamicImage,
size: TerminalSize,
) -> Option<image::DynamicImage> {
use image::{imageops::FilterType, GenericImageView};
use tracing::{event, Level};
let win_size = size.pixels?;
event!(
Level::DEBUG,
"Terminal size {:?}; image is {:?}",
size,
image.dimensions()
);
let (image_width, _) = image.dimensions();
if win_size.x < image_width {
Some(image.resize(win_size.x, win_size.y, FilterType::Nearest))
} else {
None
}
}
2 changes: 1 addition & 1 deletion pulldown-cmark-mdcat/src/terminal/capabilities/iterm2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl InlineImageProtocol for ITerm2 {
writer: &mut dyn Write,
resource_handler: &dyn ResourceUrlHandler,
url: &url::Url,
_terminal_size: &crate::TerminalSize,
_terminal_size: crate::TerminalSize,
) -> Result<()> {
let mime_data = resource_handler.read_resource(url)?;
event!(
Expand Down
Loading