Speed Coding 2016 – Q2
13 April 2016, by Chris Arnott
Here’s question 2 from our recent speed coding competition. See how quickly you can solve it.
iPhone icons are displayed with transparent rounded corners, but these are applied at display time: they’re stored as fully-opaque squares.
I would like to take any 120×120 app icon and apply iPhone-like transparent rounding to it so I can display it on a web page.
For simplicity let’s do this by editing the alpha channels only for the affected pixels i.e. there’s no need to remove no-longer-visible colour information from a now completely transparent pixel. The rounding I’d like to use is the following super-ellipse, which is very close to the rounding used by iOS:
where (0,0) is the centre of the 120×120 image, i.e. so that x/60 has range -1 to +1.
Problem 1 (optional) – A simple approach first
- read in a 120×120 icon from a PNG or BMP file
- apply a very simple version of the transparency: make a pixel fully transparent (alpha = 0) if the centre of the pixel falls outside the curve in each quadrant or fully opaque (alpha = 255) if it is inside
- write the output back to a PNG or BMP and send it to me, along with the program you used.
N.B. I want to use the centre of each pixel for this calculation, not the corner. i.e.
and in the unlikely event a point falls precisely on the curve we’ll count it as inside.
Problem 2 (main problem)
That looks OK, but the edges of the curve could be smoother. The alpha channel has range 0-255 for the alpha channel so let’s try and pick a more precise number for each pixel on the curve. We’ll use a simple form of ray-tracing: divide each pixel into a 16×16 grid and count the number of cells in that grid whose centres fall inside the curve.
This will give us a number from 0 (no cells fall inside => fully transparent) to 256 (all cells fall inside => fully opaque). To clip this to the 0-255 range let’s drop one counted cell, i.e.
alpha = max(cells_inside_curve – 1, 0)
If I’m super-obsessive about accuracy of the alpha as the fraction of the pixel inside the curve then even this isn’t enough: why not? Suggest a simple-to-implement approach that would get more accurate corners.