tap tap tap

tasty bits for your iPhone

Our blog blog blog

Looking for more recent articles? We post new articles exclusively on our new blog…
snap snap snap.

Creating a Camera+ effect

by Lisa Bettany
February 16, 201123 comments
rollover to see unedited photo

In version 2.0 of Camera+, we added a whole new FX pack, I ♥ Analog, with 9 fabulous filmic FXs to give your photos a retro flavour. From start to finish, each FX takes several days to create, test and implement. In this video I’m going to share the process on how we created one of our most complicated FXs, Nostalgia from our new I ♥ Analog Pack.

Step 1: Concept

The concept for the analog pack was a throw back to retro film styles gaining huge popularity in the iPhone app world. The challenge with creating new FXs for the I ♥ Analog pack was that I had already created 27 FXs for the app, 9 of them “vintage” in the Retro pane in the app, and these had to be completely different.

My original idea for Nostalgia was actually based on an old photograph of my mum taken in the early 70s. I loved the slight cross-processed look and the slightly yellowy aged look. I also searched Flickr for images taken in the same time period and started to form a colour palette for the FX.

Step 2: First draft of the formula

After I collect some good example photos, I fire up Photoshop and try to replicate the color, tone & contrast with an iPhone photo. One concern I always have is keeping the amount of layers and processes to a minimum. We try to keep our FXs as speedy as possible and more layers = more code & longer processing times. For this initial draft of the Nostalgia FX, I had 5 layers.

rollover to see unedited photo

Step 3: Testing

Once I feel like I have a good “formula” for the FX, I start testing it on hundreds of iPhone photos. Some look great, some look horrible. This is when I often have to go back and change, if not completely revise the formula and start from scratch. This one was working quite well so after making some tweaks, I pass on the first formula to Karl von Randow, our coding wizard.

Step 4: In-app testing

Karl tries to get the code in the app to match my Photoshop file as closely as possible, but it’s not a perfect match, so he rolls out an initial draft FX for the rest of the team to test with as many iPhone photos as possible. At this point, we felt like the FX was too similar to other Retro FXs we had, so it was back to the drawing board for me.

Step 5: Wolfgang creates textures

During the testing phase, we decided that adding some textures to the FX would make it more unique and stand out from other 35 FXs I’d previously created. I did a quick Google image search for textures and started experimenting with them. Once I’d found something that was working, I passed them on to our design wizard Wolfgang Bartleme to create original textures for Nostalgia.

In this video Wolfgang creates the Stone texture we use in the FX.

Step 6: Finalizing the FX formula in Photoshop

Once I have Wolfgang’s textures, I finalize the new FX formula in Photoshop. This video breaks down the various layers and processes used to make Nostalgia.

Step 7: Karl codes magic

Taking the final FX formula to working code is an intense process that Karl breaks down in this video:

