Giter Site home page Giter Site logo

Comments (3)

arklumpus avatar arklumpus commented on June 11, 2024 1

Hi! I'm glad you're finding the library useful!

This sounds like a good idea, I can start working on it when I get back to my computers (likely next week). I will update this issue when it's done.

from mupdfcore.

arklumpus avatar arklumpus commented on June 11, 2024 1

Hi! Version 1.5.0 now has overloads of the render methods (both for the MuPDFDocument and the MuPDFMultiThreadedPageRenderer) that return Spans.

However, you should note that:

  • If you're using ImageSharp, ImageSharp's LoadPixelData method will always create a copy of the pixel data, regardless of how you invoke it (e.g. with a byte[] or with a Span<byte>).

  • In addition to returning a Span<byte>, the new methods also return an IDisposable. This keeps track of the unmanaged memory that is pointed to by the Span. You must ensure that the lifetime of this IDisposable matches the lifetime of the Span, preferably by Disposeing it when you have finished working with the image. If the IDisposable goes out of scope while you still have access to the Span, the GC may collect it and trigger its finaliser at any time - as a result, the memory to which the Span points will be released, while you still hold an apparently valid reference to it.

  • Arrays of Spans are not allowed, therefore the MuPDFMultiThreadedPageRenderer.Render method returns a delegate instead. To get the Span<byte> corresponding to the i-th tile, you need to invoke the delegate, passing i as a parameter:

     MuPDFMultiThreadedPageRenderer renderer = ...
     
     RoundedSize targetSize = ...
     Rectangle region = ...
     PixelFormats pixelFormat = ...
     
     MuPDFMultiThreadedPageRenderer.GetSpanItem tiles = renderer.Render(targetSize, region, out IDisposable[] disposables, pixelFormat);
     
     int tileCount = disposables.Length;
     
     for (int i = 0; i < tileCount; i++)
     {
     	// Get the i-th tile.
     	Span<byte> tilePixels = tiles(i);
     	
     	// Do something with tilePixels.
     	
     	// Release the memory where the i-th tile is stored.
     	disposables[i].Dispose();
     }
  • If you use the overload of the MuPDFDocument.Render method that returns a byte[], the pixel data will NOT be marshalled by MuPDFCore. Thus, there should not be much of a performance penalty if you use this overload instead of one with an IntPtr parameter or one that returns a Span<byte>.

All in all, if you just need to manipulate the image using ImageSharp, it is probably better if you just use the MuPDFCore overload that returns a byte[]; in this way, you don't have to worry about memory management (since this a "normal" byte array that will be collected by the GC as usual), and ImageSharp is going to copy the data to its own memory storage anyways.

The MuPDFMultiThreadedPageRenderer does not have a Render overload working with byte[] arrays, but it's relatively straightforward to get an IntPtr from a byte[] staying in safe mode:

int bufferSize = ...

byte[] buffer = new byte[bufferSize];

GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr bufferPointer = bufferHandle.AddrOfPinnedObject();

// Do stuff with bufferPointer.

bufferHandle.Free();

As long as you don't wait too much before freeing the GCHandle, the side effects on the GC shouldn't be too relevant.

In any case, if you need better performance, you may need to look into some other graphics library that lets you work directly with pixel data stored in unmanaged memory (perhaps something like SkiaSharp?)...

from mupdfcore.

tzographos avatar tzographos commented on June 11, 2024

This is great! Thanks for the detailed explanation. I will give it a spin right away!

from mupdfcore.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.