From db4449ea2614e3d0c27ed727b9ebff708ae92f17 Mon Sep 17 00:00:00 2001 From: kris Date: Thu, 2 Feb 2023 22:17:56 +0000 Subject: [PATCH] Working version --- dither_hgr.pyx | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/dither_hgr.pyx b/dither_hgr.pyx index 407d52e..eca9a93 100644 --- a/dither_hgr.pyx +++ b/dither_hgr.pyx @@ -108,7 +108,7 @@ cdef unsigned int compute_fat_pixels(unsigned int screen_byte, unsigned char las # cdef int dither_lookahead(Dither* dither, float[:, :, ::1] palette_cam16, float[:, :, ::1] palette_rgb, float[:, :, ::1] image_rgb, int x, int y, int lookahead, unsigned char last_pixels, - int x_res, float[:,::1] rgb_to_cam16ucs, unsigned char palette_depth) nogil: + int x_res, float[:,::1] rgb_to_cam16ucs, unsigned char palette_depth, unsigned char last_byte): cdef int candidate_pixels, i, j, fat_pixels cdef float[3] quant_error cdef int best @@ -119,12 +119,14 @@ cdef int dither_lookahead(Dither* dither, float[:, :, ::1] palette_cam16, float[ cdef float[::1] lah_cam16ucs # Don't bother dithering past the lookahead horizon or edge of screen. - cdef int xxr = min(x + 14, x_res) # XXX + cdef int xxr = min(x + 15, x_res) # XXX cdef int lah_shape1 = xxr - x cdef int lah_shape2 = 3 cdef float *lah_image_rgb = malloc(lah_shape1 * lah_shape2 * sizeof(float)) + cdef float penalty + # For each 2**lookahead possibilities for the on/off state of the next lookahead pixels, apply error diffusion # and compute the total squared error to the source image. Since we only have two possible colours for each # given pixel (dependent on the state already chosen for pixels to the left), we need to look beyond local minima. @@ -139,7 +141,6 @@ cdef int dither_lookahead(Dither* dither, float[:, :, ::1] palette_cam16, float[ total_error = 0 fat_pixels = compute_fat_pixels(candidate_pixels, last_pixels) - # Apply dithering to lookahead horizon or edge of screen for i in range(xxr - x): xl = dither_bounds_xl(dither, i) @@ -155,12 +156,19 @@ cdef int dither_lookahead(Dither* dither, float[:, :, ::1] palette_cam16, float[ # choices, in order to compute the total error. for j in range(3): quant_error[j] = lah_image_rgb[i * lah_shape2 + j] - palette_rgb[next_pixels, phase, j] + apply_one_line(dither, xl, xr, i, lah_image_rgb, lah_shape2, quant_error) lah_cam16ucs = common.convert_rgb_to_cam16ucs( rgb_to_cam16ucs, lah_image_rgb[i*lah_shape2], lah_image_rgb[i*lah_shape2+1], lah_image_rgb[i*lah_shape2+2]) - total_error += common.colour_distance_squared(lah_cam16ucs, palette_cam16[next_pixels, phase]) + + #if (last_byte & 0x40) and (candidate_pixels & 0x80) != (last_byte & 0x80): + # penalty = 1.2 + #else: + # penalty = 1.0 + + total_error += common.colour_distance_squared(lah_cam16ucs, palette_cam16[next_pixels, phase]) * penalty if total_error >= best_error: # No need to continue @@ -170,6 +178,9 @@ cdef int dither_lookahead(Dither* dither, float[:, :, ::1] palette_cam16, float[ best_error = total_error best = candidate_pixels + #if penalty > 1: + # print("Mismatch at %d, %s %s" % (x, bin(last_byte), bin(best))) + free(lah_image_rgb) return best @@ -223,7 +234,8 @@ cdef void apply(Dither* dither, int x_res, int y_res, int x, int y, float[:,:,:: error_fraction = dither.pattern[(i - y) * dither.x_shape + j - x + dither.x_origin] for k in range(3): image[i,j,k] = common.clip(image[i,j,k] + error_fraction * quant_error[k], 0, 1) - + #if x % 14 == 13: + # return cdef image_nbit_to_bitmap( (unsigned char)[:, ::1] image_nbit, unsigned int x_res, unsigned int y_res, unsigned char palette_depth): @@ -295,6 +307,7 @@ def dither_image( cdef (unsigned char)[:, ::1] linear_bytemap = np.zeros((192, 40), dtype=np.uint8) cdef unsigned int fat_pixels + for y in range(yres): if verbose: print("%d/%d" % (y, yres)) @@ -307,19 +320,19 @@ def dither_image( # to the source image over the succeeding N pixels best_next_pixels = dither_lookahead( &cdither, palette_cam16, palette_rgb, image_rgb, x, y, lookahead, output_pixel_nbit, xres, - rgb_to_cam16ucs, palette_depth) + rgb_to_cam16ucs, palette_depth, best_next_pixels) linear_bytemap[y, x // 14] = best_next_pixels fat_pixels = compute_fat_pixels(best_next_pixels, output_pixel_nbit) - # print(y, x, best_next_pixels,bin(fat_pixels)) # Apply best choice for next 1 pixel output_pixel_nbit = shift_pixel_window( output_pixel_nbit, fat_pixels, shift_right_by=x%14 + 1, window_width=palette_depth) - # print(x, bin(output_pixel_nbit)) # Apply error diffusion from chosen output pixel value + for i in range(3): output_pixel_rgb[i] = palette_rgb[output_pixel_nbit, x % 4, i] quant_error[i] = image_rgb[y,x,i] - output_pixel_rgb[i] + apply(&cdither, xres, yres, x, y, image_rgb, quant_error) # Update image with our chosen image pixel