@@ -1757,39 +1757,43 @@ def _writeImg(self, data, id, smask=None):
1757
1757
'Subtype' : Name ('Image' ),
1758
1758
'Width' : width ,
1759
1759
'Height' : height ,
1760
- 'ColorSpace' : Name ({1 : 'DeviceGray' ,
1761
- 3 : 'DeviceRGB' }[color_channels ]),
1760
+ 'ColorSpace' : Name ({1 : 'DeviceGray' , 3 : 'DeviceRGB' }[color_channels ]),
1762
1761
'BitsPerComponent' : 8 }
1763
1762
if smask :
1764
1763
obj ['SMask' ] = smask
1765
1764
if mpl .rcParams ['pdf.compression' ]:
1766
1765
if data .shape [- 1 ] == 1 :
1767
1766
data = data .squeeze (axis = - 1 )
1767
+ png = {'Predictor' : 10 , 'Colors' : color_channels , 'Columns' : width }
1768
1768
img = Image .fromarray (data )
1769
1769
img_colors = img .getcolors (maxcolors = 256 )
1770
1770
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.
1773
1773
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 )
1781
1786
png_data , bit_depth , palette = self ._writePng (img )
1782
1787
if bit_depth is None or palette is None :
1783
1788
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 ]
1788
1792
obj ['BitsPerComponent' ] = bit_depth
1789
- color_channels = 1
1793
+ png ['Colors' ] = 1
1794
+ png ['BitsPerComponent' ] = bit_depth
1790
1795
else :
1791
1796
png_data , _ , _ = self ._writePng (img )
1792
- png = {'Predictor' : 10 , 'Colors' : color_channels , 'Columns' : width }
1793
1797
else :
1794
1798
png = None
1795
1799
self .beginStream (
0 commit comments