From 4d27055ab1729cb93bbf4bb4531a0157b8cf513f Mon Sep 17 00:00:00 2001 From: AnonymouX47 Date: Thu, 1 Jun 2023 18:08:43 +0100 Subject: [PATCH] fix: Fix jagged edges with `LINES` render method - Fix: Disable payload size optimization for `LINES` render method of kitty and iterm2 render styles. The optimization results in slant/curved edges not lining up across lines (amongst other artifacts observed on Konsole) supposedly because the terminal emulator resizes each line separately. --- src/term_image/image/common.py | 2 +- src/term_image/image/iterm2.py | 19 +++++++++++++++++-- src/term_image/image/kitty.py | 16 ++++++++++++++-- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/term_image/image/common.py b/src/term_image/image/common.py index ac64b6be..c39e8089 100644 --- a/src/term_image/image/common.py +++ b/src/term_image/image/common.py @@ -1914,7 +1914,7 @@ def __new__( ) return super().__new__(cls) - def _get_minimal_render_size(self, *, adjust: bool) -> Tuple[int, int]: + def _get_minimal_render_size(self, *, adjust: bool = False) -> Tuple[int, int]: render_size = self._get_render_size() r_height = self.rendered_height width, height = ( diff --git a/src/term_image/image/iterm2.py b/src/term_image/image/iterm2.py index 434a8888..3c5d2222 100644 --- a/src/term_image/image/iterm2.py +++ b/src/term_image/image/iterm2.py @@ -556,11 +556,22 @@ def _render_image( mix: bool = False, compress: int = 4, ) -> str: + # NOTE: It's more efficient to write separate strings to the buffer separately + # than concatenate and write together. + # Using `width=`, `height=` and `preserveAspectRatio=0` ensures # that an image always occupies the correct amount of columns and lines even if # the cell size has changed when it's drawn. # Since we use `width` and `height` control data keys, there's no need - # upscaling an image on this end; ensures minimal payload. + # upscaling the image on this end to reduce payload. + # Anyways, this also implies that the image(s) have to be resized by the + # terminal emulator, thereby leaving various details of resizing in the hands + # of the terminal emulator such as the resampling method, etc. + # This particularly affects the LINES render method negatively, resulting in + # slant/curved edges not lining up across lines (amongst other artifacts + # observed on Konsole) supposedly because the terminal emulator resizes each + # line separately. + # Hence, this optimization is only used for the WHOLE render method. r_width, r_height = self.rendered_size render_method = (method or self._render_method).lower() @@ -632,7 +643,11 @@ def _render_image( ) ) - width, height = self._get_minimal_render_size(adjust=render_method == LINES) + width, height = ( + self._get_minimal_render_size() + if render_method == WHOLE + else self._get_render_size() + ) if ( # Read directly from file when possible and reasonable self.read_from_file diff --git a/src/term_image/image/kitty.py b/src/term_image/image/kitty.py index db58fe8d..51b5ccea 100644 --- a/src/term_image/image/kitty.py +++ b/src/term_image/image/kitty.py @@ -421,11 +421,23 @@ def _render_image( # Using `c` and `r` ensures that an image always occupies the correct amount # of columns and lines even if the cell size has changed when it's drawn. # Since we use `c` and `r` control data keys, there's no need upscaling the - # image on this end; ensures minimal payload. + # image on this end to reduce payload. + # Anyways, this also implies that the image(s) have to be resized by the + # terminal emulator, thereby leaving various details of resizing in the hands + # of the terminal emulator such as the resampling method, etc. + # This particularly affects the LINES render method negatively, resulting in + # slant/curved edges not lining up across lines (amongst other artifacts + # observed on Konsole) supposedly because the terminal emulator resizes each + # line separately. + # Hence, this optimization is only used for the WHOLE render method. render_method = (method or self._render_method).lower() r_width, r_height = self.rendered_size - width, height = self._get_minimal_render_size(adjust=render_method == LINES) + width, height = ( + self._get_minimal_render_size() + if render_method == WHOLE + else self._get_render_size() + ) frame_img = img if frame else None img = self._get_render_data(