Mercurial > hgrepos > Python2 > PyMuPDF
comparison tests/test_pixmap.py @ 1:1d09e1dec1d9 upstream
ADD: PyMuPDF v1.26.4: the original sdist.
It does not yet contain MuPDF. This normally will be downloaded when
building PyMuPDF.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:37:51 +0200 |
| parents | |
| children | a6bc019ac0b2 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 1:1d09e1dec1d9 |
|---|---|
| 1 """ | |
| 2 Pixmap tests | |
| 3 * make pixmap of a page and assert bbox size | |
| 4 * make pixmap from a PDF xref and compare with extracted image | |
| 5 * pixmap from file and from binary image and compare | |
| 6 """ | |
| 7 | |
| 8 import pymupdf | |
| 9 import gentle_compare | |
| 10 | |
| 11 import os | |
| 12 import platform | |
| 13 import subprocess | |
| 14 import sys | |
| 15 import tempfile | |
| 16 import pytest | |
| 17 import textwrap | |
| 18 import time | |
| 19 | |
| 20 | |
| 21 scriptdir = os.path.abspath(os.path.dirname(__file__)) | |
| 22 epub = os.path.join(scriptdir, "resources", "Bezier.epub") | |
| 23 pdf = os.path.join(scriptdir, "resources", "001003ED.pdf") | |
| 24 imgfile = os.path.join(scriptdir, "resources", "nur-ruhig.jpg") | |
| 25 | |
| 26 | |
| 27 def test_pagepixmap(): | |
| 28 # pixmap from an EPUB page | |
| 29 doc = pymupdf.open(epub) | |
| 30 page = doc[0] | |
| 31 pix = page.get_pixmap() | |
| 32 assert pix.irect == page.rect.irect | |
| 33 pix = page.get_pixmap(alpha=True) | |
| 34 assert pix.alpha | |
| 35 assert pix.n == pix.colorspace.n + pix.alpha | |
| 36 | |
| 37 | |
| 38 def test_pdfpixmap(): | |
| 39 # pixmap from xref in a PDF | |
| 40 doc = pymupdf.open(pdf) | |
| 41 # take first image item of first page | |
| 42 img = doc.get_page_images(0)[0] | |
| 43 # make pixmap of it | |
| 44 pix = pymupdf.Pixmap(doc, img[0]) | |
| 45 # assert pixmap properties | |
| 46 assert pix.width == img[2] | |
| 47 assert pix.height == img[3] | |
| 48 # extract image and compare metadata | |
| 49 extractimg = doc.extract_image(img[0]) | |
| 50 assert extractimg["width"] == pix.width | |
| 51 assert extractimg["height"] == pix.height | |
| 52 | |
| 53 | |
| 54 def test_filepixmap(): | |
| 55 # pixmaps from file and from stream | |
| 56 # should lead to same result | |
| 57 pix1 = pymupdf.Pixmap(imgfile) | |
| 58 stream = open(imgfile, "rb").read() | |
| 59 pix2 = pymupdf.Pixmap(stream) | |
| 60 assert repr(pix1) == repr(pix2) | |
| 61 assert pix1.digest == pix2.digest | |
| 62 | |
| 63 | |
| 64 def test_pilsave(): | |
| 65 # pixmaps from file then save to pillow image | |
| 66 # make pixmap from this and confirm equality | |
| 67 try: | |
| 68 pix1 = pymupdf.Pixmap(imgfile) | |
| 69 stream = pix1.pil_tobytes("JPEG") | |
| 70 pix2 = pymupdf.Pixmap(stream) | |
| 71 assert repr(pix1) == repr(pix2) | |
| 72 except ModuleNotFoundError: | |
| 73 assert platform.system() == 'Windows' and sys.maxsize == 2**31 - 1 | |
| 74 | |
| 75 | |
| 76 def test_save(tmpdir): | |
| 77 # pixmaps from file then save to image | |
| 78 # make pixmap from this and confirm equality | |
| 79 pix1 = pymupdf.Pixmap(imgfile) | |
| 80 outfile = os.path.join(tmpdir, "foo.png") | |
| 81 pix1.save(outfile, output="png") | |
| 82 # read it back | |
| 83 pix2 = pymupdf.Pixmap(outfile) | |
| 84 assert repr(pix1) == repr(pix2) | |
| 85 | |
| 86 | |
| 87 def test_setalpha(): | |
| 88 # pixmap from JPEG file, then add an alpha channel | |
| 89 # with 30% transparency | |
| 90 pix1 = pymupdf.Pixmap(imgfile) | |
| 91 opa = int(255 * 0.3) # corresponding to 30% transparency | |
| 92 alphas = [opa] * (pix1.width * pix1.height) | |
| 93 alphas = bytearray(alphas) | |
| 94 pix2 = pymupdf.Pixmap(pix1, 1) # add alpha channel | |
| 95 pix2.set_alpha(alphas) # make image 30% transparent | |
| 96 samples = pix2.samples # copy of samples | |
| 97 # confirm correct the alpha bytes | |
| 98 t = bytearray([samples[i] for i in range(3, len(samples), 4)]) | |
| 99 assert t == alphas | |
| 100 | |
| 101 def test_color_count(): | |
| 102 ''' | |
| 103 This is known to fail if MuPDF is built without PyMuPDF's custom config.h, | |
| 104 e.g. in Linux system installs. | |
| 105 ''' | |
| 106 pm = pymupdf.Pixmap(imgfile) | |
| 107 assert pm.color_count() == 40624 | |
| 108 | |
| 109 def test_memoryview(): | |
| 110 pm = pymupdf.Pixmap(imgfile) | |
| 111 samples = pm.samples_mv | |
| 112 assert isinstance( samples, memoryview) | |
| 113 print( f'samples={samples} samples.itemsize={samples.itemsize} samples.nbytes={samples.nbytes} samples.ndim={samples.ndim} samples.shape={samples.shape} samples.strides={samples.strides}') | |
| 114 assert samples.itemsize == 1 | |
| 115 assert samples.nbytes == 659817 | |
| 116 assert samples.ndim == 1 | |
| 117 assert samples.shape == (659817,) | |
| 118 assert samples.strides == (1,) | |
| 119 | |
| 120 color = pm.pixel( 100, 100) | |
| 121 print( f'color={color}') | |
| 122 assert color == (83, 66, 40) | |
| 123 | |
| 124 def test_samples_ptr(): | |
| 125 pm = pymupdf.Pixmap(imgfile) | |
| 126 samples = pm.samples_ptr | |
| 127 print( f'samples={samples}') | |
| 128 assert isinstance( samples, int) | |
| 129 | |
| 130 def test_2369(): | |
| 131 | |
| 132 width, height = 13, 37 | |
| 133 image = pymupdf.Pixmap(pymupdf.csGRAY, width, height, b"\x00" * (width * height), False) | |
| 134 | |
| 135 with pymupdf.Document(stream=image.tobytes(output="pam"), filetype="pam") as doc: | |
| 136 test_pdf_bytes = doc.convert_to_pdf() | |
| 137 | |
| 138 with pymupdf.Document(stream=test_pdf_bytes) as doc: | |
| 139 page = doc[0] | |
| 140 img_xref = page.get_images()[0][0] | |
| 141 img = doc.extract_image(img_xref) | |
| 142 img_bytes = img["image"] | |
| 143 pymupdf.Pixmap(img_bytes) | |
| 144 | |
| 145 def test_page_idx_int(): | |
| 146 doc = pymupdf.open(pdf) | |
| 147 with pytest.raises(AssertionError): | |
| 148 doc["0"] | |
| 149 assert doc[0] | |
| 150 assert doc[(0,0)] | |
| 151 | |
| 152 def test_fz_write_pixmap_as_jpeg(): | |
| 153 width, height = 13, 37 | |
| 154 image = pymupdf.Pixmap(pymupdf.csGRAY, width, height, b"\x00" * (width * height), False) | |
| 155 | |
| 156 with pymupdf.Document(stream=image.tobytes(output="jpeg"), filetype="jpeg") as doc: | |
| 157 test_pdf_bytes = doc.convert_to_pdf() | |
| 158 | |
| 159 def test_3020(): | |
| 160 pm = pymupdf.Pixmap(imgfile) | |
| 161 pm2 = pymupdf.Pixmap(pm, 20, 30, None) | |
| 162 pm3 = pymupdf.Pixmap(pymupdf.csGRAY, pm) | |
| 163 pm4 = pymupdf.Pixmap(pm, pm3) | |
| 164 | |
| 165 def test_3050(): | |
| 166 ''' | |
| 167 This is known to fail if MuPDF is built without it's default third-party | |
| 168 libraries, e.g. in Linux system installs. | |
| 169 ''' | |
| 170 path = os.path.normpath(f'{__file__}/../../tests/resources/001003ED.pdf') | |
| 171 with pymupdf.open(path) as pdf_file: | |
| 172 page_no = 0 | |
| 173 page = pdf_file[page_no] | |
| 174 zoom_x = 4.0 | |
| 175 zoom_y = 4.0 | |
| 176 matrix = pymupdf.Matrix(zoom_x, zoom_y) | |
| 177 pix = page.get_pixmap(matrix=matrix) | |
| 178 path_out = os.path.normpath(f'{__file__}/../../tests/test_3050_out.png') | |
| 179 pix.save(path_out) | |
| 180 print(f'{pix.width=} {pix.height=}') | |
| 181 def product(x, y): | |
| 182 for yy in y: | |
| 183 for xx in x: | |
| 184 yield (xx, yy) | |
| 185 n = 0 | |
| 186 # We use a small subset of the image because non-optimised rebase gets | |
| 187 # very slow. | |
| 188 for pos in product(range(100), range(100)): | |
| 189 if sum(pix.pixel(pos[0], pos[1])) >= 600: | |
| 190 n += 1 | |
| 191 pix.set_pixel(pos[0], pos[1], (255, 255, 255)) | |
| 192 path_out2 = os.path.normpath(f'{__file__}/../../tests/test_3050_out2.png') | |
| 193 pix.save(path_out2) | |
| 194 path_expected = os.path.normpath(f'{__file__}/../../tests/resources/test_3050_expected.png') | |
| 195 rms = gentle_compare.pixmaps_rms(path_expected, path_out2) | |
| 196 print(f'{rms=}') | |
| 197 if pymupdf.mupdf_version_tuple < (1, 26): | |
| 198 # Slight differences in rendering from fix for mupdf bug 708274. | |
| 199 assert rms < 0.2 | |
| 200 else: | |
| 201 assert rms == 0 | |
| 202 wt = pymupdf.TOOLS.mupdf_warnings() | |
| 203 if pymupdf.mupdf_version_tuple >= (1, 26, 0): | |
| 204 assert wt == 'bogus font ascent/descent values (0 / 0)\nPDF stream Length incorrect' | |
| 205 else: | |
| 206 assert wt == 'PDF stream Length incorrect' | |
| 207 | |
| 208 def test_3058(): | |
| 209 doc = pymupdf.Document(os.path.abspath(f'{__file__}/../../tests/resources/test_3058.pdf')) | |
| 210 images = doc[0].get_images(full=True) | |
| 211 pix = pymupdf.Pixmap(doc, 17) | |
| 212 | |
| 213 # First bug was that `pix.colorspace` was DeviceRGB. | |
| 214 assert str(pix.colorspace) == 'Colorspace(CS_CMYK) - DeviceCMYK' | |
| 215 | |
| 216 pix = pymupdf.Pixmap(pymupdf.csRGB, pix) | |
| 217 assert str(pix.colorspace) == 'Colorspace(CS_RGB) - DeviceRGB' | |
| 218 | |
| 219 # Second bug was that the image was converted to RGB via greyscale proofing | |
| 220 # color space, so image contained only shades of grey. This compressed | |
| 221 # easily to a .png file, so we crudely check the bug is fixed by looking at | |
| 222 # size of .png file. | |
| 223 path = os.path.abspath(f'{__file__}/../../tests/test_3058_out.png') | |
| 224 pix.save(path) | |
| 225 s = os.path.getsize(path) | |
| 226 assert 1800000 < s < 2600000, f'Unexpected size of {path}: {s}' | |
| 227 | |
| 228 def test_3072(): | |
| 229 path = os.path.abspath(f'{__file__}/../../tests/resources/test_3072.pdf') | |
| 230 out = os.path.abspath(f'{__file__}/../../tests') | |
| 231 | |
| 232 doc = pymupdf.open(path) | |
| 233 page_48 = doc[0] | |
| 234 bbox = [147, 300, 447, 699] | |
| 235 rect = pymupdf.Rect(*bbox) | |
| 236 zoom = pymupdf.Matrix(3, 3) | |
| 237 pix = page_48.get_pixmap(clip=rect, matrix=zoom) | |
| 238 image_save_path = f'{out}/1.jpg' | |
| 239 pix.save(image_save_path, jpg_quality=95) | |
| 240 | |
| 241 doc = pymupdf.open(path) | |
| 242 page_49 = doc[1] | |
| 243 bbox = [147, 543, 447, 768] | |
| 244 rect = pymupdf.Rect(*bbox) | |
| 245 zoom = pymupdf.Matrix(3, 3) | |
| 246 pix = page_49.get_pixmap(clip=rect, matrix=zoom) | |
| 247 image_save_path = f'{out}/2.jpg' | |
| 248 pix.save(image_save_path, jpg_quality=95) | |
| 249 rebase = hasattr(pymupdf, 'mupdf') | |
| 250 if rebase: | |
| 251 wt = pymupdf.TOOLS.mupdf_warnings() | |
| 252 assert wt == ( | |
| 253 "syntax error: cannot find ExtGState resource 'BlendMode0'\n" | |
| 254 "encountered syntax errors; page may not be correct\n" | |
| 255 "syntax error: cannot find ExtGState resource 'BlendMode0'\n" | |
| 256 "encountered syntax errors; page may not be correct" | |
| 257 ) | |
| 258 | |
| 259 def test_3134(): | |
| 260 doc = pymupdf.Document() | |
| 261 page = doc.new_page() | |
| 262 page.get_pixmap(clip=pymupdf.Rect(0, 0, 100, 100)).save("test_3134_rect.jpg") | |
| 263 page.get_pixmap(clip=pymupdf.IRect(0, 0, 100, 100)).save("test_3134_irect.jpg") | |
| 264 stat_rect = os.stat('test_3134_rect.jpg') | |
| 265 stat_irect = os.stat('test_3134_irect.jpg') | |
| 266 print(f' {stat_rect=}') | |
| 267 print(f'{stat_irect=}') | |
| 268 assert stat_rect.st_size == stat_irect.st_size | |
| 269 | |
| 270 def test_3177(): | |
| 271 path = os.path.abspath(f'{__file__}/../../tests/resources/img-transparent.png') | |
| 272 pixmap = pymupdf.Pixmap(path) | |
| 273 pixmap2 = pymupdf.Pixmap(None, pixmap) | |
| 274 | |
| 275 | |
| 276 def test_3493(): | |
| 277 ''' | |
| 278 If python3-gi is installed, we check fix for #3493, where importing gi | |
| 279 would load an older version of libjpeg than is used in MuPDF, and break | |
| 280 MuPDF. | |
| 281 | |
| 282 This test is excluded by default in sysinstall tests, because running | |
| 283 commands in a new venv does not seem to pick up pymupdf as expected. | |
| 284 ''' | |
| 285 if platform.system() != 'Linux': | |
| 286 print(f'Not running because not Linux: {platform.system()=}') | |
| 287 return | |
| 288 | |
| 289 import subprocess | |
| 290 | |
| 291 root = os.path.abspath(f'{__file__}/../..') | |
| 292 in_path = f'{root}/tests/resources/test_3493.epub' | |
| 293 | |
| 294 def run(command, check=1, stdout=None): | |
| 295 print(f'Running with {check=}: {command}') | |
| 296 return subprocess.run(command, shell=1, check=check, stdout=stdout, text=1) | |
| 297 | |
| 298 def run_code(code, code_path, *, check=True, venv=None, venv_args='', pythonpath=None, stdout=None): | |
| 299 code = textwrap.dedent(code) | |
| 300 with open(code_path, 'w') as f: | |
| 301 f.write(code) | |
| 302 prefix = f'PYTHONPATH={pythonpath} ' if pythonpath else '' | |
| 303 if venv: | |
| 304 # Have seen this fail on Github in a curious way: | |
| 305 # | |
| 306 # Running: /tmp/tmp.fBeKNLJQKk/venv/bin/python -m venv --system-site-packages /project/tests/resources/test_3493_venv | |
| 307 # Error: [Errno 2] No such file or directory: '/project/tests/resources/test_3493_venv/bin/python' | |
| 308 # | |
| 309 r = run(f'{sys.executable} -m venv {venv_args} {venv}', check=check) | |
| 310 if r.returncode: | |
| 311 return r | |
| 312 r = run(f'. {venv}/bin/activate && {prefix}python {code_path}', check=check, stdout=stdout) | |
| 313 else: | |
| 314 r = run(f'{prefix}{sys.executable} {code_path}', check=check, stdout=stdout) | |
| 315 return r | |
| 316 | |
| 317 # Find location of system install of `gi`. | |
| 318 r = run_code( | |
| 319 ''' | |
| 320 from gi.repository import GdkPixbuf | |
| 321 import gi | |
| 322 print(gi.__file__) | |
| 323 ''' | |
| 324 , | |
| 325 f'{root}/tests/resources/test_3493_gi.py', | |
| 326 check=0, | |
| 327 venv=f'{root}/tests/resources/test_3493_venv', | |
| 328 venv_args='--system-site-packages', | |
| 329 stdout=subprocess.PIPE, | |
| 330 ) | |
| 331 if r.returncode: | |
| 332 print(f'test_3493(): Not running test because --system-site-packages venv cannot import gi.') | |
| 333 return | |
| 334 gi = r.stdout.strip() | |
| 335 gi_pythonpath = os.path.abspath(f'{gi}/../..') | |
| 336 | |
| 337 def do(gi): | |
| 338 # Run code that will import gi and pymupdf in different orders, and | |
| 339 # return contents of generated .png file as a bytes. | |
| 340 out = f'{root}/tests/resources/test_3493_{gi}.png' | |
| 341 run_code( | |
| 342 f''' | |
| 343 if {gi}==0: | |
| 344 import pymupdf | |
| 345 elif {gi}==1: | |
| 346 from gi.repository import GdkPixbuf | |
| 347 import pymupdf | |
| 348 elif {gi}==2: | |
| 349 import pymupdf | |
| 350 from gi.repository import GdkPixbuf | |
| 351 else: | |
| 352 assert 0 | |
| 353 document = pymupdf.Document('{in_path}') | |
| 354 page = document[0] | |
| 355 print(f'{gi=}: saving to: {out}') | |
| 356 page.get_pixmap().save('{out}') | |
| 357 ''' | |
| 358 , | |
| 359 os.path.abspath(f'{root}/tests/resources/test_3493_{gi}.py'), | |
| 360 pythonpath=gi_pythonpath, | |
| 361 ) | |
| 362 with open(out, 'rb') as f: | |
| 363 return f.read() | |
| 364 | |
| 365 out0 = do(0) | |
| 366 out1 = do(1) | |
| 367 out2 = do(2) | |
| 368 print(f'{len(out0)=} {len(out1)=} {len(out2)=}.') | |
| 369 assert out1 == out0 | |
| 370 assert out2 == out0 | |
| 371 | |
| 372 | |
| 373 def test_3848(): | |
| 374 if os.environ.get('PYMUPDF_RUNNING_ON_VALGRIND') == '1': | |
| 375 # Takes 40m on Github. | |
| 376 print(f'test_3848(): not running on valgrind because very slow.', flush=1) | |
| 377 return | |
| 378 if platform.python_implementation() == 'GraalVM': | |
| 379 print(f'test_3848(): Not running because slow on GraalVM.') | |
| 380 return | |
| 381 path = os.path.normpath(f'{__file__}/../../tests/resources/test_3848.pdf') | |
| 382 with pymupdf.open(path) as document: | |
| 383 for i in range(len(document)): | |
| 384 page = document.load_page(i) | |
| 385 print(f'{page=}.') | |
| 386 for annot in page.get_drawings(): | |
| 387 if page.get_textbox(annot['rect']): | |
| 388 rect = annot['rect'] | |
| 389 pixmap = page.get_pixmap(clip=rect) | |
| 390 color_bytes = pixmap.color_topusage() | |
| 391 | |
| 392 | |
| 393 def test_3994(): | |
| 394 path = os.path.normpath(f'{__file__}/../../tests/resources/test_3994.pdf') | |
| 395 with pymupdf.open(path) as document: | |
| 396 page = document[0] | |
| 397 txt_blocks = [blk for blk in page.get_text('dict')['blocks'] if blk['type']==0] | |
| 398 for blk in txt_blocks: | |
| 399 pix = page.get_pixmap(clip=pymupdf.Rect([int(v) for v in blk['bbox']]), colorspace=pymupdf.csRGB, alpha=False) | |
| 400 percent, color = pix.color_topusage() | |
| 401 wt = pymupdf.TOOLS.mupdf_warnings() | |
| 402 assert wt == 'premature end of data in flate filter\n... repeated 2 times...' | |
| 403 | |
| 404 | |
| 405 def test_3448(): | |
| 406 path = os.path.normpath(f'{__file__}/../../tests/resources/test_3448.pdf') | |
| 407 with pymupdf.open(path) as document: | |
| 408 page = document[0] | |
| 409 pixmap = page.get_pixmap(alpha=False, dpi=150) | |
| 410 path_out = f'{path}.png' | |
| 411 pixmap.save(path_out) | |
| 412 print(f'Have written to: {path_out}') | |
| 413 path_expected = os.path.normpath(f'{__file__}/../../tests/resources/test_3448.pdf-expected.png') | |
| 414 pixmap_expected = pymupdf.Pixmap(path_expected) | |
| 415 rms = gentle_compare.pixmaps_rms(pixmap, pixmap_expected) | |
| 416 diff = gentle_compare.pixmaps_diff(pixmap_expected, pixmap) | |
| 417 path_diff = os.path.normpath(f'{__file__}/../../tests/test_3448-diff.png') | |
| 418 diff.save(path_diff) | |
| 419 print(f'{rms=}') | |
| 420 if pymupdf.mupdf_version_tuple < (1, 25, 5): | |
| 421 # Prior to fix for mupdf bug 708274. | |
| 422 assert 1 < rms < 2 | |
| 423 else: | |
| 424 assert rms == 0 | |
| 425 | |
| 426 | |
| 427 def test_3854(): | |
| 428 path = os.path.normpath(f'{__file__}/../../tests/resources/test_3854.pdf') | |
| 429 with pymupdf.open(path) as document: | |
| 430 page = document[0] | |
| 431 pixmap = page.get_pixmap() | |
| 432 pixmap.save(os.path.normpath(f'{__file__}/../../tests/test_3854_out.png')) | |
| 433 | |
| 434 # 2024-11-29: this is the incorrect expected output. | |
| 435 path_expected_png = os.path.normpath(f'{__file__}/../../tests/resources/test_3854_expected.png') | |
| 436 pixmap_expected = pymupdf.Pixmap(path_expected_png) | |
| 437 pixmap_diff = gentle_compare.pixmaps_diff(pixmap_expected, pixmap) | |
| 438 path_diff = os.path.normpath(f'{__file__}/../../tests/resources/test_3854_diff.png') | |
| 439 pixmap_diff.save(path_diff) | |
| 440 rms = gentle_compare.pixmaps_rms(pixmap, pixmap_expected) | |
| 441 print(f'{rms=}.') | |
| 442 if os.environ.get('PYMUPDF_SYSINSTALL_TEST') == '1': | |
| 443 # MuPDF using external third-party libs gives slightly different | |
| 444 # behaviour. | |
| 445 assert rms < 2 | |
| 446 elif pymupdf.mupdf_version_tuple < (1, 25, 5): | |
| 447 # # Prior to fix for mupdf bug 708274. | |
| 448 assert 0.5 < rms < 2 | |
| 449 else: | |
| 450 assert rms == 0 | |
| 451 | |
| 452 | |
| 453 def test_4155(): | |
| 454 path = os.path.normpath(f'{__file__}/../../tests/resources/test_3854.pdf') | |
| 455 with pymupdf.open(path) as document: | |
| 456 page = document[0] | |
| 457 pixmap = page.get_pixmap() | |
| 458 mv = pixmap.samples_mv | |
| 459 mvb1 = mv.tobytes() | |
| 460 del page | |
| 461 del pixmap | |
| 462 try: | |
| 463 mvb2 = mv.tobytes() | |
| 464 except ValueError as e: | |
| 465 print(f'Received exception: {e}') | |
| 466 assert 'operation forbidden on released memoryview object' in str(e) | |
| 467 else: | |
| 468 assert 0, f'Did not receive expected exception when using defunct memoryview.' | |
| 469 | |
| 470 | |
| 471 def test_4336(): | |
| 472 if 0: | |
| 473 # Compare with last classic release. | |
| 474 import pickle | |
| 475 path_out = os.path.normpath(f'{__file__}/../../tests/resources/test_4336_cc') | |
| 476 code = textwrap.dedent(f''' | |
| 477 import fitz | |
| 478 import os | |
| 479 import time | |
| 480 import pickle | |
| 481 | |
| 482 path = os.path.normpath(f'{__file__}/../../tests/resources/nur-ruhig.jpg') | |
| 483 pixmap = fitz.Pixmap(path) | |
| 484 t = time.time() | |
| 485 for i in range(10): | |
| 486 cc = pixmap.color_count() | |
| 487 t = time.time() - t | |
| 488 print(f'test_4336(): {{t=}}') | |
| 489 with open({path_out!r}, 'wb') as f: | |
| 490 pickle.dump(cc, f) | |
| 491 ''') | |
| 492 path_code = os.path.normpath(f'{__file__}/../../tests/resources/test_4336.py') | |
| 493 with open(path_code, 'w') as f: | |
| 494 f.write(code) | |
| 495 venv = os.path.normpath(f'{__file__}/../../tests/resources/test_4336_venv') | |
| 496 command = f'{sys.executable} -m venv {venv}' | |
| 497 command += f' && . {venv}/bin/activate' | |
| 498 command += f' && pip install --force-reinstall pymupdf==1.23.8' | |
| 499 command += f' && python {path_code}' | |
| 500 print(f'Running: {command}', flush=1) | |
| 501 subprocess.run(command, shell=1, check=1) | |
| 502 with open(path_out, 'rb') as f: | |
| 503 cc_old = pickle.load(f) | |
| 504 else: | |
| 505 cc_old = None | |
| 506 path = os.path.normpath(f'{__file__}/../../tests/resources/nur-ruhig.jpg') | |
| 507 pixmap = pymupdf.Pixmap(path) | |
| 508 t = time.time() | |
| 509 for i in range(10): | |
| 510 cc = pixmap.color_count() | |
| 511 t = time.time() - t | |
| 512 print(f'test_4336(): {t=}') | |
| 513 | |
| 514 if cc_old: | |
| 515 assert cc == cc_old | |
| 516 | |
| 517 | |
| 518 def test_4435(): | |
| 519 print(f'{pymupdf.version=}') | |
| 520 path = os.path.normpath(f'{__file__}/../../tests/resources/test_4435.pdf') | |
| 521 with pymupdf.open(path) as document: | |
| 522 page = document[2] | |
| 523 print(f'Calling page.get_pixmap().', flush=1) | |
| 524 pixmap = page.get_pixmap(alpha=False, dpi=120) | |
| 525 print(f'Called page.get_pixmap().', flush=1) | |
| 526 wt = pymupdf.TOOLS.mupdf_warnings() | |
| 527 assert wt == 'bogus font ascent/descent values (0 / 0)\n... repeated 9 times...' | |
| 528 | |
| 529 | |
| 530 def test_4423(): | |
| 531 path = os.path.normpath(f'{__file__}/../../tests/resources/test_4423.pdf') | |
| 532 with pymupdf.open(path) as document: | |
| 533 path2 = f'{path}.pdf' | |
| 534 ee = None | |
| 535 try: | |
| 536 document.save( | |
| 537 path2, | |
| 538 garbage=4, | |
| 539 expand=1, | |
| 540 deflate=True, | |
| 541 pretty=True, | |
| 542 no_new_id=True, | |
| 543 ) | |
| 544 except Exception as e: | |
| 545 print(f'Exception: {e}') | |
| 546 ee = e | |
| 547 | |
| 548 if (1, 25, 5) <= pymupdf.mupdf_version_tuple < (1, 26): | |
| 549 assert ee, f'Did not receive the expected exception.' | |
| 550 wt = pymupdf.TOOLS.mupdf_warnings() | |
| 551 assert wt == 'dropping unclosed output' | |
| 552 else: | |
| 553 assert not ee, f'Received unexpected exception: {e}' | |
| 554 wt = pymupdf.TOOLS.mupdf_warnings() | |
| 555 assert wt == 'format error: cannot find object in xref (56 0 R)\nformat error: cannot find object in xref (68 0 R)' | |
| 556 | |
| 557 | |
| 558 def test_4445(): | |
| 559 print() | |
| 560 # Test case is large so we download it instead of having it in PyMuPDF | |
| 561 # git. We put it in `cache/` directory do it is not removed by `git clean` | |
| 562 # (unless `-d` is specified). | |
| 563 import util | |
| 564 path = util.download( | |
| 565 'https://github.com/user-attachments/files/19738242/ss.pdf', | |
| 566 'test_4445.pdf', | |
| 567 size=2671185, | |
| 568 ) | |
| 569 with pymupdf.open(path) as document: | |
| 570 page = document[0] | |
| 571 pixmap = page.get_pixmap() | |
| 572 print(f'{pixmap.width=}') | |
| 573 print(f'{pixmap.height=}') | |
| 574 if pymupdf.mupdf_version_tuple >= (1, 26): | |
| 575 assert (pixmap.width, pixmap.height) == (792, 612) | |
| 576 else: | |
| 577 assert (pixmap.width, pixmap.height) == (612, 792) | |
| 578 if 0: | |
| 579 path_pixmap = f'{path}.png' | |
| 580 pixmap.save(path_pixmap) | |
| 581 print(f'Have created {path_pixmap=}') | |
| 582 wt = pymupdf.TOOLS.mupdf_warnings() | |
| 583 print(f'{wt=}') | |
| 584 assert wt == 'broken xref subsection, proceeding anyway.\nTrailer Size is off-by-one. Ignoring.' | |
| 585 | |
| 586 | |
| 587 def test_3806(): | |
| 588 print() | |
| 589 print(f'{pymupdf.mupdf_version=}') | |
| 590 path = os.path.normpath(f'{__file__}/../../tests/resources/test_3806.pdf') | |
| 591 path_png_expected = os.path.normpath(f'{__file__}/../../tests/resources/test_3806-expected.png') | |
| 592 path_png = os.path.normpath(f'{__file__}/../../tests/test_3806.png') | |
| 593 | |
| 594 with pymupdf.open(path) as document: | |
| 595 pixmap = document[0].get_pixmap() | |
| 596 pixmap.save(path_png) | |
| 597 rms = gentle_compare.pixmaps_rms(path_png_expected, pixmap) | |
| 598 print(f'{rms=}') | |
| 599 if pymupdf.mupdf_version_tuple >= (1, 26, 6): | |
| 600 assert rms < 0.1 | |
| 601 else: | |
| 602 assert rms > 50 | |
| 603 | |
| 604 | |
| 605 def test_4388(): | |
| 606 print() | |
| 607 path_BOZ1 = os.path.normpath(f'{__file__}/../../tests/resources/test_4388_BOZ1.pdf') | |
| 608 path_BUL1 = os.path.normpath(f'{__file__}/../../tests/resources/test_4388_BUL1.pdf') | |
| 609 path_correct = os.path.normpath(f'{__file__}/../../tests/resources/test_4388_BUL1.pdf.correct.png') | |
| 610 path_test = os.path.normpath(f'{__file__}/../../tests/resources/test_4388_BUL1.pdf.test.png') | |
| 611 | |
| 612 with pymupdf.open(path_BUL1) as bul: | |
| 613 pixmap_correct = bul.load_page(0).get_pixmap() | |
| 614 pixmap_correct.save(path_correct) | |
| 615 | |
| 616 pymupdf.TOOLS.store_shrink(100) | |
| 617 | |
| 618 with pymupdf.open(path_BOZ1) as boz: | |
| 619 boz.load_page(0).get_pixmap() | |
| 620 | |
| 621 with pymupdf.open(path_BUL1) as bul: | |
| 622 pixmap_test = bul.load_page(0).get_pixmap() | |
| 623 pixmap_test.save(path_test) | |
| 624 | |
| 625 rms = gentle_compare.pixmaps_rms(pixmap_correct, pixmap_test) | |
| 626 print(f'{rms=}') | |
| 627 if pymupdf.mupdf_version_tuple >= (1, 26, 6): | |
| 628 assert rms == 0 | |
| 629 else: | |
| 630 assert rms >= 10 |
