@@ -2277,16 +2277,18 @@ def save(self, fp, format=None, **params):
22772277
22782278 if format .upper () not in SAVE :
22792279 init ()
2280- if params .pop (' save_all' , False ):
2280+ if params .pop (" save_all" , False ):
22812281 save_handler = SAVE_ALL [format .upper ()]
22822282 else :
22832283 save_handler = SAVE [format .upper ()]
22842284
2285- if params .get (' convert_mode' ):
2285+ if params .get (" convert_mode" ):
22862286 plugin = sys .modules [save_handler .__module__ ]
2287- converted_im = self ._convert_mode (plugin , params )
2288- if converted_im :
2289- return converted_im .save (fp , format , ** params )
2287+ if hasattr (plugin , "_supported_modes" ):
2288+ modes = plugin ._supported_modes ()
2289+ converted_im = self ._convert_mode (modes , params )
2290+ if converted_im :
2291+ return converted_im .save (fp , format , ** params )
22902292
22912293 self .encoderinfo = params
22922294 self .encoderconfig = ()
@@ -2315,32 +2317,57 @@ def save(self, fp, format=None, **params):
23152317 if open_fp :
23162318 fp .close ()
23172319
2318- def _convert_mode (self , plugin , params ):
2319- if not hasattr ( plugin , '_convert_mode' ) :
2320+ def _convert_mode (self , modes , params = {} ):
2321+ if not modes or self . mode in modes :
23202322 return
2321- new_mode = plugin ._convert_mode (self )
2322- if self .mode == 'LA' and new_mode == 'P' :
2323- alpha = self .getchannel ('A' )
2323+ if self .mode == "P" :
2324+ preferred_modes = []
2325+ if "A" in self .im .getpalettemode ():
2326+ preferred_modes .append ("RGBA" )
2327+ preferred_modes .append ("RGB" )
2328+ else :
2329+ preferred_modes = {
2330+ "CMYK" : ["RGB" ],
2331+ "RGB" : ["CMYK" ],
2332+ "RGBX" : ["RGB" ],
2333+ "RGBa" : ["RGBA" , "RGB" ],
2334+ "RGBA" : ["RGB" ],
2335+ "LA" : ["RGBA" , "P" , "L" ],
2336+ "La" : ["LA" , "L" ],
2337+ "L" : ["RGB" ],
2338+ "F" : ["I" ],
2339+ "I" : ["L" , "RGB" ],
2340+ "1" : ["L" ],
2341+ "YCbCr" : ["RGB" ],
2342+ "LAB" : ["RGB" ],
2343+ "HSV" : ["RGB" ],
2344+ }.get (self .mode , [])
2345+ for new_mode in preferred_modes :
2346+ if new_mode in modes :
2347+ break
2348+ else :
2349+ new_mode = modes [0 ]
2350+ if self .mode == "LA" and new_mode == "P" :
2351+ alpha = self .getchannel ("A" )
23242352 # Convert the image into P mode but only use 255 colors
23252353 # in the palette out of 256.
2326- im = self .convert ('L' ) \
2327- .convert ('P' , palette = Palette .ADAPTIVE , colors = 255 )
2354+ im = self .convert ("L" ).convert ("P" , palette = Palette .ADAPTIVE , colors = 255 )
23282355 # Set all pixel values below 128 to 255, and the rest to 0.
23292356 mask = eval (alpha , lambda px : 255 if px < 128 else 0 )
23302357 # Paste the color of index 255 and use alpha as a mask.
23312358 im .paste (255 , mask )
23322359 # The transparency index is 255.
2333- im .info [' transparency' ] = 255
2360+ im .info [" transparency" ] = 255
23342361 return im
23352362
2336- elif self .mode == 'I' :
2337- im = self .point ([i // 256 for i in range (65536 )], 'L' )
2338- return im .convert (new_mode ) if new_mode != 'L' else im
2363+ elif self .mode == "I" :
2364+ im = self .point ([i // 256 for i in range (65536 )], "L" )
2365+ return im .convert (new_mode ) if new_mode != "L" else im
23392366
2340- elif self .mode in (' RGBA' , 'LA' ) and new_mode in (' RGB' , 'L' ):
2341- fill_color = params .get (' fill_color' , ' white' )
2367+ elif self .mode in (" RGBA" , "LA" ) and new_mode in (" RGB" , "L" ):
2368+ fill_color = params .get (" fill_color" , " white" )
23422369 background = new (new_mode , self .size , fill_color )
2343- background .paste (self , self .getchannel ('A' ))
2370+ background .paste (self , self .getchannel ("A" ))
23442371 return background
23452372
23462373 elif new_mode :
0 commit comments