Diferent result between pymupdf and mupdf_net

Hi there! I am converting a prototype (made using pymupdf to mupdf_net, and using the same commands (page.GetDrawings) and re-drawing using the same strategy in python and C#, I got different results… Anyone have any clue on how (or why) to solve this?

This is the python code:

“def draw_graphics_from(input_doc: pymupdf.Document, output_doc: pymupdf.Document) → pymupdf.Document:

\# page = input_doc\[0\] outpdf = output_doc #pymupdf.open() file_export = open('./assets/exported_paths_python.txt', 'w') for page_num, page in enumerate(input_doc): paths = page.get_drawings() outpage = outpdf.load_page(page_num) shape = outpage.new_shape() percent = 0 print(f'Drawing {len(paths)} items on page {page_num + 1}: ', flush=True, end=' ') for i, path in enumerate(paths): \# if i % (len(paths) // 10) == 0 and i > 0: \# percent += 10 \# print(f'{percent}%...', flush=True, end='') for item in path\["items"\]: # these are the draw commands if item\[0\] == "l": # line shape.draw_line(item\[1\], item\[2\]) file_export.write(f'{i:03}\] line: {item\[0\]} >>> {item\[1\]}, {item\[2\]}\\n') elif item\[0\] == "re": # rectangle shape.draw_rect(item\[1\]) file_export.write(f'{i:03}\] rect: {item\[0\]} >>> {item\[1\]}\\n') elif item\[0\] == "qu": # quad shape.draw_quad(item\[1\]) file_export.write(f'{i:03}\] quad: {item\[0\]} >>> {item\[1\]}\\n') elif item\[0\] == "c": # curve shape.draw_bezier(item\[1\], item\[2\], item\[3\], item\[4\]) file_export.write(f'{i:03}\] curve: {item\[0\]} >>> {item\[1\]}, {item\[2\]}, {item\[3\]}, {item\[4\]}\\n') else: raise ValueError("unhandled drawing", item) lwidth = path.get("width", 0.03) if type(lwidth) is not float: lwidth = float(DEFAUL_LINE_WIDTH) if lwidth <= 0.03: lwidth = float(DEFAUL_LINE_WIDTH) \# print(f'Path width: {lwidth}, type: {type(lwidth)}', flush=True) shape.finish( fill=path\["fill"\], # fill color color = (random.random(), random.random(), random.random()) if USE_RANDOM_COLORS else DEFAULT_COLOR, #path\["color"\], # line color dashes=path\["dashes"\], # line dashing even_odd=path.get("even_odd", True), # control color of overlaps closePath=path\["closePath"\], # whether to connect last and first point lineJoin= 1, #max(path.get("lineJoin", 0), 1), # how line joins should look like lineCap = 1, #(1, 1, 1), # max(path.get("lineCap", 1)), # how line ends should look like width = lwidth, # line_width, # path\["width"\], # line width stroke_opacity= 1, # path.get("stroke_opacity", 1.0), # same value for both fill_opacity= 1, #path.get("fill_opacity", 1.0), # opacity parameters ) file_export.write(f'Path {i:03}\] width: {lwidth}, dashes: {path\["dashes"\]}, closePath: {path\["closePath"\]}\\n') print('Done.', flush=True) shape.commit() file_export.close() return outpdf“ 

And this is the C# code:

“ public Document? draw_graphics_from(Document inputDoc, Document outputDoc, float newWidth, IProgress progress)
{

 string filePath = @"D:\\Vectorlab\\Jobs\\2025\\PACE\\pdf_fix\\assets\\exported_paths_net.txt"; StreamWriter writer = new StreamWriter(filePath); if (inputDoc.PageCount != outputDoc.PageCount) { return null; } for (int pagNum = 0; pagNum < inputDoc.PageCount; pagNum++) { Page page = inputDoc.LoadPage(pagNum); Page outPage = outputDoc.LoadPage(pagNum); List<PathInfo> paths = page.GetDrawings(extended: false); int totalPaths = paths.Count; Shape shape = outPage.NewShape(); int i = 0; progress.Report(0); foreach (PathInfo pathInfo in paths) { foreach (Item item in pathInfo.Items) { if (item != null) { if (item.Type == "l") { shape.DrawLine(item.P1, item.LastPoint); writer.Write($"{i:000}\] line: {item.Type} >>> {item.P1}, {item.LastPoint}\\n"); } else if (item.Type == "re") { shape.DrawRect(item.Rect, item.Orientation); writer.Write($"{i:000}\] rect: {item.Type} >>> {item.Rect}, {item.Orientation}\\n"); } else if(item.Type == "qu") { shape.DrawQuad(item.Quad); writer.Write($"{i:000}\] quad: {item.Type} >>> {item.Quad}\\n"); } else if(item.Type == "c") { shape.DrawBezier(item.P1, item.P2, item.P3, item.LastPoint); writer.Write($"{i:000}\] curve: {item.Type} >>> {item.P1}, {item.P2}, {item.P3}, {item.LastPoint}\\n"); } else { throw new Exception("unhandled drawing. Aborting..."); } } } //pathInfo.Items.get float newLineWidth = pathInfo.Width; if (pathInfo.Width <= newWidth) { newLineWidth = newWidth; } shape.Finish( fill: pathInfo.Fill, color: pathInfo.Color, //this.\_m_DEFAULT_COLOR, dashes: pathInfo.Dashes, evenOdd: true, //pathInfo.EvenOdd, closePath: pathInfo.ClosePath, lineJoin: (int)1, lineCap: (int)1, width: newLineWidth, strokeOpacity: (int)pathInfo.StrokeOpacity, fillOpacity: (int)pathInfo.FillOpacity ); double progressValue = ((double)i / (double)totalPaths) \* 100.0; progress.Report((int)progressValue); // file_export.write(f'Path {i:03}\] width: {lwidth}, dashes: {path\["dashes"\]}, closePath: {path\["closePath"\]}\\n') writer.Write($"Path {i:000}\] with: {newLineWidth}, dashes: {pathInfo.Dashes}, closePath: {pathInfo.ClosePath}\\n"); i++; } shape.Commit(); } writer.Close(); return outputDoc; }“ 

And the image above is the results

exported_paths_net.txt (18,9,KB)

exported_paths_python.txt (33,1,KB)

I also create this “debuging” info to see what was write to the PDF, and looks like the .net implementation has less data than the python:

@Fabio_Nascimento Implementations look sound in both. I guess, like you expect, the .NET is “finding” less data than the Python for some reason.

Can you confirm 3 things for me:

  1. version of PyMuPDF used?
  2. version of .NET used?
  3. Supply the input PDF you use if possible?

@Maksym_Tkachuk Please watch this post for updates and let us know what you think!

PyMuPDF version: 1.26.6

MuPDF.NET version: 3.2.11

drawing2.pdf (1,2,KB)

If you look in the exported txt, Path.Fill and Path.Color are not like the .py version… This may ring a bell on what is wrong, I guess…

@Fabio_Nascimento @Jamie_Lemon

I created new nuget release to fix this issue.

Please test this problem with 3.2.13-rc.1.

dotnet add package MuPDF.NET --version 3.2.13-rc.1

If any problem, please contact me at any time.

Thanks.

Nice one @Maksym_Tkachuk ! @Fabio_Nascimento Please do let us know if it resolves your issue!

Hey guys, first tests looks great! I will continue with differents pdf’s and report here if I find something… Thank you very much!

1 Like

Awesome!!!