Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 349849b

Browse files
authored
Merge pull request #26215 from meeseeksmachine/auto-backport-of-pr-25824-on-v3.7.x
Backport PR #25824 on branch v3.7.x (pdf: Use explicit palette when saving indexed images)
2 parents 8d42212 + 399ebe1 commit 349849b

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
@@ -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(
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)