content area
content area
content area
content area

Reverse blending modes


This was a thought experiment on the possibility of terminating semi-transparent foreground elements by restoring the remaining underlying colors instead of using inaccurate area replacement tools like the clone stamp tool or color correction.


For this example I had no live update. Images had to be exported seperately and put into Processing where I did the calculation. So it wasn't as intuitive as I imagine it to be.

  • Reversing a blending mode can't be done for all blending modes. Those that consists of if/else-statements can't be reversed. Wikipedia lists all blending mode calculations here.
  • The higher the opacity of the semitransparent foreground, the harder it gets to restore the right color. Color quantization occurs. The search for the resulting color is limited by the detail of the color depth.


-- CODE language-js -- PImage img; PImage overlay; float blend_reduce; void setup() { size(1920, 1080); // image size img = loadImage("01_start_v2.png"); // Link to starting image in the same folder overlay = loadImage("02_painted_overlay_v2.png"); // Link to overlaying painted picture with alpha channel in the same folder blend_reduce = 0; //0-255 } void draw() { loadPixels(); // Since we are going to access the image's pixels too   overlay.loadPixels(); img.loadPixels(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int loc = x + y*width; // The functions red(), green(), and blue() pull out the 3 color components from a pixel. float ri = red(img.pixels[loc]); float gi = green(img.pixels[loc]); float bi = blue(img.pixels[loc]); float rw = red(overlay.pixels[loc]); float gw = green(overlay.pixels[loc]); float bw = blue(overlay.pixels[loc]); float aw = alpha(overlay.pixels[loc]); float r_final = (ri-rw*aw/(255-blend_reduce))/(1*(1-aw/(255-blend_reduce))); float g_final = (gi-gw*aw/(255-blend_reduce))/(1*(1-aw/(255-blend_reduce))); float b_final = (bi-bw*aw/(255-blend_reduce))/(1*(1-aw/(255-blend_reduce))); // Image Processing would go here // If we were to change the RGB values, we would do it here, // before setting the pixel in the display window. // Set the display pixel to the image pixelpixels[loc] =  color(r_final,g_final,b_final);         } } updatePixels(); save("03_generated_result_v2.png"); stop(); exit(); }