From b63fd81c07de1eade11724fa1429862e06c5d3f8 Mon Sep 17 00:00:00 2001 From: kris Date: Tue, 2 Nov 2021 15:23:23 +0000 Subject: [PATCH] Unify DHGRScreen implementations --- convert.py | 12 +++--------- ntsc_colours.py | 2 +- palette.py | 13 ------------- screen.py | 28 +++------------------------- 4 files changed, 7 insertions(+), 48 deletions(-) diff --git a/convert.py b/convert.py index 4c9e839..9ba29f0 100644 --- a/convert.py +++ b/convert.py @@ -62,11 +62,7 @@ def main(): args = parser.parse_args() palette = palette_py.PALETTES[args.palette]() - if args.palette == "ntsc": - # TODO: palette depth should be controlled by Palette not Screen - screen = screen_py.DHGR560NTSCScreen(palette) - else: - screen = screen_py.DHGR560Screen(palette) + screen = screen_py.DHGRScreen(palette) if args.lookahead < 1: parser.error('--lookahead must be at least 1') lookahead = args.lookahead @@ -92,10 +88,8 @@ def main(): # Show output image by rendering in target palette output_palette_name = args.show_palette or args.palette output_palette = palette_py.PALETTES[output_palette_name]() - if output_palette_name == "ntsc": - output_screen = screen_py.DHGR560NTSCScreen(output_palette) - else: - output_screen = screen_py.DHGR560Screen(output_palette) + output_screen = screen_py.DHGRScreen(output_palette) + # TODO: if output_palette_name == "ntsc" show bitmap_to_image_ntsc instead output_rgb = output_screen.bitmap_to_image_rgb(bitmap) out_image = Image.fromarray(image_py.linear_to_srgb(output_rgb).astype( np.uint8)) diff --git a/ntsc_colours.py b/ntsc_colours.py index b926766..101b71c 100644 --- a/ntsc_colours.py +++ b/ntsc_colours.py @@ -31,7 +31,7 @@ def main(): bitmap[0, j:j + 8] = bits8 # bitmap_to_ntsc produces 3 output pixels for each DHGR input - ntsc = s.bitmap_to_ntsc(bitmap) + ntsc = s.bitmap_to_image_ntsc(bitmap) last_colour = ntsc[0, 3 * (j + 8) - 1, :] colours[(bits, j - ntsc_shift)] = last_colour unique.add(tuple(last_colour)) diff --git a/palette.py b/palette.py index 7a3a12e..17d55a0 100644 --- a/palette.py +++ b/palette.py @@ -10,7 +10,6 @@ class Palette: SRGB = None RGB = {} CAM16UCS = {} - # DOTS_TO_INDEX = {} # How many successive screen pixels are used to compute output pixel # palette index. @@ -26,18 +25,6 @@ class Palette: self.CAM16UCS[k] = colour.convert( v / 255, "sRGB", "CAM16UCS").astype(np.float32) - # # Maps palette values to screen dots. Note that these are the same as - # # the binary index values in reverse order. - # _DOTS = {} - # for i in range(1 << self.PALETTE_DEPTH): - # _DOTS[i] = tuple( - # bool(i & (1 << j)) for j in range(self.PALETTE_DEPTH)) - # - # # Reverse mapping from screen dots to palette index. - # self.DOTS_TO_INDEX = {} - # for k, v in _DOTS.items(): - # self.DOTS_TO_INDEX[v] = k - def pixels_to_idx(self, pixels: np.array) -> int: return np.packbits( # numpy uses big-endian representation which is the opposite diff --git a/screen.py b/screen.py index 6ac9816..58322d5 100644 --- a/screen.py +++ b/screen.py @@ -52,29 +52,7 @@ class DHGRScreen: def bitmap_to_image_rgb(self, bitmap: np.ndarray) -> np.ndarray: """Convert our 2-bit bitmap image into a RGB image. - Colour at every pixel is determined by the value of a 4-bit sliding - window indexed by x % 4, which gives the index into our 16-colour RGB - palette. - """ - image_rgb = np.empty((self.Y_RES, self.X_RES, 3), - dtype=np.uint8) - for y in range(self.Y_RES): - pixel = [False, False, False, False] - for x in range(self.X_RES): - pixel[x % 4] = bitmap[y, x] - dots = self.palette.DOTS_TO_INDEX[tuple(pixel)] - image_rgb[y, x, :] = self.palette.RGB[dots] - return image_rgb - - -# TODO: refactor to share implementation with DHGR560Screen -class DHGR560NTSCScreen(DHGRScreen): - """DHGR screen including colour fringing and 8 pixel chroma bleed.""" - - # TODO: unify with parent - def bitmap_to_image_rgb(self, bitmap: np.ndarray) -> np.ndarray: - """Convert our 2-bit bitmap image into a RGB image. - + XXX Colour at every pixel is determined by the value of a 8-bit sliding window indexed by x % 4, which gives the index into our 256-colour RGB palette. @@ -83,8 +61,8 @@ class DHGR560NTSCScreen(DHGRScreen): for y in range(self.Y_RES): pixels = [False] * self.palette.PALETTE_DEPTH for x in range(self.X_RES): + # Maintain a sliding window of pixels of width PALETTE_DEPTH pixels = pixels[1:] + [bitmap[y, x]] - # dots = self.palette.DOTS_TO_INDEX[tuple(pixel)] image_rgb[y, x, :] = self.palette.RGB[ self.palette.pixels_to_idx( np.array(pixels, dtype=bool)), x % 4] @@ -106,7 +84,7 @@ class DHGR560NTSCScreen(DHGRScreen): return 1 if line[pos] else 0 - def bitmap_to_ntsc(self, bitmap: np.ndarray) -> np.ndarray: + def bitmap_to_image_ntsc(self, bitmap: np.ndarray) -> np.ndarray: y_width = 12 u_width = 24 v_width = 24