Here’s the relevant part of the code from the video:

  1. /* Clone the current image, blur it and then composite it back ontop of the original image with 33% soft light blend mode. */
  2. blurContext = BitmapContextCreateClone(bitmapContext);
  3. BitmapContextBlur(blurContext, 40);
  4. BitmapContextComposite(bitmapContext, blurContext, 0.33, kCGBlendModeSoftLight);
  5. BitmapContextRelease(blurContext);
  7. /* Draw a film grain tiling image over the image with 40% overlay blend mode.
  8.  * Choose a smaller tile if the target image is a thumbnail, to improve performance.
  9.  */
  10. BitmapContextCompositeTiledImageNamed(bitmapContext,
  11.         CGBitmapContextGetWidth(bitmapContext) <= 200 &&
  12.         CGBitmapContextGetHeight(bitmapContext) <= 200 ?
  13.         @"fx-film-filmgrain-thumb.jpg" : @"fx-film-filmgrain.jpg",
  14.         0.4, kCGBlendModeOverlay);
  16. /* Draw a stone texture over the image, but masked so that it draws around the edges of the image.
  17.  * Create an overlay image the same size as the original and draw the tiled image in it.
  18.  */
  19. CGContextRef overlayContext = BitmapContextCreateWithTemplate(bitmapContext);
  20. BitmapContextCompositeTiledImageNamed(overlayContext, @"fx-film-nostalgia-stone.jpg", 1.0, kCGBlendModeNormal);
  21. /* Create the mask image, the same size as the original, draw the masking image into it. */
  22. CGContextRef maskContext = BitmapContextCreateWithTemplate(bitmapContext);
  23. BitmapContextCompositeImageNamed(maskContext, @"fx-film-mask.jpg", 1.0, kCGBlendModeNormal);
  24. /* Apply the mask to the overlay image and then composite the overlay with the original image using 45% overlay blend mode.
  25.  * This composite respects the alpha channel, whereas other compositing ignores it for performance.
  26.  */
  27. BitmapContextApplyMask(overlayContext, maskContext);
  28. BitmapContextAlphaComposite(bitmapContext, overlayContext, YES, 0.45, kCGBlendModeOverlay);
  30. /* Replace the previous overlay with the special-sauce nostalgia brown tiled image, then repeat the masking
  31.  * and compositing process above.
  32.  */
  33. BitmapContextCompositeTiledImageNamed(overlayContext, @"fx-film-nostalgia-brown.jpg", 1.0, kCGBlendModeNormal);
  34. BitmapContextApplyMask(overlayContext, maskContext);
  35. BitmapContextAlphaComposite(bitmapContext, overlayContext, YES, 1.0, kCGBlendModeSoftLight);
  36. BitmapContextRelease(overlayContext);
  37. BitmapContextRelease(maskContext);
  39. /* Draw a white vignette "centre spotlight" using 50% overlay blend mode */
  40. BitmapContextVignetteRGBBlend(bitmapContext, 0xffffff, 1.05, 0.5, kCGBlendModeOverlay);
  42. /* Draw a black vignette using 50% overlay blend mode */
  43. BitmapContextVignetteRGBBlend(bitmapContext, 0x000000, 1.5, 0.5, kCGBlendModeOverlay);
  45. /* Increase the saturation 30%, applied with 50% normal blend mode */
  46. BitmapContextSaturateBlend(bitmapContext, 1.3, 0.5, kCGBlendModeNormal);
  48. /* Curves for red, green and blue.
  49.  * R: 52, 84 / 192, 177 / 255, 222
  50.  * G: 60, 66 / 207, 180
  51.  * B: 27, 0 / 225, 255
  52.  */
  53. const double curveR[] = { -4.844560000, 7.485810000, -2.417520000, 0.776277000, -0.000000000 };
  54. const double curveG[] = { -1.415160000, 1.904100000, 0.511063000, -0.000000000 };
  55. const double curveB[] = { 0.776471000, 0.105882000 };
  56. BitmapContextPolynomialFunctionChannels(bitmapContext, 5, curveR, 4, curveG, 2, curveB);
  58. /* Fill with #f21bef using a 10% colour blend mode */
  59. BitmapContextColorComposite(bitmapContext, 0xf21bef, 0.10, kCGBlendModeColor);
  61. /* Levels for red, green and blue, using a 30% normal blend mode */
  62. BitmapContextLevelsChannelsBlend(bitmapContext, 0, 1.0, 255, 0, 255,
  63.                                                 0, 1.0, 235, 0, 255,
  64.                                                 0, 1.0, 242, 0, 255,
  65.                                                 0, 1.0, 253, 0, 200,
  66.                                                 0.3, kCGBlendModeNormal);

Step 8: Karl optimization

With a lot of the I ♥ Analog FXs , we were seeing a huge lag in processing times up to 30 seconds for an iPhone 4 photo. This is one of the huge challenges with creating FXs for iPhone apps. Complex processes like Gaussian blurs can add 10 seconds of processing time on FXs, so we rely heavily on Karl to make these FXs as speedy as possible.

Step 9: Ship it!

Once we’ve got the FX looking constant and the team is happy with the results, we are ready to ship the FX. Start to finish, each FX takes a lot of time and effort to take from concept to working code inside Camera+. The I ♥ Analog pack was the most ambitious group of FXs I’ve undertaken, and I truly hope you enjoy using them to make your iPhone photos more retro fabulous.

We’re providing you with this handy pack of the Photoshop files, textures, and code so that you can play around with all of this yourself:

If you’re interested in finding out more about Camera+ and the I ♥ Analog FX Pack, visit the Camera+ website at

tap tap tap is a leading iPhone and iPad app developer and publisher.

We’ve been creating top-notch apps since the App Store first opened. Our apps are used by literally tens of millions of people in all corners of the world. A few of our favorite and most popular apps we’ve created are:

Who linked to this


  1. kc!
    2:46pm, February 16, 2011

    Love the detailed run-through! And absolutely LOVE Camera+ — the first app to replace the official camera app in my dock (and I have tried quite a few in my time with the iPhone!), and one which I consistently love filtering images through!

    Looking forward to future filters and all the wonderful goodies you guys are so good at making!!

  2. Robert-Paul Jansen
    3:01pm, February 16, 2011

    Camera+ has replaced the Apple camera here too, and I have tried lots and lots as well! It’s fast and has just the right options when shooting.

    I love the filters, especially the Analog filters, though I would like to see more basic 70s filters withouth the textures. Love that 70s and 80s look.

    Thanks for this insight, know not many devs who show us their kitchen like you do.

    Cheers, RP

  3. Ryan Ray
    3:08pm, February 16, 2011

    Hard work well worth it guys, the pack is great. I hope you are working on more, I have $0.99 ready for another great pack of FX.

    I’m ready for a cool summer/spring FX pack :)

  4. Pedro
    3:11pm, February 16, 2011

    Wow! An awesome post guys.
    Please do this more often.

  5. Jacob
    3:12pm, February 16, 2011

    Wow, thanks for sharing, great insight into these filter creation.

    Love the app as well.

  6. Joshua
    3:50pm, February 16, 2011

    Thanks for the details and the great post. Watching the videos.

  7. Nils
    5:20pm, February 16, 2011

    Hi Karl !
    Great post, very interesting.

    I wanted to know if all the BitmapContext* functions are functions that taptaptap created or if they are part of a library/framework…

    Thanks !

  8. Paurian
    5:58pm, February 16, 2011

    Thanks for sharing the insight, the code, and the zip download!

  9. Mae
    11:06pm, February 16, 2011

    Love it! For those of us who use Aperture, would you guys ever consider releasing a Cam+ plugin pack? I’d definitely buy it, and would lovelovelove to have metadata from the app available in Aperture. Someday. Thanks!

  10. Jay
    12:46am, February 17, 2011

    Seconding Mae on some Aperture presets, but I’ll expand it to Lightroom, ACR and Photoshop actions. I’ve started doing it on my own in Lightroom. I’d certainly go for some official presets!

  11. naomi yamada
    12:30pm, February 17, 2011

    Thanks for sharing the behind the scenes process. Makes me love it more, can’t wait to get it…

  12. Cory
    2:46pm, February 18, 2011

    It would be killer if you guys released all these BitmapContext in a framework - be it open source or a closed framework so you can hide your mojo. Would be awesome for us devs who have great ideas, but aren’t as talented in image manipulation…

  13. Sinesio (KinoDF)
    7:39am, February 21, 2011

    I love yours absolute sense of honesty and high quality of yours product! No mystery in expose the code of yours heavy/hard work!
    Thank you very much!

  14. moosc
    12:24pm, March 1, 2011

    Thanks thanks !!
    Very useful.

    “It would be killer if you guys released all these BitmapContext in a framework – be it open source or a closed framework so you can hide your mojo.”


  15. Ariok
    12:32pm, March 14, 2011

    Useful post!
    I’m so curious, do you choose to use some sort of compiled Library for image manipulation (like imageMagick or similar) or in BitmapContext you utilize “only” Core Graphics !?!?!?
    Thank you for your answer :D and for this cool post!

  16. krishnabhadra
    11:15pm, April 4, 2011

    Super design of your blog, and an unbelievable post..Loved it..

  17. Wilfred
    1:13pm, September 3, 2011

    Thanks for this post! Karl could you please show the body of “BitmapContextPolynomialFunctionChannels” function or share more detailed source if it’s possible. Thank you.

  18. Ricardo
    4:23am, October 26, 2011

    WOW! Thanks for share!

  19. Joeri
    1:43pm, October 30, 2011

    I wish there was a tutorial for all these effects! I love Camera+, but would like to start doing these things myself, just so I know how they work.

  20. Howard Scroggins
    8:46am, October 31, 2011

    I am writing to ask where you go in order to purchase the Analog FX Pack.

  21. Kumaresh
    5:13am, December 19, 2011

    Can i get the Nostalgia.h file? .plz.thanks in advance

  22. Muzammil
    2:44am, May 21, 2012

    Can you please little bit of BitmapContextLevelsChannelsBlend or any bitmap context.

    Thanks, Muzammil

  23. Andrea
    1:53pm, November 25, 2012

    Usually I don’t buy through in-app purchase especially if the application it’s not free. However, after reading this post, and after loving camera+, I definitely decided to buy it. I really appreciate your deep description of the process of designing new effects.

    Thanks a lot!

the comments are now closed