/// <summary> /// Creates a new <see cref="RasterImage"/> from the specified file. /// </summary> /// <param name="fileName">The path to the file containing the image.</param> /// <param name="pageNumber">The number of the page in the file from which the image should be created, starting at 0. Only useful for multi-page formats, such as PDF.</param> /// <param name="scale">The scale factor at which to render the image.</param> /// <param name="alpha">A boolean value indicating whether transparency (alpha) data from the image should be preserved or not.</param> /// <param name="interpolate">A boolean value indicating whether the image should be interpolated when it is resized or not.</param> public RasterImageFile(string fileName, int pageNumber = 0, double scale = 1, bool alpha = true, bool interpolate = true) { using (MuPDFContext context = new MuPDFContext()) { using (MuPDFDocument document = new MuPDFDocument(context, fileName)) { RoundedRectangle roundedBounds = document.Pages[pageNumber].Bounds.Round(scale); this.Width = roundedBounds.Width; this.Height = roundedBounds.Height; this.HasAlpha = alpha; this.Interpolate = interpolate; this.Id = Guid.NewGuid().ToString(); int imageSize = document.GetRenderedSize(pageNumber, scale, alpha ? MuPDFCore.PixelFormats.RGBA : MuPDFCore.PixelFormats.RGB); this.ImageDataAddress = Marshal.AllocHGlobal(imageSize); this.DataHolder = new DisposableIntPtr(this.ImageDataAddress); GC.AddMemoryPressure(imageSize); document.Render(pageNumber, scale, alpha ? MuPDFCore.PixelFormats.RGBA : MuPDFCore.PixelFormats.RGB, this.ImageDataAddress); } } }
static void Main() { //Initialise the MuPDF context. This is needed to open or create documents. using MuPDFContext ctx = new MuPDFContext(); //Open a PDF document using MuPDFDocument doc1 = new MuPDFDocument(ctx, "Document1.pdf"); //Save the page as a PNG image with transparency, at a 1x zoom level (1pt = 1px). doc1.SaveImage(0, 1, PixelFormats.RGBA, "Raster1.png", RasterOutputFileTypes.PNG); //Open an Open XPS document using MuPDFDocument doc2 = new MuPDFDocument(ctx, "Document2.oxps"); //Save only part of the page as a PNG image with transparency, at a 2x zoom level (1pt = 2px). doc2.SaveImage(0, new Rectangle(87, 360, 517, 790), 2, PixelFormats.RGBA, "Raster2.png", RasterOutputFileTypes.PNG); //Merge the two documents into a single document. MuPDFDocument.CreateDocument(ctx, "Merged.pdf", DocumentOutputFileTypes.PDF, true, //We take the full page from the first document (doc1.Pages[0], doc1.Pages[0].Bounds, 1), //We only take a region of the page from the second document (doc2.Pages[0], new Rectangle(87, 360, 517, 790), 1) ); }
/// <summary> /// Creates a new <see cref="RasterImage"/> from the specified stream. /// </summary> /// <param name="imageStream">The stream containing the image data.</param> /// <param name="fileType">The type of the image contained in the stream.</param> /// <param name="pageNumber">The number of the page in the file from which the image should be created, starting at 0. Only useful for multi-page formats, such as PDF.</param> /// <param name="scale">The scale factor at which to render the image.</param> /// <param name="alpha">A boolean value indicating whether transparency (alpha) data from the image should be preserved or not.</param> /// <param name="interpolate">A boolean value indicating whether the image should be interpolated when it is resized or not.</param> public RasterImageStream(Stream imageStream, InputFileTypes fileType, int pageNumber = 0, double scale = 1, bool alpha = true, bool interpolate = true) { using (MuPDFContext context = new MuPDFContext()) { IntPtr originalImageAddress; long originalImageLength; IDisposable toBeDisposed = null; GCHandle handleToFree; if (imageStream is MemoryStream ms) { int origin = (int)ms.Seek(0, SeekOrigin.Begin); originalImageLength = ms.Length; handleToFree = GCHandle.Alloc(ms.GetBuffer(), GCHandleType.Pinned); originalImageAddress = handleToFree.AddrOfPinnedObject(); } else { MemoryStream mem = new MemoryStream((int)imageStream.Length); imageStream.CopyTo(mem); toBeDisposed = mem; int origin = (int)mem.Seek(0, SeekOrigin.Begin); originalImageLength = mem.Length; handleToFree = GCHandle.Alloc(mem.GetBuffer(), GCHandleType.Pinned); originalImageAddress = handleToFree.AddrOfPinnedObject(); } using (MuPDFDocument document = new MuPDFDocument(context, originalImageAddress, originalImageLength, fileType)) { RoundedRectangle roundedBounds = document.Pages[pageNumber].Bounds.Round(scale); this.Width = roundedBounds.Width; this.Height = roundedBounds.Height; this.HasAlpha = alpha; this.Interpolate = interpolate; this.Id = Guid.NewGuid().ToString(); int imageSize = document.GetRenderedSize(pageNumber, scale, alpha ? MuPDFCore.PixelFormats.RGBA : MuPDFCore.PixelFormats.RGB); this.ImageDataAddress = Marshal.AllocHGlobal(imageSize); this.DataHolder = new DisposableIntPtr(this.ImageDataAddress); GC.AddMemoryPressure(imageSize); document.Render(pageNumber, scale, alpha ? MuPDFCore.PixelFormats.RGBA : MuPDFCore.PixelFormats.RGB, this.ImageDataAddress); } handleToFree.Free(); toBeDisposed?.Dispose(); } }
/// <summary> /// Invoked when the window is opened. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void WindowOpened(object sender, EventArgs e) { //Render the initial PDF and initialise the PDFRenderer with it. MemoryStream ms = RenderInitialPDF(); Context = new MuPDFContext(); Document = new MuPDFDocument(Context, ref ms, InputFileTypes.PDF); MaxPageNumber = 1; this.FindControl <PDFRenderer>("MuPDFRenderer").Initialize(Document, ocrLanguage: GetCurrentLanguage(this.FindControl <ComboBox>("OCRLanguageBox").SelectedIndex)); this.FindControl <Image>("PageAreaImage").Source = GenerateThumbnail(); //Start the UI updater thread. UIUpdater(); }
/// <summary> /// Render the page to a PNG stream. /// </summary> /// <param name="page">The <see cref="Page"/> to render.</param> /// <param name="stream">The stream to which the PNG data will be written.</param> /// <param name="scale">The scale to be used when rasterising the page. This will determine the width and height of the image file.</param> public static void SaveAsPNG(this Page page, Stream stream, double scale = 1) { Document doc = new Document(); doc.Pages.Add(page); MemoryStream ms = new MemoryStream(); doc.SaveAsPDF(ms); using (MuPDFContext context = new MuPDFContext()) { using (MuPDFDocument muDoc = new MuPDFDocument(context, ref ms, InputFileTypes.PDF)) { muDoc.WriteImage(0, scale, MuPDFCore.PixelFormats.RGBA, stream, RasterOutputFileTypes.PNG); } } }
static void Main() { //Initialise the MuPDF context. This is needed to open or create documents. using MuPDFContext ctx = new MuPDFContext(); //Open a PDF document using MuPDFDocument doc1 = new MuPDFDocument(ctx, "Document1.pdf"); //Save the page as a PNG image with transparency, at a 1x zoom level (1pt = 1px). doc1.SaveImage(0, 1, PixelFormats.RGBA, "Raster1.png", RasterOutputFileTypes.PNG); //Open an Open XPS document using MuPDFDocument doc2 = new MuPDFDocument(ctx, "Document2.oxps"); //Save only part of the page as a PNG image with transparency, at a 2x zoom level (1pt = 2px). doc2.SaveImage(0, new Rectangle(87, 360, 517, 790), 2, PixelFormats.RGBA, "Raster2.png", RasterOutputFileTypes.PNG); //Merge the two documents into a single document. MuPDFDocument.CreateDocument(ctx, "Merged.pdf", DocumentOutputFileTypes.PDF, true, //We take the full page from the first document (doc1.Pages[0], doc1.Pages[0].Bounds, 1), //We only take a region of the page from the second document (doc2.Pages[0], new Rectangle(87, 360, 517, 790), 1) ); //Open the rasterised page so that we can try using the OCR. using MuPDFDocument doc3 = new MuPDFDocument(ctx, "Raster1.png"); //Get a structured text representation of the page using OCR. MuPDFStructuredTextPage page = doc3.GetStructuredTextPage(0, new TesseractLanguage(TesseractLanguage.Fast.Eng)); //Print all the text lines. foreach (MuPDFStructuredTextBlock blk in page) { foreach (MuPDFStructuredTextLine line in blk) { System.Console.WriteLine(line.Text); } } }
/// <summary> /// Parses an image URI into a page. This is intended to replace the default image URI interpreter in <c>VectSharp.SVG.Parser.ParseImageURI</c>. To do this, use something like: /// <code>VectSharp.SVG.Parser.ParseImageURI = VectSharp.MuPDFUtils.ImageURIParser.Parser(VectSharp.SVG.Parser.ParseSVGURI);</code> /// </summary> /// <param name="parseSVG">A function to parse an SVG image uri into a page. You should pass <c>VectSharp.SVG.Parser.ParseSVGURI</c> as this argument.</param> /// <returns>A function to parse an image URI into a page.</returns> public static Func <string, bool, Page> Parser(Func <string, bool, Page> parseSVG) { return((string uri, bool interpolate) => { if (uri.StartsWith("data:")) { string mimeType = uri.Substring(uri.IndexOf(":") + 1, uri.IndexOf(";") - uri.IndexOf(":") - 1); string type = uri.Substring(uri.IndexOf(";") + 1, uri.IndexOf(",") - uri.IndexOf(";") - 1); if (mimeType != "image/svg+xml") { int offset = uri.IndexOf(",") + 1; byte[] parsed; bool isVector = false; InputFileTypes fileType; switch (mimeType) { case "image/png": fileType = InputFileTypes.PNG; break; case "image/jpeg": case "image/jpg": fileType = InputFileTypes.JPEG; break; case "image/gif": fileType = InputFileTypes.GIF; break; case "image/bmp": fileType = InputFileTypes.BMP; break; case "image/tiff": case "image/tif": fileType = InputFileTypes.TIFF; break; case "application/oxps": case "application/vnd.ms-xpsdocument": fileType = InputFileTypes.XPS; isVector = true; break; case "application/x-cbz": fileType = InputFileTypes.CBZ; break; case "application/epub+zip": fileType = InputFileTypes.EPUB; isVector = true; break; case "text/fb2+xml": fileType = InputFileTypes.FB2; break; case "image/x-portable-anymap": fileType = InputFileTypes.PNM; break; case "image/x-portable-arbitrarymap": fileType = InputFileTypes.PAM; break; case "application/pdf": fileType = InputFileTypes.PDF; isVector = true; break; default: fileType = InputFileTypes.PDF; break; } string substring = uri.Substring(offset); switch (type) { case "base64": parsed = Convert.FromBase64String(uri.Substring(offset)); break; case "": parsed = (from el in System.Web.HttpUtility.UrlDecode(uri.Substring(offset)) select(byte) el).ToArray(); break; default: throw new InvalidDataException("Unknown data stream type!"); } if (!isVector) { GCHandle handle = GCHandle.Alloc(parsed, GCHandleType.Pinned); RasterImageStream img = new RasterImageStream(handle.AddrOfPinnedObject(), parsed.Length, fileType, interpolate: interpolate); handle.Free(); Page pag = new Page(img.Width, img.Height); pag.Graphics.DrawRasterImage(0, 0, img); return pag; } else { string tempFile = Path.GetTempFileName(); using (MuPDFContext context = new MuPDFContext()) { using (MuPDFDocument document = new MuPDFDocument(context, parsed, fileType)) { MuPDFDocument.CreateDocument(context, tempFile, DocumentOutputFileTypes.SVG, true, document.Pages[0]); } } string tbr = "data:image/svg+xml;," + System.Web.HttpUtility.UrlEncode(File.ReadAllText(tempFile)); File.Delete(tempFile); return parseSVG(tbr, interpolate); } } else { return parseSVG(uri, interpolate); } } return null; }); }