Thursday, April 30, 2015

How we reduced the size of our iOS app Monster Math from ~108MB to ~39MB - Part 2

This is the second post in the series of posts where, I will explain how we reduced the size of our iOS app Monster Math from around 108MB to 39 MB.

The previous post, I described the steps we took to get the size improvements, in this post I will try explain a few steps in a bit more detail. 

Converting 24bit PNG's to 8bit PNG's

Of course its possible to update each image manually and save it as 8bit PNG using PhotoShop, but let me put it this way, it wont be convenient, doing it this way.  We had like a ton of images to be converted, so best option would have been a command line tool that we could invoke using a shell script.

With that in mind, we used pngquant a command line utility that does lossy compression of PNG files.  It conveniently converts 24bit PNG files into 8bit PNG files with a simple command.  

This simple shell script will find all the PNG files in a given directory and passes them to pngquant and converts them into 8bit PNG images.  

The results are pretty sweet, it save around 70% of the size of the original 24bit PNG image.

Converting 8bit PNG's to WebP

As mentioned in the earlier post, WebP is an image format that provides lossless and lossy compression for images.  Using the lossless compression on an 8bit PNG gives a whooping 26% reduction in image size.

To convert PNG images into WebP download and install the utilities provided by Google from here.  The simple shell script to convert PNG images to WebP looks like this
This script basically finds all the PNG images in the folder and passes it on to the WebP converter and creates new files with .webp extension.

To render webp images using UIImage use the iOS-WebP library or any other similar library.  Our game uses Cocos2d, to add WebP support to Cocos2d just refer this post

These were the two important methods that gave us significant size reductions in the final binary.  In the next post, I will talk about how we reduced the size of music and sound files of our game.

Sunday, March 29, 2015

How we reduced the size of our iOS app Monster Math from ~108MB to ~39MB - Part 1

Somewhere in November we released our iOS app Monster Math.  When we first released the app it was about 108MB large.  With so many high resolution images and sound and music files that it was bound to be a big binary file.

We knew from the very beginning that, having a binary this big is not ideal.  Some of the common problems with having big binaries are:
  • The time taken for end users to download and start using the app, linearly increases with size of binary.
  • People just don't sit around and watch the app being downloaded, they browse/download other apps, do other stuff, if the download takes longer we might end up getting a download but losing a user.
  • Not to mention the space that it takes up on the device.  Might not be such a big problem for the iPads but certainly a concern for iPhones.
  • Time taken to distribute the alpha/beta/prod builds increases with the size of binary.
These are just a few points but the list can go on and on.  After a few releases, we started actively looking for ways to reduce the size of our binary.  We evaluated numerous options and finally managed to reduce the binary size to around 39MB only!

How Do They Do It!

This post is a developer log of all the things we did to actually get us such great savings on the binary size!

NOTE: Detailed examples of how to do each of the following steps will be covered in subsequent posts.

Identify Biggest Assets In The App
  • This one is by far the easiest step of all, we can easily do a file system sort by size descending, on all the files that get shipped into your application.
  • No surprises here, as expected, biggest chunk comes from
    • Image files
    • Music files
    • Sound files

Converting 24bit PNG's to 8bit PNG's
  • All images in our application were in PNG format.  
  • One option was to convert them to JPEG to reduce the size, but I was not too keen on that.
  • Digging a bit deeper we realised that all our images were PNG 24 bit.  
  • We changed all of them to PNG 8 bit
  • We could not see any huge drop in quality - not that we are any experts on the topic - but for a regular user it didn't make much difference.
  • This single step will get you around 70-80% reduction in size of all the image assets in your application.  Awesome isn't it!

Converting 8bit PNG's to WebP
  • We were still not satisfied with our final binary size, so we went hunting for more optimisations.
  • What we stumbled upon was a new image format called WebP from google.
  • Its an awesome format, provides lossless and lossy compression for images.
  • The lossless compression is a whooping 26% smaller than the PNG's.
  • To use WebP in your iOS app you will need to integrate iOS-WebP or a similar SDK.
  • This added awesomeness, did come with some headaches.  
    • The performance of the game took a bit of a hit, because of added overhead of decoding WebP images
    • This was more apparent when bigger images needed to be decoded for e.g. the backgrounds of scene.
    • To get around this problem we eagerly decoded some of the most commonly used WebP images into PNG's on first launch of the game.
    • And from within the game we use these decoded PNG images.  This solved the performance issue to a great extent.
I know you are itching to look at the code of how we did all this, but please bare with me till the subsequent posts to see the details of each step.

Convert All Sounds and Music files from WAV (or any other format to) AAC Format
  • WAV files are huge, don't use them period!
  • Converting them to AAC format gave us big savings around 70-80% on each file.

Reducing bit rate of AAC Voices to 32K
  • We noticed that reducing the bit rate of all voices (yep! we have voice overs in our app) to around 32K didn't impact the quality much (Note that we only reduced the bitrate of Voices not the background music).  
  • They felt the same when they were played back - again no experts on the subject - but for a normal user it didn't seem to make much difference.
  • This give us another 70-80% reduction in size per voice file!
Seem like a lot of work?  But the end result is equally rewarding, we did manage to reduce the size of our binary to be just under 40MB!

We started from ~108MB and came down to ~39MB, its like more than 63% reduction in the final size!

As mentioned early, watch out for the next set of posts where I will explain in detail on how to perform each of the above steps with code examples.  Till then, keep rocking!

Saturday, February 28, 2015

How to automatically set DateTimeKind, while fetching Datetime properties from database

In one of the my projects, we were saving all DateTime properties after converting them into UTC timezone.  However while reading these values (using EntityFramework) the DateTimeKind was reset to DateTimeKind.Unspecified.

Needless to say that, this behavior causes a lot of problems when we want to convert these DateTime properties into different timezone values.  What we wanted was, an automatic way to set the DateTimeKind value of our DateTime properties to UTC.

I found an awesomely clean way to do this, without doing it manually for each and every DateTime property.

How Do They Do It!

To get the desired effect we need to follow these steps.

  • Create an Attribute that will have the responsibility to set the DateTimeKind value of all eligible DateTime properties of an entity (essentially, those DateTime properties that have this Attribute)
  • Apply this attribute on the desired DateTime properties of all entities.
  • Lastly, we need to hook up this attribute to the ObjectMaterialized event.  So that whenever an entity is materialized, the attribute can perform its job.
Three simple steps to get done, lets jump right into the code.

The code for this attribute is pretty self explanatory, basically
  • It just finds all properties of an entity of type DateTime or DateTime?
  • Loops over these properties to find whether they declare the Attribute
  • If yes, then set the value of the property along with the desired DateTimeKind value.
All we are doing here is to apply the attribute to a few properties of our EntityFramework entities.

Hooking up the Attribute with the ObjectMaterialized event of ObjectContext.

As mentioned earlier, its a simple and clean way to getting the DateTimeKind value set for all DateTime properties of EF entities.

That's all folks!

Credits: SO

Saturday, January 31, 2015

How to ignore global Ajax error handler for user aborted requests using jquery

We had this situation in one of my project, where we wanted to bypass the jquery global Ajax error handler if user aborts the Ajax request by navigating away from the page (for example, by clicking a link on the page)

I tried various options but none seem to work. Finally, I came across one solution, that seem to work perfectly well for my situation.

The idea behind this perfect solution is,
  • Bind the "beforeunload" event on the window object.
  • In the event handler, set a global variable to indicate that the page is being unloaded. 
  • In the global Ajax error handler, do not take any action if the above global variable is set.
  • In all other cases, perform the actual Ajax error handling.
Lets quickly look at the JS code as well.

The code is pretty self explanatory and well documented.  That's about all it takes to get the job done! 

Tuesday, December 30, 2014

The Last Alive Architect!

Have you ever met an Software Architect (or even worked with such a person) who thinks, he/she is the last alive Software Architect on the planet?
  • If your answer is Yes, then you will easily relate to this post :)
  • If its No, then I would have to say its definitely worth an experience - After all, life is not only about happiness :P
This rare species is facing extinction, but some of them have managed to survive.  Because they are so rare, finding them is almost like finding a needle in a hay stack!

Since they are so rare, how do you know when you have found one such person?

Here are some of the symptoms that people from this species exhibit:
  • They stopped reading about the latest in software development since 1981
  • They think all open source frameworks are crappy
  • They think the code written by them is the best possible in the world.
    • But in reality their code is a lot crappier than anything that you have seen before.
  • They would build everything from scratch.  Its their habit to reinvent the wheel.
    • For e.g. building a buggy ORM all by themselves (and of course being proud of it :P)
  • They think all code they write is bug free.  Since all their code is bug free, Unit Testing is such a big waste of time.
  • They can "talk static methods, they can walk static methods and the can laugh static methods, because static methods are the way to go!"
    • If you don't know the context around the dialog do see this clip
  • If given an opportunity, they would like to build a new programming language which runs on an Operating System built all by themselves.
As you can see, its definitely worth an experience meeting a person from this species.  My question to my readers is, whether you have ever met someone like this before?  If yes, do share any other symptoms that people of this species exhibit!

As a closing remark, here is an important disclaimer:

Disclaimer: The views expressed in this post are strictly personal and any resemblance to any real person is purely incidental and not intentional.

Sunday, November 30, 2014

How to show realtime translucent background frost/blur effect similar to iOS UIToolbar

In our app "Monster Math - Best Arithmetic Game. Ever" we wanted to show a parental gate screen, when people click on the "Upgrade" or "Restore" button.  The parental gate screen should have a realtime translucent background frosted glass/blur effect, similar to how its shown in the UIToolbar.

So essentially what I wanted was something like this.

The actual view with a carousel, Upgrade and Restore buttons on it

The parental gate with a translucent background frost effect similar to iOS UIToolbar
I searched around, to see if I can find an inbuilt API in iOS that can help us do this.  But unfortunately there is nothing exposed by Apple that helps us do it.  That said, Apple did show a simple trick that can give us the desired effect very easily.

How do they do it!

This can be done in 3 simple steps
  • Convert the underlying UIView to an UIImage
  • Frost/Blur the UIImage
  • Set this new frosted/blurred UIImage as background of your new view
NOTE: The explanation of how to do these steps can be found in this SO Answer.

Convert the underlining UIView to an UIImage

This can be done by creating a new category of UIView and adding the following method to that category

Frost/Blur the UIImage

To frost/blur the UIImage that we created in the previous step we can use the Apples Image Effect category.  The code for ImageEffects category looks as follows

Using this ImageEffects category we can frost/blur any UIImage as follows

Set this new frosted/blurred UIImage as background of your new view

This is by far the simplest step of all.  All that needs to be done here is to set the newly created UIImage as the background of your new view.  Our game is developed with Cocos2d and we could do this using the following lines of code

The end result is very satisfying.  It looks great on the devices as well!

Thats all folks! I hope you like this realtime frosted glass/blurred effect as much as I do.

Friday, October 31, 2014

How to get Apple Cover Flow effect in an iOS app

Recently, for our flagship app Monster Math, I was on a hunt to find a control that gives me the Apple Cover Flow like effect.  After evaluating a few options I ended up using the awesome iCarousel control.

Its extremely customisable, lightweight, has numerous hooks and many many predefined effects, its simply awesome!  In this post, we will see how easy it is to get the iCarousel integrated into our app.

How Do They Do It!

To get this control up and running follow these simple steps


The installation is stock standard, you can install it via Cocoapods.  Use the following line in your pod file

and then run

  • There are two protocols that need to be implemented for the iCarousel to work correctly.  iCarouselDataSource and iCarouselDelegate
  • The iCarouselDataSource protocol has two mandatory methods to be implemented 
    • (NSInteger)numberOfItemsInCarousel: This method returns the number of items in the carousel 
    • (UIView *)carousel:viewForItemAtIndex:reusingView: This method returns the view that needs to be shown in the carousel.
  • The iCarouselDelegate protocol has no mandatory methods but its good to implement the following method
    • (CGFloat)carousel:valueForOption:withDefault: This method can return values for different options which alter the display and behaviour of the carousel.
Thats about all the methods we will need to implement to get the cool Apple Cover Flow effect.  Lets jump into the code to see the details of implementation

In this snippet we are just initialising the iCarousel and setting the type of carousel to iCarouselTypeCoverFlow2, this type's behaviour closely mimics the App Cover Flow effect.

Next up are the protocol methods that we described earlier.

This snippet implements the two mandatory methods of iCarouselDataSource protocol.  For the view we are showing a simple image from our assets.  And we have total 4 items in our carousel.

The last and final method just customises two options of the iCarousel.  It basically wraps the view so that we get an infinite view sort of a feeling and adjusts the spacing between the views a bit.

With all the pieces in place lets fire it off and see how it looks!

An Infinite Cover Flow Effect

An Infinite Cover Flow Effect

Pretty impressive for such little code, won't you agree?  

That's all folks, until we meet again, Guten Tag!
Have some Fun!