| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- // 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);
- }
- }
- }
- }
- }
- }
|