PyMuPDF 1.23.14__tar.gz → 1.23.16__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/PKG-INFO +1 -1
  2. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/changes.txt +24 -0
  3. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/scripts/sysinstall.py +1 -1
  4. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/setup.py +1 -1
  5. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src/__init__.py +27 -10
  6. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src/extra.i +59 -0
  7. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src/table.py +18 -10
  8. PyMuPDF-1.23.16/src_classic/version.i +7 -0
  9. PyMuPDF-1.23.16/tests/resources/test_3058.pdf +0 -0
  10. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_pixmap.py +55 -0
  11. PyMuPDF-1.23.14/src_classic/version.i +0 -7
  12. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/COPYING +0 -0
  13. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/MANIFEST.in +0 -0
  14. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/README.md +0 -0
  15. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/READMErb.md +0 -0
  16. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/mupdf.tgz +0 -0
  17. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/pipcl.py +0 -0
  18. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/pyproject.toml +0 -0
  19. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/pytest.ini +0 -0
  20. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/scripts/gh_release.py +0 -0
  21. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/scripts/test.py +0 -0
  22. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src/__main__.py +0 -0
  23. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src/fitz.py +0 -0
  24. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src/utils.py +0 -0
  25. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/__init__.py +0 -0
  26. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/__main__.py +0 -0
  27. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/_config.h +0 -0
  28. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/fitz_old.i +0 -0
  29. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-annot.i +0 -0
  30. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-convert.i +0 -0
  31. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-defines.i +0 -0
  32. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-devices.i +0 -0
  33. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-fields.i +0 -0
  34. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-fileobj.i +0 -0
  35. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-geo-c.i +0 -0
  36. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-geo-py.i +0 -0
  37. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-globals.i +0 -0
  38. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-other.i +0 -0
  39. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-pdfinfo.i +0 -0
  40. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-pixmap.i +0 -0
  41. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-portfolio.i +0 -0
  42. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-python.i +0 -0
  43. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-select.i +0 -0
  44. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-stext.i +0 -0
  45. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/helper-xobject.i +0 -0
  46. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/src_classic/utils.py +0 -0
  47. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/README.md +0 -0
  48. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/001003ED.pdf +0 -0
  49. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/1.pdf +0 -0
  50. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/2.pdf +0 -0
  51. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/2201.00069.pdf +0 -0
  52. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/3.pdf +0 -0
  53. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/4.pdf +0 -0
  54. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/Bezier.epub +0 -0
  55. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/PragmaticaC.otf +0 -0
  56. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/bug1945.pdf +0 -0
  57. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/bug1971.pdf +0 -0
  58. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/chinese-tables.pdf +0 -0
  59. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/chinese-tables.pickle +0 -0
  60. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/circular-toc.pdf +0 -0
  61. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/cython.pdf +0 -0
  62. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/cython.pickle +0 -0
  63. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/full_toc.txt +0 -0
  64. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/full_toc2.txt +0 -0
  65. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/github_sample.pdf +0 -0
  66. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/has-bad-fonts.pdf +0 -0
  67. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/image-file1.pdf +0 -0
  68. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/img-transparent.png +0 -0
  69. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/joined.pdf +0 -0
  70. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/metadata.txt +0 -0
  71. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/mupdf_explored.pdf +0 -0
  72. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/nur-ruhig.jpg +0 -0
  73. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/quad-calc-0.pdf +0 -0
  74. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/simple_toc.txt +0 -0
  75. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/symbol-list.pdf +0 -0
  76. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/symbols.txt +0 -0
  77. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test-2333.pdf +0 -0
  78. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test-2462.pdf +0 -0
  79. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test2093.pdf +0 -0
  80. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test2182.pdf +0 -0
  81. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test2238.pdf +0 -0
  82. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_1645_expected.pdf +0 -0
  83. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_1645_expected_1.22.pdf +0 -0
  84. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_1824.pdf +0 -0
  85. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2108.pdf +0 -0
  86. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2270.pdf +0 -0
  87. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2533.pdf +0 -0
  88. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2548.pdf +0 -0
  89. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2553-2.pdf +0 -0
  90. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2553.pdf +0 -0
  91. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2596.pdf +0 -0
  92. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2608_expected +0 -0
  93. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2634.pdf +0 -0
  94. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2635.pdf +0 -0
  95. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2645_1.pdf +0 -0
  96. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2645_2.pdf +0 -0
  97. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2645_3.pdf +0 -0
  98. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2710.pdf +0 -0
  99. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2730.pdf +0 -0
  100. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2788.pdf +0 -0
  101. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2791_content.pdf +0 -0
  102. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2791_coverpage.pdf +0 -0
  103. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2861.pdf +0 -0
  104. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2871.pdf +0 -0
  105. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2904.pdf +0 -0
  106. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2907.pdf +0 -0
  107. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2954.pdf +0 -0
  108. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2957_1.pdf +0 -0
  109. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2957_2.pdf +0 -0
  110. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2969.pdf +0 -0
  111. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_2979.pdf +0 -0
  112. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/test_delete_image.pdf +0 -0
  113. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/type3font.pdf +0 -0
  114. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/v110-changes.pdf +0 -0
  115. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/resources/widgettest.pdf +0 -0
  116. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/run_compound.py +0 -0
  117. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_2548.py +0 -0
  118. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_2634.py +0 -0
  119. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_2791.py +0 -0
  120. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_2904.py +0 -0
  121. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_2907.py +0 -0
  122. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_annots.py +0 -0
  123. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_badfonts.py +0 -0
  124. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_crypting.py +0 -0
  125. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_docs_samples.py +0 -0
  126. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_drawings.py +0 -0
  127. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_embeddedfiles.py +0 -0
  128. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_extractimage.py +0 -0
  129. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_flake8.py +0 -0
  130. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_font.py +0 -0
  131. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_general.py +0 -0
  132. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_geometry.py +0 -0
  133. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_imagebbox.py +0 -0
  134. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_insertimage.py +0 -0
  135. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_insertpdf.py +0 -0
  136. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_linequad.py +0 -0
  137. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_metadata.py +0 -0
  138. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_named_links.py +0 -0
  139. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_nonpdf.py +0 -0
  140. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_object_manipulation.py +0 -0
  141. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_optional_content.py +0 -0
  142. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_pagedelete.py +0 -0
  143. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_pagelabels.py +0 -0
  144. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_showpdfpage.py +0 -0
  145. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_story.py +0 -0
  146. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_tables.py +0 -0
  147. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_tesseract.py +0 -0
  148. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_textbox.py +0 -0
  149. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_textextract.py +0 -0
  150. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_textsearch.py +0 -0
  151. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_toc.py +0 -0
  152. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_widgets.py +0 -0
  153. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/tests/test_word_delimiters.py +0 -0
  154. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/valgrind.supp +0 -0
  155. {PyMuPDF-1.23.14 → PyMuPDF-1.23.16}/wdev.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyMuPDF
3
- Version: 1.23.14
3
+ Version: 1.23.16
4
4
  Summary: A high performance Python library for data extraction, analysis, conversion & manipulation of PDF (and other) documents.
5
5
  Description-Content-Type: text/markdown
6
6
  Author: Artifex
@@ -2,6 +2,30 @@ Change Log
2
2
  ==========
3
3
 
4
4
 
5
+ **Changes in version 1.23.16 (2024-01-18)**
6
+
7
+ * Bug fixes:
8
+
9
+ * **Fixed** `3058 <https://github.com/pymupdf/PyMuPDF/issues/3058>`_: Pixmap created from CMYK JPEG delivers RGB format
10
+
11
+ * Other:
12
+
13
+ * In table detection strategy "lines_strict", exclude fill-only vector graphics.
14
+ * Fixed sysinstall test failure.
15
+ * In documentation, update feature matrix with item about text writing.
16
+
17
+
18
+ **Changes in version 1.23.15 (2024-01-16)**
19
+
20
+ * Bug fixes:
21
+
22
+ * **Fixed** `3050 <https://github.com/pymupdf/PyMuPDF/issues/3050>`_: python3.9 pix.set_pixel has something wrong in c.append( ord(i))
23
+
24
+ * Other:
25
+
26
+ * Improved docs for Page.find_tables().
27
+
28
+
5
29
  **Changes in version 1.23.14 (2024-01-15)**
