Saturday, May 25, 2013

How to fix PDFs that appear with colors too dark or too bright when viewed on iPad or iPhone.

In some of my iOS projects I had to display PDFs of documents originally intended for print format. Some of those PDFs would appear horribly on iOS devices, with colors messed up. It was a pretty surprising behaviour, which I initially attributed to bugs in Apple's PDF rendering code.

My first approach to getting around such problems was to use a server-side component powered by Ghostscript to convert each PDF page into an image, that would show up in the right colors, and display that. The advantage of this approach is that it can be fully automated. The disadvantage is that images may show up poorly (pixelated) when zoomed in, depending on their pixel density.

Upon investigating this problem further I discovered a way to fix this problem at its root, that is the source PDF document. Unfortunately it can't be automated easily because it involves running Adobe's Acrobat tool. In the absence of a public API to run that conversion programatically one has the option of using workflow-recording tools like Apple's Automator to drive the Acrobat automatically. While that approach may work, it would be hard to scale in a cost-effective manner.

Another option to handle this may be to use iText to automatically convert CYMK profiles to RGB, or if that's not possible, to at least detect the presence of CYMK profiles and alert the user about the need to convert the PDF manually using Acrobat.

Tuesday, May 14, 2013

So we had the www for a while. What's next ?

The dawn of the web introduced us to URLs starting with "http://www". For those old enough to remember those days of Lynx, Mosaic, and Netscape, "www" was true to its meaning of "world-wide web". Suddenly anyone connected to the Internet was able to reach out to any remote place in the world, also connected to the net, and browse the information published there. Powerful.

Since then a lot has changed. The devices we use to access the net had moved from our desks to our palms, and soon to our glasses, and with the mobility they afford, the Internet access got a new dimension - that of context, or location. So in addition to what's out there (www) now what's over here becomes an interesting question. Perhaps some new URLs, like "http://here" and "http://now", start to make sense. Seems that I'm not the only one thinking so. Nokia appears to be doing something like that with http://here.com. If face recognition becomes a feature of Google Glass, then a "http://you" makes sense too. I'm probably stating the obvious here, but what I'd like to see is more of these 2 things:

1. The ability of users to freely add and annotate the content presented. Think of "Augmented Reality Wikipedia". Like "digital graffiti" curated through a vote-based meritocracy, or by applying a filtering based on what your contacts on social networks think of that content.

2. More mash-ups. With the growing number of web services (over 9000 APIs as of now), and the continued move toward a more semantic web, the ability to mash things up should continue to grow.

It'd be interesting to see how all this will unfold, and maybe even contribute to this vision. Such projects, once they pass a critical mass of adoption, they tend to snowball fast.

Friday, May 10, 2013

Rendering office documents in HTML - an idea whose time has come

A while ago I was working on a project that needed rendering PDFs on iOS. There are several ways to do that. On iOS, that is. My client wanted a solution for Android too, and was complaining about the lack of similar capabilities there. Since Android wasn't one of my areas of competence at the time I wasn't involved with that effort directly. However I kept hearing about the need to use some 3rd party, rather expensive, libraries.

So naturally it dawned on me this idea: why don't the "owners" of the PDF format, Adobe, provide a cross-platform viewer. The natural solution would be an HTML based approach, since virtually all popular platforms provide a way to display HTML. At the time I was thinking that the capabilities provided by HTML 5 and CSS 3 should be enough to accomplish the "print-quality" level of rendering offered by Adobe's Acrobat Reader or Apple's Preview. Since Adobe wasn't doing much about it, it seemed a pretty good opportunity. Turns out that wasn't such a bad idea. In fact folks at Crocodoc were banging at it since 2006. Today was the payback. Good for them.

I only heard about them today. A brief glance at their API shows that right now it fetches the documents from some servers, where they're processed and converted from PDF to HTML. With this dependency on a server-side component it doesn't seem to have support for offline viewing. I guess one could hack around and save the generated HTML and all the referenced components (images, CSS, and what not), but that may be a brittle solution. With their new owner I'm sure they'll keep improving their technology and this may well become a compelling cross-platform document rendering solution.

Saturday, May 04, 2013

Caveats of using MPMoviePlayerController

For a recent iOS project I had to play some videos, embedded in a subview of a larger view. One way to achieve that is to employ the MPMoviePlayerController. At first glance that component seems easy enough to use. Folks at Apple are trying to help by providing the following code snippet, right there in the official docs:

MPMoviePlayerController *player =
        [[MPMoviePlayerController alloc] initWithContentURL: myURL];

[player prepareToPlay];

[player.view setFrame: myView.bounds];  // player's frame must match parent's

[myView addSubview: player.view];

// ...

[player play];

Right on. I'm adding this stuff to my app, and ... nothing happens. Nothing plays, just a black rectangle where the video player was supposed to show up. My first reaction was to look if they have a complete sample project that I could play with, and learn how to use the API. They do. I open it and it's using manual memory management (pre-ARC). Yuck ! Still I look there and see that they're using notifications to observe the state of the player. That sounds like a good way to debug what's going on. I do the same in my code. None of the notifications get called. What the ... ?

On a 2nd look at the code above, it becomes clear that in an ARC project, like mine was, the player local variable will be gone at the end of its enclosing scope. No wonder that nothing happens. The player must be kept alive through a strong ivar, or property. Doing that fixed my problem. So Apple's code snippet is pretty bad. It would have worked in the pre-ARC projects, albeit by leaking memory, but obviously this stuff was never updated for ARC.

Luckily I have plenty of experience doing manual memory management, and I can handle old code bases, like so many of Apple's code samples are. For now I'll inform their docs team of the problem.