@@ -499,26 +499,27 @@ rgba2rgb_(UINT8 *out, const UINT8 *in, int xsize) {
499499}
500500
501501/*
502- * Conversion of RGB + single transparent color to RGBA,
503- * where any pixel that matches the color will have the
504- * alpha channel set to 0
502+ * Conversion of RGB + single transparent color either to
503+ * RGBA or LA, where any pixel matching the color will have the alpha channel set to 0, or
504+ * RGBa or La, where any pixel matching the color will have all channels set to 0
505505 */
506506
507507static void
508- rgbT2rgba (UINT8 * out , int xsize , int r , int g , int b ) {
508+ rgbT2a (UINT8 * out , UINT8 * in , int xsize , int r , int g , int b , int premultiplied ) {
509509#ifdef WORDS_BIGENDIAN
510510 UINT32 trns = ((r & 0xff ) << 24 ) | ((g & 0xff ) << 16 ) | ((b & 0xff ) << 8 ) | 0xff ;
511- UINT32 repl = trns & 0xffffff00 ;
511+ UINT32 repl = premultiplied ? 0 : ( trns & 0xffffff00 ) ;
512512#else
513513 UINT32 trns = (0xffU << 24 ) | ((b & 0xff ) << 16 ) | ((g & 0xff ) << 8 ) | (r & 0xff );
514- UINT32 repl = trns & 0x00ffffff ;
514+ UINT32 repl = premultiplied ? 0 : ( trns & 0x00ffffff ) ;
515515#endif
516516
517517 int i ;
518518
519- for (i = 0 ; i < xsize ; i ++ , out += sizeof (trns )) {
519+ UINT8 * ref = in != NULL ? in : out ;
520+ for (i = 0 ; i < xsize ; i ++ , ref += sizeof (trns ), out += sizeof (trns )) {
520521 UINT32 v ;
521- memcpy (& v , out , sizeof (v ));
522+ memcpy (& v , ref , sizeof (v ));
522523 if (v == trns ) {
523524 memcpy (out , & repl , sizeof (repl ));
524525 }
@@ -941,12 +942,14 @@ static struct {
941942 {"RGB" , "1" , rgb2bit },
942943 {"RGB" , "L" , rgb2l },
943944 {"RGB" , "LA" , rgb2la },
945+ {"RGB" , "La" , rgb2la },
944946 {"RGB" , "I" , rgb2i },
945947 {"RGB" , "F" , rgb2f },
946948 {"RGB" , "BGR;15" , rgb2bgr15 },
947949 {"RGB" , "BGR;16" , rgb2bgr16 },
948950 {"RGB" , "BGR;24" , rgb2bgr24 },
949951 {"RGB" , "RGBA" , rgb2rgba },
952+ {"RGB" , "RGBa" , rgb2rgba },
950953 {"RGB" , "RGBX" , rgb2rgba },
951954 {"RGB" , "CMYK" , rgb2cmyk },
952955 {"RGB" , "YCbCr" , ImagingConvertRGB2YCbCr },
@@ -1681,14 +1684,27 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
16811684 ImagingSectionCookie cookie ;
16821685 ImagingShuffler convert ;
16831686 Imaging imOut = NULL ;
1687+ int premultiplied = 0 ;
1688+ // If the transparency matches pixels in the source image, not the converted image
1689+ UINT8 * source ;
1690+ int source_transparency = 0 ;
16841691 int y ;
16851692
16861693 if (!imIn ) {
16871694 return (Imaging )ImagingError_ModeError ();
16881695 }
16891696
1690- if (strcmp (imIn -> mode , "RGB" ) == 0 && strcmp (mode , "RGBA" ) == 0 ) {
1697+ if (strcmp (imIn -> mode , "RGB" ) == 0 && ( strcmp (mode , "RGBA" ) == 0 || strcmp ( mode , "RGBa" ) == 0 ) ) {
16911698 convert = rgb2rgba ;
1699+ if (strcmp (mode , "RGBa" ) == 0 ) {
1700+ premultiplied = 1 ;
1701+ }
1702+ } else if (strcmp (imIn -> mode , "RGB" ) == 0 && (strcmp (mode , "LA" ) == 0 || strcmp (mode , "La" ) == 0 )) {
1703+ convert = rgb2la ;
1704+ source_transparency = 1 ;
1705+ if (strcmp (mode , "La" ) == 0 ) {
1706+ premultiplied = 1 ;
1707+ }
16921708 } else if ((strcmp (imIn -> mode , "1" ) == 0 ||
16931709 strcmp (imIn -> mode , "I" ) == 0 ||
16941710 strcmp (imIn -> mode , "I;16" ) == 0 ||
@@ -1726,7 +1742,9 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) {
17261742 ImagingSectionEnter (& cookie );
17271743 for (y = 0 ; y < imIn -> ysize ; y ++ ) {
17281744 (* convert )((UINT8 * )imOut -> image [y ], (UINT8 * )imIn -> image [y ], imIn -> xsize );
1729- rgbT2rgba ((UINT8 * )imOut -> image [y ], imIn -> xsize , r , g , b );
1745+
1746+ source = source_transparency ? (UINT8 * )imIn -> image [y ] : NULL ;
1747+ rgbT2a ((UINT8 * )imOut -> image [y ], source , imIn -> xsize , r , g , b , premultiplied );
17301748 }
17311749 ImagingSectionLeave (& cookie );
17321750
0 commit comments