6
30
 
7
31
  * Bug fixes:
@@ -291,7 +291,7 @@ def main():
291
291
  # PyMuPDF.
292
292
  command = f'. {test_venv}/bin/activate'
293
293
  command += f' && LD_LIBRARY_PATH={root_prefix}/lib PYTHONPATH={pythonpath}'
294
- command += f' pytest -k "not test_color_count" {pymupdf_dir}'
294
+ command += f' pytest -k "not test_color_count and not test_3050" {pymupdf_dir}'
295
295
  run(command)
296
296
 
297
297
 
@@ -1072,7 +1072,7 @@ with open( f'{g_root}/READMErb.md', encoding='utf-8') as f:
1072
1072
  # We generate different wheels depending on g_flavour.
1073
1073
  #
1074
1074
 
1075
- version = '1.23.14'
1075
+ version = '1.23.16'
1076
1076
  version_b = '1.23.9'
1077
1077
 
1078
1078
  tag_python = None
@@ -2396,7 +2396,9 @@ class Colorspace:
2396
2396
 
2397
2397
  def __init__(self, type_):
2398
2398
  """Supported are GRAY, RGB and CMYK."""
2399
- if type_ == CS_GRAY:
2399
+ if isinstance( type_, mupdf.FzColorspace):
2400
+ self.this = type_
2401
+ elif type_ == CS_GRAY:
2400
2402
  self.this = mupdf.FzColorspace(mupdf.FzColorspace.Fixed_GRAY)
2401
2403
  elif type_ == CS_CMYK:
2402
2404
  self.this = mupdf.FzColorspace(mupdf.FzColorspace.Fixed_CMYK)
@@ -7759,8 +7761,8 @@ class Page:
7759
7761
  else:
