At ThoughtFaqtory we are continually encouraged to think outside of the box when challenges are presented. A challenge was set recently by a pretty innocuous requirement from one of our clients.
This project required me to implement functionality that would allow the end user to export groups of images to PDF. The PDF needed to be high quality, 300 ppi (pixels per inch). After some searching I came across the AlivePDF website which appeared to be perfect for my requirements. Initially after using AlivePDF to generate a few PDFs, I couldn’t believe how easy it was to use and I thought that I had found Utopia. My joy however was short lived after the following error message was received:
AlivePDF had no alpha channel support for PNGs and the PNG encoder provided by Adobe always returns a PNG with an alpha channel. Even if you turned off the transparency you will get back a 32 bit ARGB PNG.
I continued searching for someone who had a method of successfully removing the alpha channel but my search proved fruitless. Hence I decided to do my own research into PNGs and found the following:
A valid PNG consists of:
PNG signature
IHDR chunk (only one)
IDAT chunk (one or more)
IEND chunk (only one)
The PNG signature:
89 50 4E 47 0D 0A 1A 0A.
The IHDR image header:
| Width: | 4 bytes |
| Height: | 4 bytes |
| Bit depth: | 1 byte |
| Colour type: | 1 byte |
| Compression method: | 1 byte |
| Filter method: | 1 byte |
| Interlace method: | 1 byte |
The IDAT chunks contain the image data.
The IEND chunk marks the end of the PNG.
The colour type under the IHDR chunk needs to be mentioned here as that is where the image type is defined.
| Image type | Colour type |
| Greyscale | 0 |
| True colour | 2 |
| Indexed colour | 3 |
| Grey scale with alpha | 4 |
| True colour with alpha | 6 |
After familiarizing myself with PNGs, I revisited Adobe’s PNGEncoder.as class again and eventually managed to make certain changes that allowed the removal of the alpha channel all together.
After all the research this ended up being a lot easier than I had originally thought, all that I needed to do was change the colour type and extract the RGB values. Adobe’s colour type was 6 (True colour with alpha) I changed it to 2 (True colour only). Next I needed to isolate and extract the RGB values, this was done with a bitwise right shift operation and a bitwise AND operation.
// Build IHDR chunk var IHDR:ByteArray = new ByteArray(); IHDR.writeInt(w); IHDR.writeInt(h); IHDR.writeUnsignedInt(0x08020000); // True colour (no alpha) IHDR.writeByte(0); writeChunk(png, 0x49484452, IHDR); // Isolate RGB values for (var j:int = 0; j < w; j++) { p = img.getPixel(j, i); IDAT.writeByte(p >> 16 & 0xFF); IDAT.writeByte(p >> 8 & 0xFF); IDAT.writeByte(p & 0xFF); }
The changes implemented resulted in the removal of the Alpha channel which allowed me to successfully embedded the encoded PNG image into a PDF with AlivePDF. This was the first of many problems I had working with PDFs, maybe you will get to read about the others in the not too distant future. Attached below is a sample application that will embed a PNG into a PDF.
[kml_flashembed publishmethod="static" fversion="10.0.0" movie="http://thoughtfaqtory.com/blog/wp-content/uploads/2009/10/pngalpha1.swf" width="630" height="400" targetclass="flashmovie" ]
[/kml_flashembed]
[kml_flashembed publishmethod="static" fversion="10.0.0" movie="http://www.thoughtfaqtory.com/blog/wp-content/uploads/2009/09/filterdemo.swf" width="600" height="465" targetclass="flashmovie"]
[/kml_flashembed]
My transformation started with ThoughtFaqtory nearly a year ago and before that I was a new vehicle salesperson with a propensity for pyrotechnics. . . like blowing things up! With a burning desire to be in the IT industry, but without an opportunity to make the move to becoming a software developer, I was up the river without a paddle! A couple of years ago the motor industry experienced a downward trend in sales, realizing that this maybe a blessing in disguise, a Plan B was necessary. While sitting on the sales floor watching tumble weeds roll past, I embarked on teaching myself Java, as I was more than willing to invest that time in my future. By the end of last year I felt confident enough to find myself an employer that would be willing to take me on. ThoughtFaqtory was on my radar, through a newspaper editorial, and contacted Simon and Phil Barber. They offered me this huge opportunity to learn from within their company and then spent the next 6 months on a rigorous training program using Flex.
So the former sales person was morphed into a developer, but I must share a little secret – my father was a programmer for Siemens, so let’s say it’s in the blood. ThoughtFaqtory offered me some time to research a technology of my choice and was given the opportunity to post this blog. Two weeks was invested learning how to use Pixel Bender; there are numerous amounts of resources that you can look at if you want to learn how to use it. Keith Peters had a fantastic chapter on Pixel Bender in his book “Advanced ActionScript Animation” which was a great help and also adapted one of his examples to my needs in this example. Also available was some excellent info from Lee Brimelow and his tutorials on www.gotoandlearn.com. A shout also goes out to Jonathan Hart who had an awesome example of RGB sine distortion on http://synja.com, which was adapted for this presentation.
This article does not cover the actual Pixel Bender code but shows you how to import the filters in Flex and create a small animation using 4 filters that were created in Pixel Bender. I implemented a base class that each of my custom filters could extend. This would give them the ability to dispatch an event when any of the properties on the filter have been updated. My application could listen for this event on each of the filters and reapply them to the image and update the display.
An animation class was created that would control this and allow various properties to be animated. I do realize that Flash actually provides such classes already but wanted to discover this unknown territory for myself and see how well I would do in solving any obstacles that were cast in my path. It was another learning curve and an enjoyable one. The AnimateFilter class takes an array of Properties on the filter that should be animated. Provision was made for reversing the animation, setting a delay to start the animation and also setting a delay to reverse the animation. The AnimateFilter takes a target, which is the filter that contains the properties to be animated. This can be set up in MXML.
The resulting image has the filters applied and you can see the result when you move your mouse over the image. Four filters have been attached to the image and have an animation set up for each of the filters, which plays on the mouseOver event. The combination of all 4 filters gives an unusual effect. . . at least I think so. CHECK OUT MY EXAMPLE ABOVE.
So there you have it. I am very proud of how far I have come from being a salesperson less than a year ago to where I am now. I would never have been able to absorb this amount of information without the help of all the awesome staff at ThoughtFaqtory. There is a realization though that with this kind of opportunity comes the responsibility to apply myself and work hard to achieve my goals. But in the meantime, I’m loving every minute of it and still blowing things up . . . only kidding.