From b1b55e1c758e8a15991a659cbfbf8c9608bb03af Mon Sep 17 00:00:00 2001 From: Liquid Cat Date: Wed, 31 Jul 2024 16:13:51 +0100 Subject: [PATCH 1/5] iterm2 -- only pass optional height if set --- imgcat/iterm2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgcat/iterm2.py b/imgcat/iterm2.py index 917edf4..800d51d 100644 --- a/imgcat/iterm2.py +++ b/imgcat/iterm2.py @@ -37,7 +37,8 @@ def _write_image(buf, fp, else: filename_bytes = filename.encode() fp.write(b';name=' + base64.b64encode(filename_bytes)) - fp.write(b';height=' + str(height).encode()) + if height: + fp.write(b';height=' + str(height).encode()) if width: fp.write(b';width=' + str(width).encode()) if not preserve_aspect_ratio: From 35eb456d4bfb46ab5f99a47bce52557b0ae1954e Mon Sep 17 00:00:00 2001 From: Liquid Cat Date: Wed, 31 Jul 2024 16:14:51 +0100 Subject: [PATCH 2/5] add no-preserve-aspect argument --- imgcat/imgcat.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgcat/imgcat.py b/imgcat/imgcat.py index e192667..02c5d09 100644 --- a/imgcat/imgcat.py +++ b/imgcat/imgcat.py @@ -237,6 +237,8 @@ def main(): help='The number of rows (in terminal) for displaying images.') parser.add_argument('--width', default=None, type=int, help='The number of columns (in terminal) for displaying images.') + parser.add_argument('--no-preserve-aspect', action='store_true', + help='Allow reshaping of image.') parser.add_argument('-v', '--version', action='version', version='python-imgcat %s' % __version__) args = parser.parse_args() @@ -246,6 +248,7 @@ def main(): kwargs['height'] = args.height if args.width: kwargs['width'] = args.width + kwargs['preserve_aspect_ratio'] = not args.no_preserve_aspect # read from stdin? if not sys.stdin.isatty(): From d3d23d3a42dc0b775c2ed0fd18f902ca109953b4 Mon Sep 17 00:00:00 2001 From: Liquid Cat Date: Wed, 31 Jul 2024 16:19:58 +0100 Subject: [PATCH 3/5] CLI -- allow passing of full range of width/height values; add help --- imgcat/imgcat.py | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/imgcat/imgcat.py b/imgcat/imgcat.py index 02c5d09..5319586 100644 --- a/imgcat/imgcat.py +++ b/imgcat/imgcat.py @@ -12,6 +12,21 @@ import sys from urllib.request import urlopen +HELP_EPILOG = """ +SIZES + +Sizes can be specified as (N is any integer): + * N: Number of character cells. + * Npx: Pixels. + * N%: Percentage of session's size. + * auto: Use the original dimension, but allow scaling above this (terminal dependent?). + * default: Let the terminal decide. + * v0.5: Height only; use smaller of terminal height or original pixels/24 rows. + +Where aspect is preserved, the smaller dimension will be used. +The scaling is performed by your terminal, except in v0.5 mode. On Konsole, the image will be scaled to the largest size which fits the constraints, except that 'auto' is ignored. +The defaults are --width=default --height=v0.5 +""" if TYPE_CHECKING: import matplotlib.figure # type: ignore @@ -199,7 +214,7 @@ def imgcat(data: Any, filename=None, if len(buf) == 0: raise ValueError("Empty buffer") - if height is None: + if height == 'v0.5': im_width, im_height = get_image_shape(buf) if im_height: assert pixels_per_line > 0 @@ -217,12 +232,24 @@ def imgcat(data: Any, filename=None, # image height unavailable, fallback? height = 10 + if width == 'v0.5': + raise ValueError("There is no legacy fallback for width") + from . import iterm2 iterm2._write_image(buf, fp, filename=filename, width=width, height=height, preserve_aspect_ratio=preserve_aspect_ratio) +def parse_size(s): + if s in ("v0.5", "auto"): + return s + if s == 'default': + return None + for suffix in ("%", "px", ""): + if s.endswith(suffix): + return f"{int(s[:-len(suffix)])}{suffix}" + def main(): import argparse try: @@ -230,13 +257,17 @@ def main(): except ImportError: __version__ = 'N/A' - parser = argparse.ArgumentParser(description=__doc__) + parser = argparse.ArgumentParser( + description=__doc__, + epilog=HELP_EPILOG, + formatter_class=argparse.RawTextHelpFormatter, + ) parser.add_argument('input', nargs='*', type=str, help='Path to the images.') - parser.add_argument('--height', default=None, type=int, - help='The number of rows (in terminal) for displaying images.') - parser.add_argument('--width', default=None, type=int, - help='The number of columns (in terminal) for displaying images.') + parser.add_argument('--height', default='v0.5', type=parse_size, + help='Height of image.') + parser.add_argument('--width', default=None, type=parse_size, + help='Width of image.') parser.add_argument('--no-preserve-aspect', action='store_true', help='Allow reshaping of image.') parser.add_argument('-v', '--version', action='version', From 489b2cffe81199dcf6c44e6d8a38c7d869e0f416 Mon Sep 17 00:00:00 2001 From: Liquid Cat Date: Wed, 31 Jul 2024 16:20:51 +0100 Subject: [PATCH 4/5] CLI/API -- support "original" for width/height --- imgcat/imgcat.py | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/imgcat/imgcat.py b/imgcat/imgcat.py index 5319586..dac839d 100644 --- a/imgcat/imgcat.py +++ b/imgcat/imgcat.py @@ -20,6 +20,7 @@ * Npx: Pixels. * N%: Percentage of session's size. * auto: Use the original dimension, but allow scaling above this (terminal dependent?). + * original: Use the original dimension. * default: Let the terminal decide. * v0.5: Height only; use smaller of terminal height or original pixels/24 rows. @@ -214,23 +215,28 @@ def imgcat(data: Any, filename=None, if len(buf) == 0: raise ValueError("Empty buffer") - if height == 'v0.5': + if height == 'v0.5' or 'original' in (height, width): im_width, im_height = get_image_shape(buf) - if im_height: - assert pixels_per_line > 0 - height = (im_height + (pixels_per_line - 1)) // pixels_per_line - - # automatically limit height to the current tty, - # otherwise the image will be just erased - try: - tty_height, _ = get_tty_size() - height = max(1, min(height, tty_height - 9)) - except OSError: - # may not be a terminal - pass - else: - # image height unavailable, fallback? - height = 10 + if height == 'v0.5': + if im_height: + assert pixels_per_line > 0 + height = (im_height + (pixels_per_line - 1)) // pixels_per_line + + # automatically limit height to the current tty, + # otherwise the image will be just erased + try: + tty_height, _ = get_tty_size() + height = max(1, min(height, tty_height - 9)) + except OSError: + # may not be a terminal + pass + else: + # image height unavailable, fallback? + height = 10 + elif height == 'original': + height = f'{im_height}px' if im_height else 'auto' + if width == 'original': + width = f'{im_width}px' if im_width else 'auto' if width == 'v0.5': raise ValueError("There is no legacy fallback for width") @@ -242,7 +248,7 @@ def imgcat(data: Any, filename=None, def parse_size(s): - if s in ("v0.5", "auto"): + if s in ("v0.5", "auto", "original"): return s if s == 'default': return None From 792999a76ac83e90e6b94cf906fdf6bf6782543a Mon Sep 17 00:00:00 2001 From: Liquid Cat Date: Wed, 31 Jul 2024 16:21:17 +0100 Subject: [PATCH 5/5] CLI -- change defaults to --width=100% --height=original --- imgcat/imgcat.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgcat/imgcat.py b/imgcat/imgcat.py index dac839d..6c0ab45 100644 --- a/imgcat/imgcat.py +++ b/imgcat/imgcat.py @@ -26,7 +26,7 @@ Where aspect is preserved, the smaller dimension will be used. The scaling is performed by your terminal, except in v0.5 mode. On Konsole, the image will be scaled to the largest size which fits the constraints, except that 'auto' is ignored. -The defaults are --width=default --height=v0.5 +The defaults are --width=100% --height=original """ if TYPE_CHECKING: @@ -270,9 +270,9 @@ def main(): ) parser.add_argument('input', nargs='*', type=str, help='Path to the images.') - parser.add_argument('--height', default='v0.5', type=parse_size, + parser.add_argument('--height', default='original', type=parse_size, help='Height of image.') - parser.add_argument('--width', default=None, type=parse_size, + parser.add_argument('--width', default='100%', type=parse_size, help='Width of image.') parser.add_argument('--no-preserve-aspect', action='store_true', help='Allow reshaping of image.')