Use Shaders to mimic some Instagram filter effect.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
.settings on desktop Mar 13, 2014
bin on desktop Mar 13, 2014
gen/com/littlecheesecake/instagram_trial on desktop Mar 13, 2014
libs on desktop Mar 13, 2014
res on desktop Mar 13, 2014
src/com/littlecheesecake/instagram_trial on desktop Mar 13, 2014
.classpath on desktop Mar 13, 2014
.gitignore Initial commit Mar 13, 2014
.project on desktop Mar 13, 2014
AndroidManifest.xml on desktop Mar 13, 2014 Update Mar 13, 2014
ic_launcher-web.png on desktop Mar 13, 2014
proguard-project.txt on desktop Mar 13, 2014 on desktop Mar 13, 2014

##Having More Fun: Explore Instagram-like Filters with Photoshop and OpenGL ES Shaders By LittleCheeseCake

I used to spend quite some time working with Photoshop®, to edit photos or do some digital painting. However I became too lazy to PS since I started to use smartphones. Apps like Instagram® seems to be able to do the processing job more efficiently and produce results that look surprisingly amazing (not considering the quality loss of the photo). After studying the OpenGL Shaders, I thought I should be enable to do mimic the filter effect using shaders, with those previous experience working with Photoshop®. I could first explore in Photoshop® to figure out the steps to take to produce the filter effect. Then I could implement it using OpenGL ES Shaders. After spending some time in research, I kind of found the way to duplicate the filter effect, might not be exactly the same, but the feeling is captured. Take the Hudson filter as an example, I summarized the work I have done.


Working with Photoshop®

Learned from a digital photography course in the college, the first thing we need to do when loading an photo into the Photoshop, is to adjust the level and curve. However I think level and curve adjusting is not that easy to implement in the shaders. How about a less effective but simpler way: adjust Brightness/Contrast/Saturation. All these three steps can be easily realized by blending the image with a base image (either a constant image or the luminanced image of itself). By simply doing these, the quality of the image can be improved quite a lot.

bright and contrast

hue and satu

Then if the filter favors a particular color, can adjust the color balance a bit. Or can also add a filter layer on top then blend it with the base image. Hudson is a filter to make the image have an icy look, the slight tint and altered lighting give the images a colder feel. Therefore a radial gradient mask with blue to black is used for blending. With a lot trials, I found that "overlay" blending mode is best suitable to produce the vignetting effect (darkens the corners). Overlay blending is a combination of multiply and screen. It darkens the darker part and brightens the lighter part of the base image. And we can adjust the opacity of the top filtering layer to make the effect less strong.


blend mode

Basically that's it! Just simply three steps: 1) adjust B/C/S, 2) adjust color balance, 3) overlay blend a radial gradient layer with some opacity. Let's see the result. Emm.. not exactly, but similar.


Implement using OpenGL ES Shaders

So, I have three things to do: adjust the B/C/S, change the color balance and add a new layer of texture to overlay blend on top.

1. Adjust the B/C/S

In my previous post, I have discussed all the three processes, I just combine them into a single function in the Fragment Shader.

vec3 BrightnessContrastSaturation(vec3 color, float brt, float con, float sat){
    vec3 black = vec3(0., 0., 0.);
    vec3 middle = vec3(0.5, 0.5, 0.5);
    float luminance = dot(color, W);
    vec3 gray = vec3(luminance, luminance, luminance);
    vec3 brtColor = mix(black, color, brt);
    vec3 conColor = mix(middle, brtColor, con);
    vec3 satColor = mix(gray, conColor, sat);
    return satColor;

2. Adjust color

I slightly adjust the single channel.

//add blue
vec3 blue_result = vec3(bcs_result.r, bcs_result.g, bcs_result.b * 1.1);

3. Overlay blending

The function of overlay blending:


vec3 ovelayBlender(vec3 Color, vec3 filter)
    vec3 filter_result;
    float luminance = dot(filter, W); 
    if(luminance < 0.5)
        filter_result = 2. * filter * Color;
        filter_result = 1. - (1. - (2. *(filter - 0.5)))*(1. - Color); 
    return filter_result;

The result from shader implementation:


###Some Other Exploration

Similarly I create more filters to mimic the Instagram® style.

  • I add noise at the edge of the top filter lay, to produce the over- exposured film effect in Hefe filter

  • Give high saturation to vibrate the color and to emphasize the dark corners to get X-pro

  • Reduce the saturation and add a lot of red and yellow, to give the feel of Rise filter

  • Add a red to purple filter to get the Toaster effect

hefe_gl xpro_gl rise_gl toaster_gl


This is so fun! Weeks ago I was told by my friend of the words


I start to realize what it means. Find the things you are good at and try to make connection and produce better work on it. I will definitely continue with this work. I am also glad to share with anyone who are interested in this area, find the full implementation of the basic image processing using OpenGL ES Shaders in Android from my github.

####Reference [1] Texture in OpenGL ES

[2] Image Processing using Shaders