@@ -1757,39 +1757,43 @@ def _writeImg(self, data, id, smask=None):
17571757 'Subtype' : Name ('Image' ),
17581758 'Width' : width ,
17591759 'Height' : height ,
1760- 'ColorSpace' : Name ({1 : 'DeviceGray' ,
1761- 3 : 'DeviceRGB' }[color_channels ]),
1760+ 'ColorSpace' : Name ({1 : 'DeviceGray' , 3 : 'DeviceRGB' }[color_channels ]),
17621761 'BitsPerComponent' : 8 }
17631762 if smask :
17641763 obj ['SMask' ] = smask
17651764 if mpl .rcParams ['pdf.compression' ]:
17661765 if data .shape [- 1 ] == 1 :
17671766 data = data .squeeze (axis = - 1 )
1767+ png = {'Predictor' : 10 , 'Colors' : color_channels , 'Columns' : width }
17681768 img = Image .fromarray (data )
17691769 img_colors = img .getcolors (maxcolors = 256 )
17701770 if color_channels == 3 and img_colors is not None :
1771- # Convert to indexed color if there are 256 colors or fewer
1772- # This can significantly reduce the file size
1771+ # Convert to indexed color if there are 256 colors or fewer. This can
1772+ # significantly reduce the file size.
17731773 num_colors = len (img_colors )
1774- # These constants were converted to IntEnums and deprecated in
1775- # Pillow 9.2
1776- dither = getattr (Image , 'Dither' , Image ).NONE
1777- pmode = getattr (Image , 'Palette' , Image ).ADAPTIVE
1778- img = img .convert (
1779- mode = 'P' , dither = dither , palette = pmode , colors = num_colors
1780- )
1774+ palette = np .array ([comp for _ , color in img_colors for comp in color ],
1775+ dtype = np .uint8 )
1776+ palette24 = ((palette [0 ::3 ].astype (np .uint32 ) << 16 ) |
1777+ (palette [1 ::3 ].astype (np .uint32 ) << 8 ) |
1778+ palette [2 ::3 ])
1779+ rgb24 = ((data [:, :, 0 ].astype (np .uint32 ) << 16 ) |
1780+ (data [:, :, 1 ].astype (np .uint32 ) << 8 ) |
1781+ data [:, :, 2 ])
1782+ indices = np .argsort (palette24 ).astype (np .uint8 )
1783+ rgb8 = indices [np .searchsorted (palette24 , rgb24 , sorter = indices )]
1784+ img = Image .fromarray (rgb8 , mode = 'P' )
1785+ img .putpalette (palette )
17811786 png_data , bit_depth , palette = self ._writePng (img )
17821787 if bit_depth is None or palette is None :
17831788 raise RuntimeError ("invalid PNG header" )
1784- palette = palette [:num_colors * 3 ] # Trim padding
1785- obj ['ColorSpace' ] = Verbatim (
1786- b'[/Indexed /DeviceRGB %d %s]'
1787- % (num_colors - 1 , pdfRepr (palette )))
1789+ palette = palette [:num_colors * 3 ] # Trim padding; remove for Pillow>=9
1790+ obj ['ColorSpace' ] = [Name ('Indexed' ), Name ('DeviceRGB' ),
1791+ num_colors - 1 , palette ]
17881792 obj ['BitsPerComponent' ] = bit_depth
1789- color_channels = 1
1793+ png ['Colors' ] = 1
1794+ png ['BitsPerComponent' ] = bit_depth
17901795 else :
17911796 png_data , _ , _ = self ._writePng (img )
1792- png = {'Predictor' : 10 , 'Colors' : color_channels , 'Columns' : width }
17931797 else :
17941798 png = None
17951799 self .beginStream (
0 commit comments