@@ -913,6 +913,15 @@ p2bit(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
913913 * out ++ = (L (& palette [in [x ]* 4 ]) >= 128000 ) ? 255 : 0 ;
914914}
915915
916+ static void
917+ pa2bit (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
918+ {
919+ int x ;
920+ /* FIXME: precalculate greyscale palette? */
921+ for (x = 0 ; x < xsize ; x ++ , in += 4 )
922+ * out ++ = (L (& palette [in [0 ]* 4 ]) >= 128000 ) ? 255 : 0 ;
923+ }
924+
916925static void
917926p2l (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
918927{
@@ -922,6 +931,28 @@ p2l(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
922931 * out ++ = L (& palette [in [x ]* 4 ]) / 1000 ;
923932}
924933
934+ static void
935+ pa2l (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
936+ {
937+ int x ;
938+ /* FIXME: precalculate greyscale palette? */
939+ for (x = 0 ; x < xsize ; x ++ , in += 4 )
940+ * out ++ = L (& palette [in [0 ]* 4 ]) / 1000 ;
941+ }
942+
943+ static void
944+ p2pa (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
945+ {
946+ int x ;
947+ for (x = 0 ; x < xsize ; x ++ , in += 4 ) {
948+ const UINT8 * rgba = & palette [in [0 ] * 4 ];
949+ * out ++ = in [0 ];
950+ * out ++ = in [0 ];
951+ * out ++ = in [0 ];
952+ * out ++ = rgba [3 ];
953+ }
954+ }
955+
925956static void
926957p2la (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
927958{
@@ -939,9 +970,9 @@ pa2la(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
939970{
940971 int x ;
941972 /* FIXME: precalculate greyscale palette? */
942- for (x = 0 ; x < xsize ; x ++ , in += 2 ) {
943- * out ++ = L (& palette [in [0 ]* 4 ]) / 1000 ;
944- * out ++ = in [1 ];
973+ for (x = 0 ; x < xsize ; x ++ , in += 4 , out += 4 ) {
974+ out [ 0 ] = out [ 1 ] = out [ 2 ] = L (& palette [in [0 ]* 4 ]) / 1000 ;
975+ out [ 3 ] = in [3 ];
945976 }
946977}
947978
@@ -954,6 +985,15 @@ p2i(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette)
954985 * out ++ = L (& palette [in [x ]* 4 ]) / 1000 ;
955986}
956987
988+ static void
989+ pa2i (UINT8 * out_ , const UINT8 * in , int xsize , const UINT8 * palette )
990+ {
991+ int x ;
992+ INT32 * out = (INT32 * ) out_ ;
993+ for (x = 0 ; x < xsize ; x ++ , in += 4 )
994+ * out ++ = L (& palette [in [0 ]* 4 ]) / 1000 ;
995+ }
996+
957997static void
958998p2f (UINT8 * out_ , const UINT8 * in , int xsize , const UINT8 * palette )
959999{
@@ -963,6 +1003,15 @@ p2f(UINT8* out_, const UINT8* in, int xsize, const UINT8* palette)
9631003 * out ++ = (float ) L (& palette [in [x ]* 4 ]) / 1000.0F ;
9641004}
9651005
1006+ static void
1007+ pa2f (UINT8 * out_ , const UINT8 * in , int xsize , const UINT8 * palette )
1008+ {
1009+ int x ;
1010+ FLOAT32 * out = (FLOAT32 * ) out_ ;
1011+ for (x = 0 ; x < xsize ; x ++ , in += 4 )
1012+ * out ++ = (float ) L (& palette [in [0 ]* 4 ]) / 1000.0F ;
1013+ }
1014+
9661015static void
9671016p2rgb (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
9681017{
@@ -976,6 +1025,19 @@ p2rgb(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
9761025 }
9771026}
9781027
1028+ static void
1029+ pa2rgb (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
1030+ {
1031+ int x ;
1032+ for (x = 0 ; x < xsize ; x ++ , in += 4 ) {
1033+ const UINT8 * rgb = & palette [in [0 ] * 4 ];
1034+ * out ++ = rgb [0 ];
1035+ * out ++ = rgb [1 ];
1036+ * out ++ = rgb [2 ];
1037+ * out ++ = 255 ;
1038+ }
1039+ }
1040+
9791041static void
9801042p2rgba (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
9811043{
@@ -1009,13 +1071,27 @@ p2cmyk(UINT8* out, const UINT8* in, int xsize, const UINT8* palette)
10091071 rgb2cmyk (out , out , xsize );
10101072}
10111073
1074+ static void
1075+ pa2cmyk (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
1076+ {
1077+ pa2rgb (out , in , xsize , palette );
1078+ rgb2cmyk (out , out , xsize );
1079+ }
1080+
10121081static void
10131082p2ycbcr (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
10141083{
10151084 p2rgb (out , in , xsize , palette );
10161085 ImagingConvertRGB2YCbCr (out , out , xsize );
10171086}
10181087
1088+ static void
1089+ pa2ycbcr (UINT8 * out , const UINT8 * in , int xsize , const UINT8 * palette )
1090+ {
1091+ pa2rgb (out , in , xsize , palette );
1092+ ImagingConvertRGB2YCbCr (out , out , xsize );
1093+ }
1094+
10191095static Imaging
10201096frompalette (Imaging imOut , Imaging imIn , const char * mode )
10211097{
@@ -1032,27 +1108,27 @@ frompalette(Imaging imOut, Imaging imIn, const char *mode)
10321108 alpha = !strcmp (imIn -> mode , "PA" );
10331109
10341110 if (strcmp (mode , "1" ) == 0 )
1035- convert = p2bit ;
1111+ convert = alpha ? pa2bit : p2bit ;
10361112 else if (strcmp (mode , "L" ) == 0 )
1037- convert = p2l ;
1113+ convert = alpha ? pa2l : p2l ;
10381114 else if (strcmp (mode , "LA" ) == 0 )
1039- convert = ( alpha ) ? pa2la : p2la ;
1115+ convert = alpha ? pa2la : p2la ;
10401116 else if (strcmp (mode , "PA" ) == 0 )
1041- convert = l2la ;
1117+ convert = p2pa ;
10421118 else if (strcmp (mode , "I" ) == 0 )
1043- convert = p2i ;
1119+ convert = alpha ? pa2i : p2i ;
10441120 else if (strcmp (mode , "F" ) == 0 )
1045- convert = p2f ;
1121+ convert = alpha ? pa2f : p2f ;
10461122 else if (strcmp (mode , "RGB" ) == 0 )
1047- convert = p2rgb ;
1123+ convert = alpha ? pa2rgb : p2rgb ;
10481124 else if (strcmp (mode , "RGBA" ) == 0 )
1049- convert = ( alpha ) ? pa2rgba : p2rgba ;
1125+ convert = alpha ? pa2rgba : p2rgba ;
10501126 else if (strcmp (mode , "RGBX" ) == 0 )
1051- convert = p2rgba ;
1127+ convert = alpha ? pa2rgba : p2rgba ;
10521128 else if (strcmp (mode , "CMYK" ) == 0 )
1053- convert = p2cmyk ;
1129+ convert = alpha ? pa2cmyk : p2cmyk ;
10541130 else if (strcmp (mode , "YCbCr" ) == 0 )
1055- convert = p2ycbcr ;
1131+ convert = alpha ? pa2ycbcr : p2ycbcr ;
10561132 else
10571133 return (Imaging ) ImagingError_ValueError ("conversion not supported" );
10581134
@@ -1073,16 +1149,19 @@ frompalette(Imaging imOut, Imaging imIn, const char *mode)
10731149#pragma optimize("", off)
10741150#endif
10751151static Imaging
1076- topalette (Imaging imOut , Imaging imIn , ImagingPalette inpalette , int dither )
1152+ topalette (Imaging imOut , Imaging imIn , const char * mode , ImagingPalette inpalette , int dither )
10771153{
10781154 ImagingSectionCookie cookie ;
1155+ int alpha ;
10791156 int x , y ;
10801157 ImagingPalette palette = inpalette ;;
10811158
10821159 /* Map L or RGB/RGBX/RGBA to palette image */
10831160 if (strcmp (imIn -> mode , "L" ) != 0 && strncmp (imIn -> mode , "RGB" , 3 ) != 0 )
10841161 return (Imaging ) ImagingError_ValueError ("conversion not supported" );
10851162
1163+ alpha = !strcmp (mode , "PA" );
1164+
10861165 if (palette == NULL ) {
10871166 /* FIXME: make user configurable */
10881167 if (imIn -> bands == 1 )
@@ -1094,7 +1173,7 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
10941173 if (!palette )
10951174 return (Imaging ) ImagingError_ValueError ("no palette" );
10961175
1097- imOut = ImagingNew2Dirty ("P" , imOut , imIn );
1176+ imOut = ImagingNew2Dirty (mode , imOut , imIn );
10981177 if (!imOut ) {
10991178 if (palette != inpalette )
11001179 ImagingPaletteDelete (palette );
@@ -1109,8 +1188,13 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
11091188
11101189 /* Greyscale palette: copy data as is */
11111190 ImagingSectionEnter (& cookie );
1112- for (y = 0 ; y < imIn -> ysize ; y ++ )
1113- memcpy (imOut -> image [y ], imIn -> image [y ], imIn -> linesize );
1191+ for (y = 0 ; y < imIn -> ysize ; y ++ ) {
1192+ if (alpha ) {
1193+ l2la ((UINT8 * ) imOut -> image [y ], (UINT8 * ) imIn -> image [y ], imIn -> xsize );
1194+ } else {
1195+ memcpy (imOut -> image [y ], imIn -> image [y ], imIn -> linesize );
1196+ }
1197+ }
11141198 ImagingSectionLeave (& cookie );
11151199
11161200 } else {
@@ -1141,7 +1225,7 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
11411225 int g , g0 , g1 , g2 ;
11421226 int b , b0 , b1 , b2 ;
11431227 UINT8 * in = (UINT8 * ) imIn -> image [y ];
1144- UINT8 * out = imOut -> image8 [y ];
1228+ UINT8 * out = alpha ? ( UINT8 * ) imOut -> image32 [ y ] : imOut -> image8 [y ];
11451229 int * e = errors ;
11461230
11471231 r = r0 = r1 = 0 ;
@@ -1160,7 +1244,12 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
11601244 cache = & ImagingPaletteCache (palette , r , g , b );
11611245 if (cache [0 ] == 0x100 )
11621246 ImagingPaletteCacheUpdate (palette , r , g , b );
1163- out [x ] = (UINT8 ) cache [0 ];
1247+ if (alpha ) {
1248+ out [x * 4 ] = out [x * 4 + 1 ] = out [x * 4 + 2 ] = (UINT8 ) cache [0 ];
1249+ out [x * 4 + 3 ] = 255 ;
1250+ } else {
1251+ out [x ] = (UINT8 ) cache [0 ];
1252+ }
11641253
11651254 r -= (int ) palette -> palette [cache [0 ]* 4 ];
11661255 g -= (int ) palette -> palette [cache [0 ]* 4 + 1 ];
@@ -1193,7 +1282,7 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
11931282 for (y = 0 ; y < imIn -> ysize ; y ++ ) {
11941283 int r , g , b ;
11951284 UINT8 * in = (UINT8 * ) imIn -> image [y ];
1196- UINT8 * out = imOut -> image8 [y ];
1285+ UINT8 * out = alpha ? ( UINT8 * ) imOut -> image32 [ y ] : imOut -> image8 [y ];
11971286
11981287 for (x = 0 ; x < imIn -> xsize ; x ++ , in += 4 ) {
11991288 INT16 * cache ;
@@ -1204,8 +1293,12 @@ topalette(Imaging imOut, Imaging imIn, ImagingPalette inpalette, int dither)
12041293 cache = & ImagingPaletteCache (palette , r , g , b );
12051294 if (cache [0 ] == 0x100 )
12061295 ImagingPaletteCacheUpdate (palette , r , g , b );
1207- out [x ] = (UINT8 ) cache [0 ];
1208-
1296+ if (alpha ) {
1297+ out [x * 4 ] = out [x * 4 + 1 ] = out [x * 4 + 2 ] = (UINT8 ) cache [0 ];
1298+ out [x * 4 + 3 ] = 255 ;
1299+ } else {
1300+ out [x ] = (UINT8 ) cache [0 ];
1301+ }
12091302 }
12101303 }
12111304 ImagingSectionLeave (& cookie );
@@ -1335,8 +1428,8 @@ convert(Imaging imOut, Imaging imIn, const char *mode,
13351428 if (strcmp (imIn -> mode , "P" ) == 0 || strcmp (imIn -> mode , "PA" ) == 0 )
13361429 return frompalette (imOut , imIn , mode );
13371430
1338- if (strcmp (mode , "P" ) == 0 )
1339- return topalette (imOut , imIn , palette , dither );
1431+ if (strcmp (mode , "P" ) == 0 || strcmp ( mode , "PA" ) == 0 )
1432+ return topalette (imOut , imIn , mode , palette , dither );
13401433
13411434 if (dither && strcmp (mode , "1" ) == 0 )
13421435 return tobilevel (imOut , imIn , dither );
0 commit comments