7760
7762
  pm = mupdf.fz_convert_pixmap(
7761
7763
  arg_pix,
7762
- mupdf.FzColorspace(0),
7763
- mupdf.FzColorspace(0),
7764
+ mupdf.FzColorspace(),
7765
+ mupdf.FzColorspace(),
7764
7766
  mupdf.FzDefaultColorspaces(None),
7765
7767
  mupdf.FzColorParams(),
7766
7768
  1,
@@ -9429,7 +9431,7 @@ class Pixmap:
9429
9431
  self.this = mupdf.fz_convert_pixmap(
9430
9432
  spix,
9431
9433
  cs,
9432
- mupdf.FzColorspace(0),
9434
+ mupdf.FzColorspace(),
9433
9435
  mupdf.FzDefaultColorspaces(None),
9434
9436
  mupdf.FzColorParams(),
9435
9437
  1
@@ -9647,6 +9649,11 @@ class Pixmap:
9647
9649
  text += f' {type(arg)}: {arg}\n'
9648
9650
  raise Exception( text)
9649
9651
 
9652
+ # 2024-01-16: Experimental support for a memory-view of the underlying
9653
+ # data. Doesn't seem to make much difference to Pixmap.set_pixel() so
9654
+ # not currently used.
9655
+ self._memory_view = None
9656
+
9650
9657
  def __len__(self):
9651
9658
  return self.size
9652
9659
 
@@ -10117,20 +10124,28 @@ class Pixmap:
10117
10124
 
10118
10125
  def set_pixel(self, x, y, color):
10119
10126
  """Set color of pixel (x, y)."""
10127
+ if g_use_extra:
10128
+ return extra.set_pixel(self.this.m_internal, x, y, color)
10120
10129
  pm = self.this
10121
10130
  if not _INRANGE(x, 0, pm.w() - 1) or not _INRANGE(y, 0, pm.h() - 1):
10122
10131
  raise ValueError( MSG_PIXEL_OUTSIDE)
10123
10132
  n = pm.n()
10124
- c = list()
10125
10133
  for j in range(n):
10126
10134
  i = color[j]
10127
10135
  if not _INRANGE(i, 0, 255):
10128
10136
  raise ValueError( MSG_BAD_COLOR_SEQ)
10129
- c.append( ord(i))
10130
10137
  stride = mupdf.fz_pixmap_stride( pm)
10131
10138
  i = stride * y + n * x
10132
- for j in range(n):
10133
- pm.m_internal.samples[i + j] = c[j]
10139
+ if 0:
10140
+ # Using a cached self._memory_view doesn't actually make much
10141
+ # difference to speed.
10142
+ if not self._memory_view:
10143
+ self._memory_view = self.samples_mv
10144
+ for j in range(n):
10145
+ self._memory_view[i + j] = color[j]
10146
+ else:
10147
+ for j in range(n):
10148
+ pm.fz_samples_set(i + j, color[j])
10134
10149
 
10135
10150
  def set_rect(self, bbox, color):
10136
10151
  """Set color of all pixels in bbox."""
@@ -10154,6 +10169,8 @@ class Pixmap:
10154
10169
  JM_Warning("ignoring shrink factor < 1")
10155
10170
  return
10156
10171
  mupdf.fz_subsample_pixmap( self.this, factor)
10172
+ # Pixmap has changed so clear our memory view.
10173
+ self._memory_view = None
10157
10174
 
10158
10175
  @property
10159
10176
  def size(self):
@@ -21739,8 +21756,8 @@ def int_rc(text):
21739
21756
  return int(text)
21740
21757
 
21741
21758
  VersionFitz = "1.23.9" # MuPDF version.
21742
- VersionBind = "1.23.14" # PyMuPDF version.
21743
- VersionDate = "2024-01-15 00:00:01"
21759
+ VersionBind = "1.23.16" # PyMuPDF version.
21760
+ VersionDate = "2024-01-18 00:00:01"
21744
21761
  VersionDate2 = VersionDate.replace('-', '').replace(' ', '').replace(':', '')
21745
21762
  version = (VersionBind, VersionFitz, VersionDate2)
21746
21763
  pymupdf_version_tuple = tuple( [int_rc(i) for i in VersionBind.split('.')])
@@ -3670,6 +3670,7 @@ PyObject* extractBLOCKS(mupdf::FzStextPage& self)
3670
3670
  mupdf::fz_clear_buffer(res); // set text buffer to empty
3671
3671
  int line_n = -1;
3672
3672
  int last_char = 0;
3673
+ (void) line_n; /* Not actually used, but keeping in the code for now. */
3673
3674
  for (fz_stext_line* line = block->u.t.first_line; line; line = line->next)
3674
3675
  {
3675
3676
  line_n++;
@@ -3954,6 +3955,62 @@ int pixmap_n(mupdf::FzPixmap& pixmap)
3954
3955
  return mupdf::fz_pixmap_components( pixmap);
3955
3956
  }
3956
3957
 
3958
+ static int
3959
+ JM_INT_ITEM(PyObject *obj, Py_ssize_t idx, int *result)
3960
+ {
3961
+ PyObject *temp = PySequence_ITEM(obj, idx);
3962
+ if (!temp) return 1;
3963
+ if (PyLong_Check(temp)) {
3964
+ *result = (int) PyLong_AsLong(temp);
3965
+ Py_DECREF(temp);
3966
+ } else if (PyFloat_Check(temp)) {
3967
+ *result = (int) PyFloat_AsDouble(temp);
3968
+ Py_DECREF(temp);
3969
+ } else {
3970
+ Py_DECREF(temp);
3971
+ return 1;
3972
+ }
3973
+ if (PyErr_Occurred()) {
3974
+ PyErr_Clear();
3975
+ return 1;
3976
+ }
3977
+ return 0;
3978
+ }
3979
+
3980
+ PyObject *set_pixel(fz_pixmap* pm, int x, int y, PyObject *color)
3981
+ {
3982
+ fz_context* ctx = mupdf::internal_context_get();
3983
+ if (0
3984
+ || x < 0
3985
+ || x >= pm->w
3986
+ || y < 0
3987
+ || y >= pm->h
3988
+ )
3989
+ {
3990
+ throw std::range_error( MSG_PIXEL_OUTSIDE);
3991
+ }
3992
+ int n = pm->n;
3993
+ if (!PySequence_Check(color) || PySequence_Size(color) != n) {
3994
+ throw std::range_error(MSG_BAD_COLOR_SEQ);
3995
+ }
3996
+ int i, j;
3997
+ unsigned char c[5];
3998
+ for (j = 0; j < n; j++) {
3999
+ if (JM_INT_ITEM(color, j, &i) == 1) {
4000
+ throw std::range_error(MSG_BAD_COLOR_SEQ);
4001
+ }
4002
+ if (i < 0 or i >= 256) {
4003
+ throw std::range_error(MSG_BAD_COLOR_SEQ);
4004
+ }
4005
+ c[j] = (unsigned char) i;
4006
+ }
4007
+ int stride = fz_pixmap_stride(ctx, pm);
4008
+ i = stride * y + n * x;
4009
+ for (j = 0; j < n; j++) {
4010
+ pm->samples[i + j] = c[j];
4011
+ }
4012
+ Py_RETURN_NONE;
4013
+ }
3957
4014
  //-------------------------------------------
3958
4015
  // make a buffer from an stext_page's text
3959
4016
  //-------------------------------------------
@@ -4409,3 +4466,5 @@ PyObject *pixmap_pixel(fz_pixmap* pm, int x, int y);
4409
4466
  int pixmap_n(mupdf::FzPixmap& pixmap);
4410
4467
 
4411
4468
  PyObject* JM_search_stext_page(fz_stext_page *page, const char *needle);
4469
+
4470
+ PyObject *set_pixel(fz_pixmap* pm, int x, int y, PyObject *color);
@@ -1886,8 +1886,24 @@ def make_edges(page, clip=None, tset=None):
1886
1886
 
1887
1887
  parea = abs(page.rect) * 0.8 # area of the full page (80%)
1888
1888
 
1889
- # exclude graphics that are too large
1890
- paths = [p for p in page.get_drawings() if abs(p["rect"]) < parea]
1889
+ # exclude irrelevant graphics
1890
+ paths = []
1891
+ for p in page.get_drawings():
1892
+ if abs(p["rect"]) >= parea:
1893
+ continue
1894
+ if "s" in p["type"]:
1895
+ paths.append(p)
1896
+ continue
1897
+ if (
1898
+ p["rect"].width > 3
1899
+ and p["rect"].height > 3
1900
+ and (
1901
+ tset.vertical_strategy == "lines_strict"
1902
+ or tset.horizontal_strategy == "lines_strict"
1903
+ )
1904
+ ):
1905
+ continue
1906
+ paths.append(p)
1891
1907
 
1892
1908
  # make a list of vector graphics rectangles (IRects are sufficient)
1893
1909
  prects = sorted([p["rect"] for p in paths], key=lambda r: (r.y1, r.x0))
@@ -1998,14 +2014,6 @@ def make_edges(page, clip=None, tset=None):
1998
2014
  return line_dict
1999
2015
 
2000
2016
  for p in paths:
2001
- if p["type"] == "f" and p["fill"] == (1, 1, 1):
2002
- continue
2003
- if p["type"] == "f" and p["rect"].width > 3 and p["rect"].height > 3:
2004
- if (
2005
- tset.vertical_strategy == "lines_strict"
2006
- or tset.horizontal_strategy == "lines_strict"
2007
- ):
2008
- continue
2009
2017
  items = p["items"] # items in this path
2010
2018
 
2011
2019
  # if 'closePath', add a line from last to first point
@@ -0,0 +1,7 @@
1
+ %pythoncode %{
2
+ VersionFitz = "1.23.9" # MuPDF version.
3
+ VersionBind = "1.23.16" # PyMuPDF version.
4
+ VersionDate = "2024-01-18 00:00:01"
5
+ version = (VersionBind, VersionFitz, "20240118000001")
6
+ pymupdf_version_tuple = tuple( [int(i) for i in VersionFitz.split('.')])
7
+ %}
@@ -94,6 +94,10 @@ def test_setalpha():
94
94
  assert t == alphas
95
95
 
96
96
  def test_color_count():
97
+ '''
98
+ This is known to fail if MuPDF is built without PyMuPDF's custom config.h,
99
+ e.g. in Linux system installs.
100
+ '''
97
101
  pm = fitz.Pixmap(imgfile)
98
102
  assert pm.color_count() == 40624
99
103
 
@@ -152,3 +156,54 @@ def test_3020():
152
156
  pm2 = fitz.Pixmap(pm, 20, 30, None)
153
157
  pm3 = fitz.Pixmap(fitz.csGRAY, pm)
154
158
  pm4 = fitz.Pixmap(pm, pm3)
159
+
160
+ def test_3050():
161
+ '''
162
+ This is known to fail if MuPDF is built without it's default third-party
163
+ libraries, e.g. in Linux system installs.
164
+ '''
165
+ pdf_file = fitz.open(pdf)
166
+ for page_no, page in enumerate(pdf_file):
167
+ zoom_x = 4.0
168
+ zoom_y = 4.0
169
+ matrix = fitz.Matrix(zoom_x, zoom_y)
170
+ pix = page.get_pixmap(matrix=matrix)
171
+ digest0 = pix.digest
172
+ print(f'{pix.width=} {pix.height=}')
173
+ def product(x, y):
174
+ for yy in y:
175
+ for xx in x:
176
+ yield (xx, yy)
177
+ n = 0
178
+ # We use a small subset of the image because non-optimised rebase gets
179
+ # very slow.
180
+ for pos in product(range(100), range(100)):
181
+ if sum(pix.pixel(pos[0], pos[1])) >= 600:
182
+ n += 1
183
+ pix.set_pixel(pos[0], pos[1], (255, 255, 255))
184
+ digest1 = pix.digest
185
+ print(f'{page_no=} {n=} {digest0=} {digest1=}')
186
+ digest_expected = b'\xd7x\x94_\x98\xa1<-/\xf3\xf9\x04\xec#\xaa\xee'
187
+ pix.save(os.path.abspath(f'{__file__}/../../tests/test_3050_out.png'))
188
+ assert digest1 != digest0
189
+ assert digest1 == digest_expected
190
+
191
+ def test_3058():
192
+ doc = fitz.Document(os.path.abspath(f'{__file__}/../../tests/resources/test_3058.pdf'))
193
+ images = doc[0].get_images(full=True)
194
+ pix = fitz.Pixmap(doc, 17)
195
+
196
+ # First bug was that `pix.colorspace` was DeviceRGB.
197
+ assert str(pix.colorspace) == 'Colorspace(CS_CMYK) - DeviceCMYK'
198
+
199
+ pix = fitz.Pixmap(fitz.csRGB, pix)
200
+ assert str(pix.colorspace) == 'Colorspace(CS_RGB) - DeviceRGB'
201
+
202
+ # Second bug was that the image was converted to RGB via greyscale proofing
203
+ # color space, so image contained only shades of grey. This compressed
204
+ # easily to a .png file, so we crudely check the bug is fixed by looking at
205
+ # size of .png file.
206
+ path = os.path.abspath(f'{__file__}/../../tests/test_3058_out.png')
207
+ pix.save(path)
208
+ s = os.path.getsize(path)
209
+ assert 1800000 < s < 2600000, f'Unexpected size of {path}: {s}'
@@ -1,7 +0,0 @@
1
- %pythoncode %{
2
- VersionFitz = "1.23.9" # MuPDF version.
3
- VersionBind = "1.23.14" # PyMuPDF version.
4
- VersionDate = "2024-01-15 00:00:01"
5
- version = (VersionBind, VersionFitz, "20240115000001")
6
- pymupdf_version_tuple = tuple( [int(i) for i in VersionFitz.split('.')])
7
- %}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes