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 toSolution 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(newNaiveTransparencyRemover(255,255,255));varwidth=reader.GetPageWidth();varheight=reader.GetPageHeight();varnewImage=newImage<Rgba32>(width,height);varrowBytes=width*4;for(inti=0;i<imgBytes.Length;i+=rowBytes){varsingleRow=imgBytes.Slice(i,rowBytes);Span<Rgba32>pixelRowSpan=newImage.GetPixelRowSpan(i==0?0:i/rowBytes);for(intj=0;j<rowBytes;j+=4){varpx=singleRow.Slice(j,4);pixelRowSpan[j==0?0:j/4]=newRgba32(px[2],px[1],px[0],px[3]);}}using(varfs=File.Create(Path.Combine(Environment.CurrentDirectory,$"wave-{DateTime.Now.Ticks}.png"))){newImage.SaveAsPng(fs);}
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.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse