Mercurial > hgrepos > Python2 > PyMuPDF
view mupdf-source/scripts/mupdfwrap_gui.cs @ 38:8934ac156ef5
Allow to build with the PyPI package "clang" instead of "libclang".
1. It seems to be maintained.
2. In the FreeBSD base system there is no pre-built libclang.so. If you
need this library you have to install llvm from ports additionally.
2. On FreeBSD there is no pre-built wheel "libclang" with a packaged
libclang.so.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Tue, 23 Sep 2025 10:27:15 +0200 |
| parents | b50eed0cc0ef |
| children |
line wrap: on
line source
// Basic PDF viewer using MuPDF C# bindings. // public class MuPDFGui : System.Windows.Forms.Form { // We use static pixmap to ensure it isn't garbage-collected. mupdf.FzPixmap pixmap; private System.Windows.Forms.MainMenu menu; private System.Windows.Forms.MenuItem menu_item_file; /* Zooming works by incrementing self.zoom by +/- 1 then using magnification = 2**(self.zoom/self.zoom_multiple). */ private int zoom_multiple = 4; private double zoom = 0; private int page_number = 0; mupdf.FzDocument document; mupdf.FzPage page; System.Drawing.Bitmap bitmap; System.Windows.Forms.PictureBox picture_box; // Need STAThread here otherwise OpenFileDialog hangs. [System.STAThread] public static void Main() { System.Windows.Forms.Application.Run(new MuPDFGui()); } public MuPDFGui() { menu_item_file = new System.Windows.Forms.MenuItem("File", new System.Windows.Forms.MenuItem[] { new System.Windows.Forms.MenuItem("&Open...", new System.EventHandler(this.open)), new System.Windows.Forms.MenuItem("&Show html", new System.EventHandler(this.show_html)), new System.Windows.Forms.MenuItem("&Quit", new System.EventHandler(this.quit)) } ); menu = new System.Windows.Forms.MainMenu(new System.Windows.Forms.MenuItem [] {menu_item_file}); this.Menu = menu; Resize += handle_resize; KeyDown += handle_key_down; this.picture_box = new System.Windows.Forms.PictureBox(); this.picture_box.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.AutoScroll = true; Controls.Add(picture_box); this.open_file("zlib.3.pdf"); } public void open(System.Object sender, System.EventArgs e) { var dialog = new System.Windows.Forms.OpenFileDialog(); var result = dialog.ShowDialog(); if (result == System.Windows.Forms.DialogResult.OK) { this.open_file(dialog.FileName); } } void open_file(string path) { try { this.document = new mupdf.FzDocument(path); } catch (System.Exception e) { System.Console.WriteLine("Failed to open: " + path + " because: " + e); return; } this.goto_page(0, 0); } public void show_html(System.Object sender, System.EventArgs e) { System.Console.WriteLine("ShowHtml() called"); var buffer = this.page.fz_new_buffer_from_page_with_format( "docx", "html", new mupdf.FzMatrix(1, 0, 0, 1, 0, 0), new mupdf.FzCookie() ); System.Console.WriteLine("buffer=" + buffer); var html_bytes = buffer.fz_buffer_extract(); var html_string = System.Text.Encoding.UTF8.GetString(html_bytes, 0, html_bytes.Length); var web_browser = new System.Windows.Forms.WebBrowser(); web_browser.DocumentText = html_string; web_browser.Show(); } public void quit(System.Object sender, System.EventArgs e) { System.Console.WriteLine("Quit() called"); System.Windows.Forms.Application.Exit(); } // Shows page. If width and/or height are zero we use .Width and/or .Height. // // To preserve current page and/or zoom, use .page_number and/or .zoom. // public void goto_page(int page_number, double zoom) { if (page_number < 0 || page_number >= document.fz_count_pages()) { return; } this.zoom = zoom; this.page_number = page_number; this.page = document.fz_load_page(page_number); var z = System.Math.Pow(2, this.zoom / this.zoom_multiple); /* For now we always use 'fit width' view semantics. */ var page_rect = this.page.fz_bound_page(); var vscroll_width = System.Windows.Forms.SystemInformation.VerticalScrollBarWidth; z *= (this.ClientSize.Width - vscroll_width) / (page_rect.x1 - page_rect.x0); if (System.Type.GetType("Mono.Runtime") != null) { /* Use pixmap data without copying. This does not work on Windows. It looks like it's important to use MuPDF Fixed_RGB with alpha=1, and C#'s Format32bppRgb. Other combinations, e.g. (Fixed_RGB with alpha=0) and Format24bppRgb, result in a blank display. */ var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Reset(); stopwatch.Start(); this.pixmap = this.page.fz_new_pixmap_from_page_contents( new mupdf.FzMatrix((float) z, 0, 0, (float) z, 0, 0), new mupdf.FzColorspace(mupdf.FzColorspace.Fixed.Fixed_RGB), 1 /*alpha*/ ); stopwatch.Stop(); var t_pixmap = stopwatch.Elapsed; stopwatch.Reset(); stopwatch.Start(); this.bitmap = new System.Drawing.Bitmap( this.pixmap.fz_pixmap_width(), this.pixmap.fz_pixmap_height(), this.pixmap.fz_pixmap_stride(), System.Drawing.Imaging.PixelFormat.Format32bppRgb, (System.IntPtr) this.pixmap.fz_pixmap_samples_int() ); stopwatch.Stop(); var t_bitmap = stopwatch.Elapsed; stopwatch.Reset(); stopwatch.Start(); // This is slow for large pixmaps/bitmaps. //check(pixmap, bitmap, 4); stopwatch.Stop(); var t_check = stopwatch.Elapsed; /*System.Console.WriteLine("" + " t_pixmap=" + t_pixmap + " t_bitmap=" + t_bitmap + " t_check=" + t_check );*/ } else { /* Copy pixmap's pixels into bitmap. This works on both Linux (Mono) and Windows. Unlike above, it seems that we need to use MuPDF Fixed_RGB with alpha=0, and C#'s Format32bppRgb. Other combinations give a blank display (possibly with alpha=0 for each pixel). */ this.pixmap = this.page.fz_new_pixmap_from_page_contents( new mupdf.FzMatrix((float) z, 0, 0, (float) z, 0, 0), new mupdf.FzColorspace(mupdf.FzColorspace.Fixed.Fixed_RGB), 0 /*alpha*/ ); this.bitmap = new System.Drawing.Bitmap( this.pixmap.fz_pixmap_width(), this.pixmap.fz_pixmap_height(), System.Drawing.Imaging.PixelFormat.Format32bppRgb ); long samples = pixmap.fz_pixmap_samples_int(); int stride = pixmap.fz_pixmap_stride(); for (int x=0; x<bitmap.Width; x+=1) { for (int y=0; y<bitmap.Height; y+=1) { unsafe { byte* sample = (byte*) samples + stride * y + 3 * x; var color = System.Drawing.Color.FromArgb(sample[0], sample[1], sample[2]); this.bitmap.SetPixel( x, y, color); } } } //check(pixmap, bitmap, 3); } this.picture_box.Image = this.bitmap; } private void handle_key_down(object sender, System.Windows.Forms.KeyEventArgs e) { //System.Console.WriteLine("HandleKeyDown: " + e.KeyCode); if (e.Shift && e.KeyCode == System.Windows.Forms.Keys.PageUp) { goto_page(this.page_number - 1, this.zoom); } else if (e.Shift && e.KeyCode == System.Windows.Forms.Keys.PageDown) { goto_page(this.page_number + 1, this.zoom); } else if (e.KeyCode == System.Windows.Forms.Keys.D0) { goto_page(this.page_number, 0); } else if (e.KeyCode == System.Windows.Forms.Keys.Add || e.KeyCode == System.Windows.Forms.Keys.Oemplus ) { goto_page(this.page_number, this.zoom + 1); } else if (e.KeyCode == System.Windows.Forms.Keys.Subtract || e.KeyCode == System.Windows.Forms.Keys.OemMinus) { goto_page(this.page_number, this.zoom - 1); } } private void handle_resize(object sender, System.EventArgs e) { goto_page(page_number, zoom); } // Throws exception if pixmap and bitmap differ. void check(mupdf.FzPixmap pixmap, System.Drawing.Bitmap bitmap, int pixmap_bytes_per_pixel) { long samples = pixmap.fz_pixmap_samples_int(); if (pixmap.fz_pixmap_width() != bitmap.Width || pixmap.fz_pixmap_height() != bitmap.Height) { throw new System.Exception("Inconsistent sizes:" + " pixmap=(" + pixmap.fz_pixmap_width() + " " + pixmap.fz_pixmap_height() + " bitmap=(" + bitmap.Width + " " + bitmap.Height ); } int stride = pixmap.fz_pixmap_stride(); for (int x=0; x<bitmap.Width; x+=1) { for (int y=0; y<bitmap.Height; y+=1) { unsafe { byte* sample = (byte*) samples + stride * y + pixmap_bytes_per_pixel * x; System.Drawing.Color color = bitmap.GetPixel( x, y); if (color.R != sample[0] || color.G != sample[1] || color.B != sample[2]) { string pixmap_pixel_text = ""; for (int i=0; i<pixmap_bytes_per_pixel; ++i) { if (i > 0) pixmap_pixel_text += " "; pixmap_pixel_text += sample[i]; } throw new System.Exception("Pixels differ: (" + x + " " + y + "):" + " pixmap: (" + pixmap_pixel_text + ")" + " bitmap: " + color); } } } } } }
