DEV Community

Jethro Daniel
Jethro Daniel

Posted on

2 2

Hacking Together A PDF To Image Export Library

So, the other day at work, i got a ticket to build a feature to export pdf documents as images. It looked like a straight forward task, but quickly turned out to be a nightmare.

The Problem

Many of the PDF spec implementations in circulation today are always almost natively written (C/C++), and many languages all have a wrapper around them, because why re-invent the wheel when there is already a battle tested library right ?

Well, in my case this wasn't helpful, due to some dependency management/server constraints, i was unable to work with these types of implementations.

Solution 1: Get A Library

Since the native way wasnt feasible, i began heavy googling and research, trying to find 100% managed Go libraries, and yea, i found alot of libraries 100% go, but all of them didnt have the feature i really needed, which was exporting the pdf to image, at this point my brain was already experiencing a stackoverflow 🤯

Solution 2: Find A Managed Library In Another Language

Simply write that part of our system in another language, that had managed libraries to work with, surely enough i got many libraries like that are in C#/Java etc to work with, which is good since i have significant experience in C#. But at this point my paranoia was off the charts, simply accepting a solution like this was not satisfactory to me.

Solution 3: Building My Own Library In A Managed Language

So how hard would it be implementing a pdf to image library in a managed language ? 😏

Well, turns out that it is not so difficult. I started of my journey by understanding what exactly is truly involved, went to github, to look for some ideas, i saw a project with a proof of concept, and basically all they did was to take the PDF document, parse it and extract the pdf objects (images/text) and draw them onto a canvas and save the canvas as an image.

This should be fun i thought, i started writing my own implementation, and in under a day working with C#/.Net Core and its beautiful low level APIs, and this beautiful library ImageSharp i was able to hack something together.

Soon enough all the pdf hidden Spec features began to hunt me, Pdfs with images that had opacity were a nightmare, pdfs with custom fonts also came along and on and on, any new pdf i tried, came with its own twist.

Final Solution

I soon realised that this is another whole project on its own, and since time was running out i decided to fallback to Solution 2 and quickly close the ticket.

Then another roadblock, the perfect library i found in Solution 2 was exporting the image in ARGB32 pixel format, essentially when i try to parse the image i get images in this all blue format, like a snapchat filter.

Thanks to the knowledge learnt in Solution 3, i was able to manipulate the raw bytes of the image and fix the exported image by manipulating the individual pixel. Rearranging them back to RGBA32 pixel format.

Span<byte> imgBytes = reader.GetImage(new NaiveTransparencyRemover(255, 255, 255));

var width = reader.GetPageWidth();
var height = reader.GetPageHeight();

var newImage = new Image<Rgba32>(width,height);
var rowBytes = width * 4;
for (int i = 0; i < imgBytes.Length; i+=rowBytes)
{
     var singleRow = imgBytes.Slice(i, rowBytes);
     Span<Rgba32> pixelRowSpan = newImage.GetPixelRowSpan(i == 0?0:i/rowBytes);
     for (int j = 0; j < rowBytes; j+=4)
     {
         var px = singleRow.Slice(j, 4);
          pixelRowSpan[j==0?0:j/4] = new Rgba32(px[2],px[1],px[0],px[3]);
      }
 }


using (var fs = File.Create(Path.Combine(Environment.CurrentDirectory, $"wave-{DateTime.Now.Ticks}.png")))
{
        newImage.SaveAsPng(fs);
}

Enter fullscreen mode Exit fullscreen mode

Summary

This was an interesting ticket to work on, i learnt alot about computer graphics, pixel standards, the PDF specification and all, i hope i can comeback and work on a 100% easy managed solution in Go as a side project.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay