I have simulated the grainy effect as shown below:
For this I firstly generate a random integer between 1000 to 2000 in C called "rand_seed" and pass it into the GLSL fragment shader as a uniform variable. In GLSL I used the sin function as the pseudo number generator.
int rand = int(abs(sin(rand_seed * fs_Texcoords.x * fs_Texcoords.y)) * 10000);
rand = rand & 63;
out_Color *= max( 1.0f, (float(rand) / 64.0f + 0.5f));
The first line generate an integer according to the fs_Texcoords.
This process uses the third and fourth digit after the decimal point by doing bitwise and operation with 0x3F.
Then the result is divided by 64.0 to get the grainy weight of the current pixel. Since the color of each pixel should be mostly determined by the original picture, I decrease the influence of grainy effect by half using the max( 1.0f, (float(rand) / 64.0f + 0.5f)) and multiply the result to out_Color.
Because the rand_seed is updated every frame, this method could easily create dynamic distributed grainy effects over time.
I just implemented Sepia Tone Filter and Lens Blur to images.
Below is the original image:
For the Sepia Tone Filter, I used a linear equation to convert the color from the original image as a texture map. The image after filtered is shown as below:
For the lens Blur effect, I used a simple circle to distinguish between the center and boundary area. Then for the boundary I applied box blur and controlled the size of the box linearly to the pixel distance from the center. The size of the box means the scale of the average interpolation surrounding the target pixel.
These two effects are easily combined. Since Lens Blur requires communication between pixels while Sepia Tone Filter operation is independent to each pixel, I firstly get the blurred image and then apply the Sepia Tone Filter to the modified color value. Below is the final result.
I will implement scratches and maybe also grains later this week. I will also do more research into Android SDK and camera API.