@@ -1731,39 +1731,43 @@ def _writeImg(self, data, id, smask=None):
1731
1731
'Subtype' : Name ('Image' ),
1732
1732
'Width' : width ,
1733
1733
'Height' : height ,
1734
- 'ColorSpace' : Name ({1 : 'DeviceGray' ,
1735
- 3 : 'DeviceRGB' }[color_channels ]),
1734
+ 'ColorSpace' : Name ({1 : 'DeviceGray' , 3 : 'DeviceRGB' }[color_channels ]),
1736
1735
'BitsPerComponent' : 8 }
1737
1736
if smask :
1738
1737
obj ['SMask' ] = smask
1739
1738
if mpl .rcParams ['pdf.compression' ]:
1740
1739
if data .shape [- 1 ] == 1 :
1741
1740
data = data .squeeze (axis = - 1 )
1741
+ png = {'Predictor' : 10 , 'Colors' : color_channels , 'Columns' : width }
1742
1742
img = Image .fromarray (data )
1743
1743
img_colors = img .getcolors (maxcolors = 256 )
1744
1744
if color_channels == 3 and img_colors is not None :
1745
- # Convert to indexed color if there are 256 colors or fewer
1746
- # This can significantly reduce the file size
1745
+ # Convert to indexed color if there are 256 colors or fewer. This can
1746
+ # significantly reduce the file size.
1747
1747
num_colors = len (img_colors )
1748
- # These constants were converted to IntEnums and deprecated in
1749
- # Pillow 9.2
1750
- dither = getattr (Image , 'Dither' , Image ).NONE
1751
- pmode = getattr (Image , 'Palette' , Image ).ADAPTIVE
1752
- img = img .convert (
1753
- mode = 'P' , dither = dither , palette = pmode , colors = num_colors
1754
- )
1748
+ palette = np .array ([comp for _ , color in img_colors for comp in color ],
1749
+ dtype = np .uint8 )
1750
+ palette24 = ((palette [0 ::3 ].astype (np .uint32 ) << 16 ) |
1751
+ (palette [1 ::3 ].astype (np .uint32 ) << 8 ) |
1752
+ palette [2 ::3 ])
1753
+ rgb24 = ((data [:, :, 0 ].astype (np .uint32 ) << 16 ) |
1754
+ (data [:, :, 1 ].astype (np .uint32 ) << 8 ) |
1755
+ data [:, :, 2 ])
1756
+ indices = np .argsort (palette24 ).astype (np .uint8 )
1757
+ rgb8 = indices [np .searchsorted (palette24 , rgb24 , sorter = indices )]
1758
+ img = Image .fromarray (rgb8 , mode = 'P' )
1759
+ img .putpalette (palette )
1755
1760
png_data , bit_depth , palette = self ._writePng (img )
1756
1761
if bit_depth is None or palette is None :
1757
1762
raise RuntimeError ("invalid PNG header" )
1758
- palette = palette [:num_colors * 3 ] # Trim padding
1759
- obj ['ColorSpace' ] = Verbatim (
1760
- b'[/Indexed /DeviceRGB %d %s]'
1761
- % (num_colors - 1 , pdfRepr (palette )))
1763
+ palette = palette [:num_colors * 3 ] # Trim padding; remove for Pillow>=9
1764
+ obj ['ColorSpace' ] = [Name ('Indexed' ), Name ('DeviceRGB' ),
1765
+ num_colors - 1 , palette ]
1762
1766
obj ['BitsPerComponent' ] = bit_depth
1763
- color_channels = 1
1767
+ png ['Colors' ] = 1
1768
+ png ['BitsPerComponent' ] = bit_depth
1764
1769
else :
1765
1770
png_data , _ , _ = self ._writePng (img )
1766
- png = {'Predictor' : 10 , 'Colors' : color_channels , 'Columns' : width }
1767
1771
else :
1768
1772
png = None
1769
1773
self .beginStream (
0 commit comments