Allow alpha palettes in grayscale mode.

This commit is contained in:
Matt Dawson 2020-05-09 17:15:33 -07:00
parent 7e83dbb92e
commit c45ab418d4
2 changed files with 20 additions and 11 deletions

View File

@ -579,7 +579,7 @@ inline bool pixel_to_binary(int bpp, uint32_t pixel) {
* @param other_x_end End x pixel (exclusive) location in source/mask image. * @param other_x_end End x pixel (exclusive) location in source/mask image.
* @param over_x_scale Scale from other scale to image scale. * @param over_x_scale Scale from other scale to image scale.
*/ */
static void int_generate_cache_line_grayscale(uint16_t *cache_line, int alpha, uint8_t *other_row_ptr, int other_bpp, void *mask_row_ptr, int mask_bpp, int other_x_start, int other_x_end, float over_xscale) static void int_generate_cache_line_grayscale(uint16_t *cache_line, int alpha, uint8_t *other_row_ptr, int other_bpp, void *mask_row_ptr, int mask_bpp, int other_x_start, int other_x_end, float over_xscale, const uint8_t *alpha_palette)
{ {
for (int i = 0, x = other_x_start; x < other_x_end; x++, i++) { for (int i = 0, x = other_x_start; x < other_x_end; x++, i++) {
float other_x_float = (x + 0.5) * over_xscale; float other_x_float = (x + 0.5) * over_xscale;
@ -594,8 +594,16 @@ static void int_generate_cache_line_grayscale(uint16_t *cache_line, int alpha, u
uint32_t alpha1 = mask1 ? (alpha - weight_x) : 0; uint32_t alpha1 = mask1 ? (alpha - weight_x) : 0;
uint32_t alpha2 = mask2 ? weight_x : 0; uint32_t alpha2 = mask2 ? weight_x : 0;
uint32_t other_pixel1 = safe_map_pixel(IMAGE_BPP_GRAYSCALE, other_bpp, imlib_get_pixel_fast(other_bpp, other_row_ptr, other_x)) * alpha1; uint32_t other_pixel1 = safe_map_pixel(IMAGE_BPP_GRAYSCALE, other_bpp, imlib_get_pixel_fast(other_bpp, other_row_ptr, other_x));
uint32_t other_pixel2 = safe_map_pixel(IMAGE_BPP_GRAYSCALE, other_bpp, imlib_get_pixel_fast(other_bpp, other_row_ptr, other_x + 1)) * alpha2; uint32_t other_pixel2 = safe_map_pixel(IMAGE_BPP_GRAYSCALE, other_bpp, imlib_get_pixel_fast(other_bpp, other_row_ptr, other_x + 1));
if (alpha_palette) {
alpha1 = alpha1 * alpha_palette[other_pixel1] >> 8;
alpha2 = alpha2 * alpha_palette[other_pixel2] >> 8;
}
other_pixel1 *= alpha1;
other_pixel2 *= alpha2;
// Image alpha is the remaining alpha after applying other alpha // Image alpha is the remaining alpha after applying other alpha
uint32_t img_alpha = 256 - (alpha1 + alpha2); uint32_t img_alpha = 256 - (alpha1 + alpha2);
@ -755,7 +763,7 @@ void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float
uint8_t *other_row_ptr = imlib_compute_row_ptr(other, temp_other_y); uint8_t *other_row_ptr = imlib_compute_row_ptr(other, temp_other_y);
void *mask_row_ptr = mask ? imlib_compute_row_ptr(mask, temp_other_y) : NULL; void *mask_row_ptr = mask ? imlib_compute_row_ptr(mask, temp_other_y) : NULL;
int_generate_cache_line_grayscale(cache_line_bottom, alpha, other_row_ptr, other_bpp, mask_row_ptr, mask_bpp, other_x_start, other_x_end, over_xscale); int_generate_cache_line_grayscale(cache_line_bottom, alpha, other_row_ptr, other_bpp, mask_row_ptr, mask_bpp, other_x_start, other_x_end, over_xscale, alpha_palette);
// Used to detect when other starts rendering from the next line // Used to detect when other starts rendering from the next line
int last_other_y = -1; int last_other_y = -1;
@ -785,7 +793,7 @@ void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float
// And generate a new y+1 // And generate a new y+1
other_row_ptr = imlib_compute_row_ptr(other, other_y + 1); other_row_ptr = imlib_compute_row_ptr(other, other_y + 1);
mask_row_ptr = mask ? imlib_compute_row_ptr(mask, other_y + 1) : NULL; mask_row_ptr = mask ? imlib_compute_row_ptr(mask, other_y + 1) : NULL;
int_generate_cache_line_grayscale(cache_line_bottom, alpha, other_row_ptr, other_bpp, mask_row_ptr, mask_bpp, other_x_start, other_x_end, over_xscale); int_generate_cache_line_grayscale(cache_line_bottom, alpha, other_row_ptr, other_bpp, mask_row_ptr, mask_bpp, other_x_start, other_x_end, over_xscale, alpha_palette);
} }
// Draw the line to img // Draw the line to img
@ -946,13 +954,13 @@ void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float
float other_y_float = y * over_yscale; float other_y_float = y * over_yscale;
int other_y = fast_floorf(other_y_float); int other_y = fast_floorf(other_y_float);
uint16_t *other_row_ptr = imlib_compute_row_ptr(other, other_y); uint16_t *other_row_ptr = imlib_compute_row_ptr(other, other_y);
for (int x = other_x_start; x < other_x_end; x++) { for (int x = other_x_start; x < other_x_end; x++) {
int other_x = fast_floorf(x * over_xscale); int other_x = fast_floorf(x * over_xscale);
if (!mask || image_get_mask_pixel(mask, other_x, other_y)) { if (!mask || image_get_mask_pixel(mask, other_x, other_y)) {
uint32_t result_pixel = imlib_get_pixel_fast(other_bpp, other_row_ptr, other_x); uint32_t result_pixel = imlib_get_pixel_fast(other_bpp, other_row_ptr, other_x);
if (alpha_palette) { if (alpha_palette) {
uint32_t temp_alpha = (alpha * alpha_palette[result_pixel]) >> 8; uint32_t temp_alpha = (alpha * alpha_palette[result_pixel]) >> 8;

View File

@ -1964,6 +1964,10 @@ STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t
} }
} }
if (color_palette && arg_img->bpp != IMAGE_BPP_RGB565) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palettes must be used with color images!"));
}
const uint8_t *alpha_palette = NULL; const uint8_t *alpha_palette = NULL;
{ {
image_t *arg_alpha_palette = py_helper_keyword_to_image_mutable_alpha_palette(n_args, args, offset + 5, kw_args); image_t *arg_alpha_palette = py_helper_keyword_to_image_mutable_alpha_palette(n_args, args, offset + 5, kw_args);
@ -1972,15 +1976,12 @@ STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t
if (arg_other->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Can only specify an alpha palette when passing a grayscale image!")); if (arg_other->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Can only specify an alpha palette when passing a grayscale image!"));
if (arg_alpha_palette->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be an grayscale format image!")); if (arg_alpha_palette->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be an grayscale format image!"));
if ((arg_alpha_palette->w * arg_alpha_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette image must have 256 pixels!")); if ((arg_alpha_palette->w * arg_alpha_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette image must have 256 pixels!"));
if (arg_img->bpp != IMAGE_BPP_GRAYSCALE && arg_img->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palettes must be used with color images!"));
alpha_palette = (uint8_t*)arg_alpha_palette->data; alpha_palette = (uint8_t*)arg_alpha_palette->data;
} }
} }
if ((color_palette || alpha_palette) && arg_img->bpp != IMAGE_BPP_RGB565) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Palettes must be used with color images!"));
}
image_hint_t hint = image_hint_t hint =
py_helper_keyword_int(n_args, args, offset + 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hint), 0); py_helper_keyword_int(n_args, args, offset + 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hint), 0);