Combining Different Light Sources on Photos

Once we already learned how to digitally manipulate images with processing its time to a new assignment from Multimedia Systems course. The task now is explore the manipulation of multiple photographs from the same scene with different light sources by combining them completely or just specifics color channels. You’ll see how amazing are the results achieved in this post.

Reference Photograph

Reference Photograph (with both light sources)

Our subject is an action figure from Neil Gaiman’s Sandman and all three photographs were taken with a regular Sony manual camera fixed some inches from the scene and with two directional light sources. The first photograph was taken by turning on both light sources, then each one of them was turned off for taking another photograph.

Manipulating the photographs

The chosen manipulations  for the assignment were the combination of both pictures with one light source for comparing with the reference image, and also play with image color channels. If you have a camera of good quality (that’s not my case) the results are even better and all you need for simulating the reference image is summing the values of each color channel of single lighted images.

Simulated Image

Simulated Image

For playing with color channels and its influence in final image I’ve added six buttons representing the presence of RGB colors from left and right image in final color value. Also, before summing images, the values are multiplied by a variable that indicates the intensity of the contribution of each image in final color. All results can be viewed in following gallery.

The Code

Part of the interactive code was taken from the example of professor Erick Passos  available here, and this snippet is used for define the contribution of each image in the final result by using the map function for transform the mouseX value in another number based in the width of the image.

float normalizedX = map(mouseX, 0, width, -1,1);
float rightIntensity = 1;
if (mouseX < width/2) {
 rightIntensity += normalizedX;
float leftIntensity = 1;
if (mouseX > width/2) {
 leftIntensity -= normalizedX;

The other snippet presented just read the RGB values for each pixel in input images, multiply them by the calculated intensity and, if the corresponding channel is enabled, apply its sum in final value.

for (int i = 0; i<leftImg.pixels.length; i++) {
 color c1 = leftImg.pixels[i];
 color c2 = rightImg.pixels[i];

 float rightR = red(c2)*rightIntensity;
 float rightG = green(c2)*rightIntensity;
 float rightB = blue(c2)*rightIntensity;

 float leftR = red(c1)*leftIntensity;
 float leftG = green(c1)*leftIntensity;
 float leftB = blue(c1)*leftIntensity;

 if (bleftR == false) {leftR = 0;}
 if (bleftG == false) {leftG = 0;}
 if (bleftB == false) {leftB = 0;}
 if (brightR == false) {rightR = 0;}
 if (brightG == false) {rightG = 0;}
 if (brightB == false) {rightB = 0;}

 sumImg.pixels[i] = color(leftR+rightR , leftG+rightG,leftB+rightB, 255);

Final Considerations

I hope you’ve enjoyed this post and try this experiments for real, a interactive applet is available here for all of you explore the results. I’m planning follow a friend’s example and create a GIT repository for all the example codes used here be available for you download and modify as you wish. For now, feel free to used the comments for asking any questions about the code.


Leave a Reply

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

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

Google photo

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

Twitter picture

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

Facebook photo

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

Connecting to %s

%d bloggers like this: