Return a bitmap directly from dither_image. This removes the need to

deal with n-bit encodings at all in DHGRScreen
This commit is contained in:
kris 2021-11-02 14:42:00 +00:00
parent b7e8c69f64
commit 809b975e6e
3 changed files with 18 additions and 38 deletions

View File

@ -85,9 +85,9 @@ def main():
gamma=args.gamma_correct)).astype(np.float32) / 255
dither = dither_pattern.PATTERNS[args.dither]()
output_nbit, _ = dither_pyx.dither_image(
bitmap = dither_pyx.dither_image(
screen, rgb, dither, lookahead, args.verbose, rgb_to_cam16)
bitmap = screen.pack(output_nbit)
screen.pack(bitmap)
# Show output image by rendering in target palette
output_palette_name = args.show_palette or args.palette

View File

@ -217,6 +217,19 @@ cdef void apply(Dither* dither, int x_res, int y_res, int x, int y, float[:,:,::
image[i,j,k] = clip(image[i,j,k] + error_fraction * quant_error[k], 0, 1)
@cython.boundscheck(False)
@cython.wraparound(False)
cdef image_nbit_to_bitmap(
(unsigned char)[:, ::1] image_nbit, unsigned int x_res, unsigned int y_res, unsigned char palette_depth):
cdef unsigned int x, y
bitmap = np.zeros((y_res, x_res), dtype=bool)
for y in range(y_res):
for x in range(x_res):
# MSB of each array element is the pixel state at (x, y)
bitmap[y, x] = image_nbit[y, x] >> (palette_depth - 1)
return bitmap
# Dither a source image
#
# Args:
@ -303,4 +316,4 @@ def dither_image(
image_rgb[y, x, i] = output_pixel_rgb[i]
free(cdither.pattern)
return image_nbit, np.array(image_rgb)
return image_nbit_to_bitmap(image_nbit, xres, yres, palette_depth)

View File

@ -23,16 +23,8 @@ class DHGRScreen:
return 1024 * c + 128 * b + 40 * a
def _image_to_bitmap(self, image_nbit: np.ndarray) -> np.ndarray:
"""Converts n-bit image to 2-bit image bitmap.
Each n-bit colour value maps to a sliding window of n successive pixels.
"""
raise NotImplementedError
def pack(self, image: np.ndarray):
def pack(self, bitmap: np.ndarray):
"""Packs an image into memory format (8k AUX + 8K MAIN)."""
bitmap = self._image_to_bitmap(image)
# The DHGR display encodes 7 pixels across interleaved 4-byte sequences
# of AUX and MAIN memory, as follows:
# PBBBAAAA PDDCCCCB PFEEEEDD PGGGGFFF
@ -55,8 +47,7 @@ class DHGRScreen:
addr = self.y_to_base_addr(y)
self.aux[addr:addr + 40] = aux_col[y, :]
self.main[addr:addr + 40] = main_col[y, :]
return bitmap
return
def bitmap_to_image_rgb(self, bitmap: np.ndarray) -> np.ndarray:
"""Convert our 2-bit bitmap image into a RGB image.
@ -76,34 +67,10 @@ class DHGRScreen:
return image_rgb
class DHGR560Screen(DHGRScreen):
"""DHGR screen including colour fringing and 4 pixel chroma bleed."""
def _image_to_bitmap(self, image_nbit: np.ndarray) -> np.ndarray:
bitmap = np.zeros((self.Y_RES, self.X_RES), dtype=np.bool)
for y in range(self.Y_RES):
for x in range(self.X_RES):
pixel = image_nbit[y, x]
dots = self.palette.DOTS[pixel]
phase = x % 4
bitmap[y, x] = dots[phase]
return bitmap
# TODO: refactor to share implementation with DHGR560Screen
class DHGR560NTSCScreen(DHGRScreen):
"""DHGR screen including colour fringing and 8 pixel chroma bleed."""
# XXX image_nbit is MSB (x, ... x-7) LSB pixel values?
def _image_to_bitmap(self, image_nbit: np.ndarray) -> np.ndarray:
bitmap = np.zeros((self.Y_RES, self.X_RES), dtype=np.bool)
for y in range(self.Y_RES):
for x in range(self.X_RES):
pixel = image_nbit[y, x]
bitmap[y, x] = pixel >> 7
return bitmap
# 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.