aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Kangas2023-08-25 20:26:45 +0200
committerStefan Kangas2023-08-25 20:26:59 +0200
commiteb61bbacef76ff10b47008711529f8c0b18ea993 (patch)
tree5b253d6bc6b56ac651e86bf6080cbf5feb41fb1c /src
parentaaaee4ebe198d810a2e62a38bee49fc2ee2cfcbd (diff)
downloademacs-eb61bbacef76ff10b47008711529f8c0b18ea993.tar.gz
emacs-eb61bbacef76ff10b47008711529f8c0b18ea993.zip
Fix alpha blending for WebP images
* src/image.c (webp_load): Fix WebP transparency by doing manual alpha blending instead of naive masking. (Bug#59242)
Diffstat (limited to 'src')
-rw-r--r--src/image.c72
1 files changed, 38 insertions, 34 deletions
diff --git a/src/image.c b/src/image.c
index 7019bbf31be..70dd280b5dd 100644
--- a/src/image.c
+++ b/src/image.c
@@ -10450,22 +10450,36 @@ webp_load (struct frame *f, struct image *img)
10450 } 10450 }
10451 10451
10452 /* Create the x image and pixmap. */ 10452 /* Create the x image and pixmap. */
10453 Emacs_Pix_Container ximg, mask_img = NULL; 10453 Emacs_Pix_Container ximg;
10454 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, false)) 10454 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, false))
10455 goto webp_error2; 10455 goto webp_error2;
10456 10456
10457 /* Create an image and pixmap serving as mask if the WebP image 10457 /* Find the background to use if the WebP image contains an alpha
10458 contains an alpha channel. */ 10458 channel. */
10459 if (features.has_alpha 10459 Emacs_Color bg_color;
10460 && !image_create_x_image_and_pixmap (f, img, width, height, 1, 10460 if (features.has_alpha)
10461 &mask_img, true))
10462 { 10461 {
10463 image_destroy_x_image (ximg); 10462 Lisp_Object specified_bg
10464 image_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP); 10463 = image_spec_value (img->spec, QCbackground, NULL);
10465 goto webp_error2; 10464
10465 /* If the user specified a color, try to use it; if not, use the
10466 current frame background, ignoring any default background
10467 color set by the image. */
10468 if (STRINGP (specified_bg))
10469 FRAME_TERMINAL (f)->defined_color_hook (f,
10470 SSDATA (specified_bg),
10471 &bg_color,
10472 false,
10473 false);
10474 else
10475 FRAME_TERMINAL (f)->query_frame_background_color (f, &bg_color);
10476 bg_color.red >>= 8;
10477 bg_color.green >>= 8;
10478 bg_color.blue >>= 8;
10466 } 10479 }
10467 10480
10468 /* Fill the X image and mask from WebP data. */ 10481 /* Fill the X image from WebP data. */
10482
10469 init_color_table (); 10483 init_color_table ();
10470 10484
10471 img->corners[TOP_CORNER] = 0; 10485 img->corners[TOP_CORNER] = 0;
@@ -10480,21 +10494,21 @@ webp_load (struct frame *f, struct image *img)
10480 { 10494 {
10481 for (int x = 0; x < width; ++x) 10495 for (int x = 0; x < width; ++x)
10482 { 10496 {
10483 int r = *p++ << 8; 10497 int r, g, b;
10484 int g = *p++ << 8; 10498 /* The WebP alpha channel allows 256 levels of partial
10485 int b = *p++ << 8; 10499 transparency. Blend it with the background manually. */
10500 if (features.has_alpha || anim) {
10501 float a = (float) p[3] / UINT8_MAX;
10502 r = (int)(a * p[0] + (1.0 - a) * bg_color.red) << 8;
10503 g = (int)(a * p[1] + (1.0 - a) * bg_color.green) << 8;
10504 b = (int)(a * p[2] + (1.0 - a) * bg_color.blue) << 8;
10505 p += 4;
10506 } else {
10507 r = *p++ << 8;
10508 g = *p++ << 8;
10509 b = *p++ << 8;
10510 }
10486 PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, r, g, b)); 10511 PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, r, g, b));
10487
10488 /* An alpha channel associates variable transparency with an
10489 image. WebP allows up to 256 levels of partial transparency.
10490 We handle this like with PNG (which see), using the frame's
10491 background color to combine the image with. */
10492 if (features.has_alpha || anim)
10493 {
10494 if (mask_img)
10495 PUT_PIXEL (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
10496 ++p;
10497 }
10498 } 10512 }
10499 } 10513 }
10500 10514
@@ -10507,16 +10521,6 @@ webp_load (struct frame *f, struct image *img)
10507 /* Put ximg into the image. */ 10521 /* Put ximg into the image. */
10508 image_put_x_image (f, img, ximg, 0); 10522 image_put_x_image (f, img, ximg, 0);
10509 10523
10510 /* Same for the mask. */
10511 if (mask_img)
10512 {
10513 /* Fill in the background_transparent field while we have the
10514 mask handy. Casting avoids a GCC warning. */
10515 image_background_transparent (img, f, (Emacs_Pix_Context)mask_img);
10516
10517 image_put_x_image (f, img, mask_img, 1);
10518 }
10519
10520 img->width = width; 10524 img->width = width;
10521 img->height = height; 10525 img->height = height;
10522 10526