From c0829f16d548a5c9b7c080f49544abb554752b84 Mon Sep 17 00:00:00 2001 From: Liquid Cat Date: Wed, 31 Jul 2024 15:33:03 +0100 Subject: [PATCH 1/2] factor out numpy float mode handling --- imgcat/imgcat.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/imgcat/imgcat.py b/imgcat/imgcat.py index e192667..2915b5b 100644 --- a/imgcat/imgcat.py +++ b/imgcat/imgcat.py @@ -98,14 +98,13 @@ def to_content_buf(data: Any) -> bytes: # numpy ndarray: convert to png import numpy im: 'numpy.ndarray' = data + if im.dtype.kind == 'f': + im = (im * 255).astype('uint8') if len(im.shape) == 2: mode = 'L' # 8-bit pixels, grayscale - im = im.astype(sys.modules['numpy'].uint8) elif len(im.shape) == 3 and im.shape[2] in (1, 3, 4): # (H, W, C) format mode = None # RGB/RGBA - if im.dtype.kind == 'f': - im = (im * 255).astype('uint8') if im.shape[2] == 1: mode = 'L' # 8-bit grayscale im = numpy.squeeze(im, axis=2) @@ -113,8 +112,6 @@ def to_content_buf(data: Any) -> bytes: # (C, H, W) format mode = None # RGB/RGBA im = numpy.rollaxis(im, 0, 3) # CHW -> HWC - if im.dtype.kind == 'f': - im = (im * 255).astype('uint8') if im.shape[2] == 1: mode = 'L' # 8-bit grayscale im = numpy.squeeze(im, axis=2) From 96c5a7c2e23330521b4c96c35f8f6dcc1bea0db2 Mon Sep 17 00:00:00 2001 From: Liquid Cat Date: Wed, 31 Jul 2024 15:53:40 +0100 Subject: [PATCH 2/2] Fix numpy mode to use full range Old formula only used 255 at exactly 1.0, but used 0 for 1/255 of the space. New formula uses both 0 and 255 (and every other number) for exactly 1/256 of the space. If starting with a float between 0 and 1, this is probably the intent. --- imgcat/imgcat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgcat/imgcat.py b/imgcat/imgcat.py index 2915b5b..9fb63fb 100644 --- a/imgcat/imgcat.py +++ b/imgcat/imgcat.py @@ -99,7 +99,8 @@ def to_content_buf(data: Any) -> bytes: import numpy im: 'numpy.ndarray' = data if im.dtype.kind == 'f': - im = (im * 255).astype('uint8') + # https://stackoverflow.com/a/66862750 + im = (im * 256).clip(0, 255).astype('uint8') if len(im.shape) == 2: mode = 'L' # 8-bit pixels, grayscale elif len(im.shape) == 3 and im.shape[2] in (1, 3, 4):