Home > Android, Graphics, My Thoughts > Split v2.0 – Going Online

Split v2.0 – Going Online

A while ago I made a very small app around the idea of selecting an image, then revealing its details by touching the screen and moving your finger and once you’re happy with the result, you can share the photo to other apps.

Yesterday I published a new version where I changed the design and added the ability for users to sign in\register using a Google account then share what’s being created inside the app so other users can view and like.

In this post I’m going to share some technical details that I found interesting while improving the app and implementing the backend.


Backend Development

Writing some backend code was my main motivation to upgrade the app. As an Android apps developer, I had no prior experience with backend development and I wanted to learn a framework for that. I went with Laravel since we use it at work and I’ve been exposed to it on several occasions. Laravel proved to be easy to pickup even for someone who isn’t experienced in backend development. It’s extensively documented and the project structure is really easy to understand. I also have this course to thank.

So without even refreshing my old knowledge of the PHP language itself, I was able to write something simple for my app. The backend provides various REST APIs with the sign in / register being the most interesting one. APIs provided are:

  • Sign Up / Register
  • Uploading a photo
  • Browsing paginated photos
  • Getting photo details
  • Liking / Unliking a photo
  • Getting photo likes

Sign In / Register: this API handles users authorization through an Oauth 2 implementation. The default implementation provided by this library only offered a password grant where authorization requires a username and a password. Since I want my users to login with one click using  a Google account I had to create my own custom grant which proved to be a challenge for someone like me, especially when the docs give you a very large TODO page 😀 .

The API is used for both registration and signing in. It expects a request with a Google ID token sent from the client app. The backend verifies this token with Google servers and retrieves the actual user ID then saves it in the database if it doesn’t exist. I’ve seen some disastrous cases where the backend developer gets the user id from the client app instead of a something secure like Google id token! Such backend developers still don’t understand how any user can use a REST client like Postman and send the id of another user to hijack his account.

After I finished working on localhost, I needed to deploy my backend. After various failures attempting to get Laravel to work on a virtual server, I used Laravel Forge and everything went smoothly.

Compressed Image Format

When I first wrote the photos upload and list APIs I used files. The app exports the created photo as a PNG file then uploads it to the server. I found two issues with PNGs (or any raster format)

  1. File size: PNGs are good for indexed colors, my generated photos have few colors most of the time but I was still getting some files larger than 1MB mainly because the image is full of small circles which cripples the compression.
  2. Differences in screen densities will cause PNGs to be blurred when created on a low density device then viewed on a high density device.

My solution was to create a custom format that stores the actual structure of the cells as a quad tree where tree leaves hold the cells colors. This way I can save some space and also have detailed images on all devices.

The steps to produced a compressed image are as follows:

  1. We start with a simple photo like this
    7 cells
  2. Using a recursive method, serialize the tree structure as a JSON object. The output for the above photo is the following (formatted for your convenience)
     "circle_frame": false,
     "circle_cells": true,
     "background_color": 0,
     "cells": [
  3. Using GZIP, compress the JSON object to a byte array. The output is now an array of bytes, binary in other words.

    31, -117, 8, 0, 0, 0, 0, 0, 0, 0, 53, -118, -53, 14, -62, 32, 16, 69, -1, -123, 117, -101, -64, 48, 51, 60, 126, -91, 105, 26, 68, 106, -116, 40, 9, -75, 43, -29, -65, 75, 105, -36, -99, 115, -17, -7, -120, 120, -81, 49, -89, 101, -83, -31, -103, -124, 95, 67, -34, -46, -16, 31, 99, -54, 121, 19, -2, 93, -9, -74, 93, 66, 124, -36, 106, -39, 95, -41, 37, -106, 92, -86, -16, -93, 106, -27, -103, 76, -45, -88, 16, -119, -119, -26, -95, -95, -106, 78, 26, 62, -72, 9, -80, -45, 32, 93, 63, -128, -40, 0, -38, -109, 45, 88, 70, -18, -84, 28, 27, 54, 56, 119, 33, 96, -115, -121, 124, 127, -68, -128, -27, 120, -97, 0, 0, 0

  1. To make the result more portable, we convert it to a base64 string. This adds a little bit to the result size but makes it more portable.


While the previous example seems like an overkill for storing only 7 circles, see an actual example below

Leaves Photo


The size of the image before compression is 1.4 MB, while after compression it’s only 73,978 ASCII characters, which means it can be stored with a minimum size of 72.2 KB 😀


That’s it for this version. I wrote some code to run a mini version of the app on Android Wear but it currently uses a static photo and that’s not much fun. Maybe I’ll have phone fetch something from the backend then pass it to the android wear device!.


You can give the app a try from here:

Get it on Google Play


  1. Nayana
    12/04/2016 at 10:00 am

    gr8 work

  1. No trackbacks yet.

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: