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

Commit

Permalink
Merge pull request #258 from swsnr/resize-images-to-columns
Browse files Browse the repository at this point in the history
Resize images to columns
  • Loading branch information
swsnr authored Apr 22, 2023
2 parents 747df9e + 549e245 commit ee4783a
Show file tree
Hide file tree
Showing 13 changed files with 259 additions and 171 deletions.
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

0 comments on commit ee4783a

Please sign in to comment.