Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbe2e5d7

Browse files
authored
Merge pull request#17895 from mpetroff/pdf-indexed-color
Use indexed color for PNG images in PDF files when possible
2 parents56ca51f +c9599a2 commitbe2e5d7

File tree

2 files changed

+45
-12
lines changed

2 files changed

+45
-12
lines changed

‎lib/matplotlib/backends/backend_pdf.py

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,28 +1521,34 @@ def _unpack(self, im):
15211521
alpha=None
15221522
returnrgb,alpha
15231523

1524-
def_writePng(self,data):
1524+
def_writePng(self,img):
15251525
"""
1526-
Write the image *data* into the pdf file using png
1526+
Write the image *img* into the pdf file using png
15271527
predictors with Flate compression.
15281528
"""
15291529
buffer=BytesIO()
1530-
ifdata.shape[-1]==1:
1531-
data=data.squeeze(axis=-1)
1532-
Image.fromarray(data).save(buffer,format="png")
1530+
img.save(buffer,format="png")
15331531
buffer.seek(8)
1532+
png_data=b''
1533+
bit_depth=palette=None
15341534
whileTrue:
15351535
length,type=struct.unpack(b'!L4s',buffer.read(8))
1536-
iftype==b'IDAT':
1536+
iftypein [b'IHDR',b'PLTE',b'IDAT']:
15371537
data=buffer.read(length)
15381538
iflen(data)!=length:
15391539
raiseRuntimeError("truncated data")
1540-
self.currentstream.write(data)
1540+
iftype==b'IHDR':
1541+
bit_depth=int(data[8])
1542+
eliftype==b'PLTE':
1543+
palette=data
1544+
eliftype==b'IDAT':
1545+
png_data+=data
15411546
eliftype==b'IEND':
15421547
break
15431548
else:
15441549
buffer.seek(length,1)
15451550
buffer.seek(4,1)# skip CRC
1551+
returnpng_data,bit_depth,palette
15461552

15471553
def_writeImg(self,data,id,smask=None):
15481554
"""
@@ -1551,17 +1557,40 @@ def _writeImg(self, data, id, smask=None):
15511557
(alpha channel) *smask*, which should be either None or a ``(height,
15521558
width, 1)`` array.
15531559
"""
1554-
height,width,colors=data.shape
1560+
height,width,color_channels=data.shape
15551561
obj= {'Type':Name('XObject'),
15561562
'Subtype':Name('Image'),
15571563
'Width':width,
15581564
'Height':height,
1559-
'ColorSpace':Name({1:'DeviceGray',3:'DeviceRGB'}[colors]),
1565+
'ColorSpace':Name({1:'DeviceGray',
1566+
3:'DeviceRGB'}[color_channels]),
15601567
'BitsPerComponent':8}
15611568
ifsmask:
15621569
obj['SMask']=smask
15631570
ifmpl.rcParams['pdf.compression']:
1564-
png= {'Predictor':10,'Colors':colors,'Columns':width}
1571+
ifdata.shape[-1]==1:
1572+
data=data.squeeze(axis=-1)
1573+
img=Image.fromarray(data)
1574+
img_colors=img.getcolors(maxcolors=256)
1575+
ifcolor_channels==3andimg_colorsisnotNone:
1576+
# Convert to indexed color if there are 256 colors or fewer
1577+
# This can significantly reduce the file size
1578+
num_colors=len(img_colors)
1579+
img=img.convert(mode='P',dither=Image.NONE,
1580+
palette=Image.ADAPTIVE,colors=num_colors)
1581+
png_data,bit_depth,palette=self._writePng(img)
1582+
ifbit_depthisNoneorpaletteisNone:
1583+
raiseRuntimeError("invalid PNG header")
1584+
palette=palette[:num_colors*3]# Trim padding
1585+
palette=pdfRepr(palette)
1586+
obj['ColorSpace']=Verbatim(b'[/Indexed /DeviceRGB '
1587+
+str(num_colors-1).encode()
1588+
+b' '+palette+b']')
1589+
obj['BitsPerComponent']=bit_depth
1590+
color_channels=1
1591+
else:
1592+
png_data,_,_=self._writePng(img)
1593+
png= {'Predictor':10,'Colors':color_channels,'Columns':width}
15651594
else:
15661595
png=None
15671596
self.beginStream(
@@ -1571,7 +1600,7 @@ def _writeImg(self, data, id, smask=None):
15711600
png=png
15721601
)
15731602
ifpng:
1574-
self._writePng(data)
1603+
self.currentstream.write(png_data)
15751604
else:
15761605
self.currentstream.write(data.tobytes())
15771606
self.endStream()

‎lib/matplotlib/tests/test_image.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,11 @@ def test_log_scale_image():
732732
ax.set(yscale='log')
733733

734734

735-
@image_comparison(['rotate_image'],remove_text=True)
735+
# Increased tolerance is needed for PDF test to avoid failure. After the PDF
736+
# backend was modified to use indexed color, there are ten pixels that differ
737+
# due to how the subpixel calculation is done when converting the PDF files to
738+
# PNG images.
739+
@image_comparison(['rotate_image'],remove_text=True,tol=0.35)
736740
deftest_rotate_image():
737741
delta=0.25
738742
x=y=np.arange(-3.0,3.0,delta)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp