Wednesday, July 24, 2013

Android Image Cropping Example

When I was creating PsyYourself, I was faced with a challenge on how I can crop out the face with an image that the user provides. One option was to somehow apply Optical Character Recognition (OCR) to detect faces in an image and crop that part out, but at the time OCR was something out of my league to create.

Instead I optioned to have a set of templates that make up
the various shapes of faces and from there, users will be able to orient, either by zooming in or out or moving the image, to fit inside the template. Once that was done, it was up to the device to crop out the image. The problem with this is that there were no available cropping tools/algorithms that I can make use of. I mean, there are existing cropping APIs, but the only problem with that is that they crop out rectangular shaped images, which is something that I did not want. Therefore I am posting this blog to show how I did this. The example project can be found on Github android-cropping-example.

Project Setup

Now, both the image that is going to cropped and the template image has to be overlapped on the screen so that users can easily orient the image to fit into the template. This can be accomplished by using FrameLayout and having two ImageView as its children. As seen below.

The first ImageView with the id cp_img will be the image that user will be orienting. While the second ImageView cp_face_template with scaleType as centerInside because I want to use the exact size of my templates that I have created.

Once the users are done with orienting the image, we then now have to get those images from ImageView the way how it is displayed on the screen. To do this we must first call View.buildDrawingCache() and View.setDrawingCacheEnabled() with the boolean value true as their arguments. Then, to get the bitmap, call View.getDrawingCache(). Lastly, call View.setDrawingCacheEnabled() again and this time with the boolean value false passed in. This process will allow you to retrieve images from ImageView multiple times.

Once, we have retrieved both the template and the oriented image, it's time to put the device to work. As we can see above, I created another thread to handle that work as we don't want the main thread to be blocked because it's processing. So, now this is where my algorithm that I have create comes into play.

Cropping Algorithm

The main idea of how my algorithm works is:
  1. I merge the two bitmaps together making sure template is placed on top.
  2. Since I know the size of the template, create a new blank bitmap with those dimensions.
  3. From the centre of the combined image, go out quadrant by quadrant, going through every pixel value and copy it onto the blank bitmap.
  4. Once it hits the colour of the template lines, then from that point on set the pixel value of the blank bitmap transparent.
  5. After it has gotten through all 4 quadrants, return the created bitmap, which is the cropped image. 
Here is the cropping code:
Feel free to view, download, and make use of my code HERE!!
Enjoy :)

Link to android-cropping-example.