Code evolution: Considering pictures, big and small, and matrix transformations

Code evolution: Considering pictures, big and small, and matrix transformations

When evaluating a customer issue, it’s often useful to run their files through our sample apps to establish if we are seeing the same thing. Occasionally, the output is somewhat unexpected.

That happened to me recently with our C# DrawSeparations sample app. So, I thought it might useful to walk through the steps of addressing the unexpected output, and going a bit beyond to handle other possible cases.

Now, the original code in DrawSeparations looks like this:

There is nothing wrong with this code when handling a fairly common case. But, it has some hidden assumptions built into it that didn’t hold up with the file I was using as input.

The images that were coming out were shifted from where I was expecting them to be, looking at the input file. So, I zeroed in on this code:

Now generally, a PDF Viewer will not show you how exactly the page will look if printed on a page size specified by its MediaBox. Instead, it will show you the page contents that fit within its CropBox; everything outside of that CropBox is assumed to be clipped out and will be white. The CropBox is optional, and if it isn’t specified, then it defaults to the MediaBox. When specified, the CropBox is often smaller than the MediaBox, so you may need to shift the CropBox contents to line things up correctly. Below is my first stab at correcting the problem:

But I wasn’t happy about having the matrix explicitly defined in terms of the CropBox, because this matrix should work for any rectangle really, not just the CropBox. So for the next iteration, I explicitly set the DrawParams.UpdateRect and set the DestRect by transforming the UpdateRect with the DrawParams.Matrix:

With this change, the shifting is now done in terms of the UpdateRect rather than the page’s CropBox. I often explain the relationship between matrix, UpdateRect and DestRect as the Matrix is used to map UpdateRect coordinates to the DestRect area, so explicitly setting the DestRect in terms of a transformation of the UpdateRect makes sense: if the matrix is valid then the DestRect will be valid.

One remaining problem is that the output looks like crap. Because there is a 1:1 correspondence of points to pixels, so the effective resolution of the output is 72DPI, which is about half of the standard resolution of Fax machines. We can do better than that, so:

Now the image will be scaled up to the desired resolution. Have we handled all possible cases? Well, no. What if the page has a rotation specified?

So, to simplify things for this next step, let’s back out scaling up the resolutions, and let’s test with an input file that has rotations and has its CropBox’s bottom left corner at the plane origin (0, 0):

DrawSeparations0-out0 Cyan

And for a final step, let’s tweak the CropBox so we can calculate the translation correctly, so we end up with:

ImageRotatedCropped.PDF

DrawSeparations5-out0 Cyan

So that the final code ends up being:

This iteration of the code is, no doubt, significantly more complicated than the original code we started out with. That may not be what you want for code meant for demonstrating the use of related but separate functionality. But for production code, you might want to think about these different cases and make sure that your output will deliver the results your clients expect. Sample app code is often meant to demonstrate technique stripped down to its essentials rather than be hardened for production use.  Consider the big picture…when looking at little pictures that aren’t quite lining up as they should.

For more information on matrix transformations, leave a comment below or feel free to contact us!

Leave a Reply

Your email address will not be published. Required fields are marked *