Skip to content

Commit 475612e

Browse files
authored
Merge pull request matplotlib#25824 from QuLogic/fix-index-pdf
2 parents 94edf8a + 96fad22 commit 475612e

File tree

21 files changed

+46
-22
lines changed

21 files changed

+46
-22
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,39 +1731,43 @@ def _writeImg(self, data, id, smask=None):
17311731
'Subtype': Name('Image'),
17321732
'Width': width,
17331733
'Height': height,
1734-
'ColorSpace': Name({1: 'DeviceGray',
1735-
3: 'DeviceRGB'}[color_channels]),
1734+
'ColorSpace': Name({1: 'DeviceGray', 3: 'DeviceRGB'}[color_channels]),
17361735
'BitsPerComponent': 8}
17371736
if smask:
17381737
obj['SMask'] = smask
17391738
if mpl.rcParams['pdf.compression']:
17401739
if data.shape[-1] == 1:
17411740
data = data.squeeze(axis=-1)
1741+
png = {'Predictor': 10, 'Colors': color_channels, 'Columns': width}
17421742
img = Image.fromarray(data)
17431743
img_colors = img.getcolors(maxcolors=256)
17441744
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.
17471747
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)
17551760
png_data, bit_depth, palette = self._writePng(img)
17561761
if bit_depth is None or palette is None:
17571762
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]
17621766
obj['BitsPerComponent'] = bit_depth
1763-
color_channels = 1
1767+
png['Colors'] = 1
1768+
png['BitsPerComponent'] = bit_depth
17641769
else:
17651770
png_data, _, _ = self._writePng(img)
1766-
png = {'Predictor': 10, 'Colors': color_channels, 'Columns': width}
17671771
else:
17681772
png = None
17691773
self.beginStream(
Binary file not shown.
-2.48 KB
Binary file not shown.
41 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
-15.6 KB
Binary file not shown.
66 Bytes
Binary file not shown.
-237 Bytes
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)