Eating Our Own Dogfood: How we built the Photoshop 20th Anniversary App in Three Days

By Evan Kirchhoff

When Russell Brown of Adobe approached us about doing a Photoshop 20th Anniversary app, we were immediately excited (if you've seen Russell's show, you know that his enthusiasm is what you might call highly infectious). His proposal was to boil the functionality down to the 1990 "Levels" control panel, which he felt was the original soul of Photoshop. The app would load an image from the user's iPhone photo library, allow multiple changes with live previews, and then let them save the modified image back to their library. In short, it would combine the nostalgia of seeing old-school Photoshop UI running on today's iPhone with a genuinely useful photo-manipulating function.

However, we had to ship the Corona 1.1 update in early February, with a lot of high-priority features. This pretty much wiped out everyone, and also left very little time for the Photoshop app. To get it done for the anniversary, we had to rely heavily on existing sample code and techniques. Think of it as a reality check at gunpoint: Corona had to be as "quick and easy" for us as our marketing always claims, or the project would flop.


The goal was to bring back the look of the 1990 Macintosh, but since we don't have one, we needed to find an emulator that would run on current Intel-based Macs. It's relatively easy to emulate System 7 and later; however, the available OS in 1990 was actually System 6, which retained the classic one-bit black and white window chrome even on color Macs. Finally, we discovered the Mini vMac emulator, along with Apple's public archive of legacy system software (if you're curious, this page has usefully compiled boot disk images and other support files that make the emulation easy to run).

We also stumbled onto a working disk image of Photoshop 1.0, which meant that we could capture clean images of the splash screen and other assets, and also solved the problem of creating text in fonts that no longer exist on the Mac: we could generate new text within Photoshop 1.0 itself.


All the buttons were created with our "ui.lua" library (as seen in the "ButtonEvents" sample code), and the sliders and draggable dialog use our "FollowMe" sample code.

Even though the tiny sliders look difficult to use in a touch-based environment, the trick is that there are much larger invisible "hit" areas around all the onscreen controls, using PNG transparency:

How big should touchable areas be? I recall Verizon's mobile style guide (for devices with roughly iPhone screen resolution1) recommending nothing smaller than 44 by 44 pixels; there are native iPhone controls that are smaller, but if you look carefully, you'll see that there's often an invisible "fuzz factor" that makes small elements easier to hit. This app generally uses at least 40 by 50 pixels where possible, and that seems to work fairly well, especially because you can move your finger vertically away during a drag action, and the slider controls will continue to follow your horizontal motions, just like on the desktop OS.

We also stole a bit of extra space in the Levels dialog by removing the original "Preview" button (not required since we're previewing the image changes in real time) -- this allowed us to move the other controls farther apart and make them more touch-friendly.

A more subtle feature -- obtained for free from our "FollowMe" sample code -- is that any dragged item is automatically popped to the top of the display list. This means that even if you drag the sliders very close together, it's impossible to get the current slider "lost" beneath the others, since the last one you touched is always invisibly on top, so its hit area remains fully exposed. I wouldn't have thought of this in advance, but it turns out to be a key feature in making the old-school controls at all useable on iPhone.


The old Macintosh bitmap fonts (Chicago, in this case) obviously aren't available on the iPhone, so the dynamically-changing number fields had to be created from bitmap images: each digit is a series of ten PNG files bundled into a "digit" class, and the raw input value is split into separate digits and displayed using instances of this class. This "digit" code is based on the same techniques that you can see in our "Movieclip" sample code.

This method sounds like it would impose a lot of overhead, but there are two things to remember about Corona: it only loads an image once into memory, even if that image is "loaded" in multiple places within your code, and onscreen elements with isVisible set to "false" have no performance effects at all. (The Corona game Core Damage has roughly 700 sprites onscreen at all times, but most of them aren't visible at any given moment.)


This is probably the coolest part of the app, due to the spookiness of seeing the same output replicated side by side in the modern version of Photoshop:

However, our histogram is nothing more than plain old Corona vector rectangles, created with a width of one pixel and stacked side by side.


Finally, the alterations to the image (gamma, white and black point, red/green/blue channels) are performed using pixel-level bitmap manipulation features that we haven't publicly exposed yet. Our current plan is to unveil these features as part of the upcoming 1.2 release, once we have a finalized API that we're happy with -- and building the Photoshop app has been a helpful exercise in determining what that API should look like.

1 (Clarification added for Slashdot comment)