Support conversion from RGB to RGBa

This commit is contained in:
Andrew Murray 2024-03-21 16:25:40 +11:00
parent b3edfb08ce
commit 8b6a182815
3 changed files with 18 additions and 9 deletions

View File

@ -191,6 +191,10 @@ def test_trns_RGB(tmp_path: Path) -> None:
assert "transparency" not in im_rgba.info assert "transparency" not in im_rgba.info
im_rgba.save(f) im_rgba.save(f)
im_rgba = im.convert("RGBa")
assert "transparency" not in im_rgba.info
assert im_rgba.getpixel((0, 0)) == (0, 0, 0, 0)
im_p = pytest.warns(UserWarning, im.convert, "P", palette=Image.Palette.ADAPTIVE) im_p = pytest.warns(UserWarning, im.convert, "P", palette=Image.Palette.ADAPTIVE)
assert "transparency" not in im_p.info assert "transparency" not in im_p.info
im_p.save(f) im_p.save(f)

View File

@ -979,7 +979,7 @@ class Image:
# transparency handling # transparency handling
if has_transparency: if has_transparency:
if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or ( if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or (
self.mode == "RGB" and mode == "RGBA" self.mode == "RGB" and mode in ("RGBa", "RGBA")
): ):
# Use transparent conversion to promote from transparent # Use transparent conversion to promote from transparent
# color to an alpha channel. # color to an alpha channel.

View File

@ -499,19 +499,19 @@ rgba2rgb_(UINT8 *out, const UINT8 *in, int xsize) {
} }
/* /*
* Conversion of RGB + single transparent color to RGBA, * Conversion of RGB + single transparent color either to
* where any pixel that matches the color will have the * RGBA, where any pixel matching the color will have the alpha channel set to 0, or
* alpha channel set to 0 * RGBa, where any pixel matching the color will have all channels set to 0
*/ */
static void static void
rgbT2rgba(UINT8 *out, int xsize, int r, int g, int b) { rgbT2rgba(UINT8 *out, int xsize, int r, int g, int b, int premultiplied) {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
UINT32 trns = ((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8) | 0xff; UINT32 trns = ((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8) | 0xff;
UINT32 repl = trns & 0xffffff00; UINT32 repl = premultiplied ? 0 : (trns & 0xffffff00);
#else #else
UINT32 trns = (0xffU << 24) | ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff); UINT32 trns = (0xffU << 24) | ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff);
UINT32 repl = trns & 0x00ffffff; UINT32 repl = premultiplied ? 0 : (trns & 0x00ffffff);
#endif #endif
int i; int i;
@ -947,6 +947,7 @@ static struct {
{"RGB", "BGR;16", rgb2bgr16}, {"RGB", "BGR;16", rgb2bgr16},
{"RGB", "BGR;24", rgb2bgr24}, {"RGB", "BGR;24", rgb2bgr24},
{"RGB", "RGBA", rgb2rgba}, {"RGB", "RGBA", rgb2rgba},
{"RGB", "RGBa", rgb2rgba},
{"RGB", "RGBX", rgb2rgba}, {"RGB", "RGBX", rgb2rgba},
{"RGB", "CMYK", rgb2cmyk}, {"RGB", "CMYK", rgb2cmyk},
{"RGB", "YCbCr", ImagingConvertRGB2YCbCr}, {"RGB", "YCbCr", ImagingConvertRGB2YCbCr},
@ -1681,14 +1682,18 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
ImagingShuffler convert; ImagingShuffler convert;
Imaging imOut = NULL; Imaging imOut = NULL;
int premultiplied = 0;
int y; int y;
if (!imIn) { if (!imIn) {
return (Imaging)ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (strcmp(imIn->mode, "RGB") == 0 && strcmp(mode, "RGBA") == 0) { if (strcmp(imIn->mode, "RGB") == 0 && (strcmp(mode, "RGBA") == 0 || strcmp(mode, "RGBa") == 0)) {
convert = rgb2rgba; convert = rgb2rgba;
if (strcmp(mode, "RGBa") == 0) {
premultiplied = 1;
}
} else if ((strcmp(imIn->mode, "1") == 0 || } else if ((strcmp(imIn->mode, "1") == 0 ||
strcmp(imIn->mode, "I") == 0 || strcmp(imIn->mode, "I") == 0 ||
strcmp(imIn->mode, "I;16") == 0 || strcmp(imIn->mode, "I;16") == 0 ||
@ -1726,7 +1731,7 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
(*convert)((UINT8 *)imOut->image[y], (UINT8 *)imIn->image[y], imIn->xsize); (*convert)((UINT8 *)imOut->image[y], (UINT8 *)imIn->image[y], imIn->xsize);
rgbT2rgba((UINT8 *)imOut->image[y], imIn->xsize, r, g, b); rgbT2rgba((UINT8 *)imOut->image[y], imIn->xsize, r, g, b, premultiplied);
} }
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);