Loading...
Logo
Processing Forum

CMYK & Blending Modes

in Programming Questions  •  3 years ago  
I've searched everywhere for how one would go about creating this effect in Processing but to no avail. 
Here is a very basic attempt but for some reason the MULTIPLY MODE for blending does not work as expected :

int cyan = (#009ee0);
int magenta = (#e2007a);
int yellow = (#ffed00);

void setup()  {
  
  size (400,400);
  noStroke();
  background(255);



fill(cyan,MULTIPLY);
ellipse(250,250,150,150);

fill(magenta,MULTIPLY);
ellipse(150,250,150,150);

fill(yellow,MULTIPLY);
ellipse(200, 150, 150,150);
}

Replies(4)

The second parameter to fill() is an alpha value, not a blend mode, so won't work as written.
 
RGB monitors use additive color (fe: black,+red,+green emit both, causing yellow), CMY print is subtractive color (fe: white,-cyan,-yellow absorb all but, causing green).
 
To simulate CMY absorbtion on an RGB emitting monitor you have to think backwards, subtracting the inverse of the color from white (instead of adding up from zero as with RGB).  For example:
Copy code
  1. color notYellow = #0000FF;
    color notCyan = #FF0000;
    color notMagenta = #00FF00;
  2. PGraphics pgCyan;
    PGraphics pgMagenta;
    PGraphics pgYellow;
  3. void setup() {
      size(400,400,JAVA2D);
      pgCyan = createOffscreen();
      pgMagenta = createOffscreen();
      pgYellow = createOffscreen();
      renderEllipse(pgCyan, 250,250, 150,150, notCyan);
      renderEllipse(pgMagenta, 150,250, 150,150, notMagenta);
      renderEllipse(pgYellow, 200,150, 150,150, notYellow);
    }
  4. PGraphics createOffscreen() {
      PGraphics pg = createGraphics(width,height,JAVA2D);
      pg.smooth();
      return pg;
    }
  5. void renderEllipse(PGraphics pg, float x, float y, float w, float h, color c) {
      pg.beginDraw();
      pg.background(0);
      pg.fill(c);
      pg.noStroke();
      pg.ellipse(x,y,w,h);
      pg.endDraw();
    }
  6. void draw() {
      background(255);
      blend(pgCyan, 0,0,width,height, 0,0,width,height, SUBTRACT);
      blend(pgMagenta, 0,0,width,height, 0,0,width,height, SUBTRACT);
      blend(pgYellow, 0,0,width,height, 0,0,width,height, SUBTRACT);
    }
Thanks Dave for the reply and solution. Is it possible however to use PShape (loading svg files) with PGraphics? Eventually, I want to create a  composite image that is made up of an array of  SVG files which serve as pictograms. Each pictogram is made up of either one, two or three of these  SVG files overlayed and given each a cyan, magenta or yellow colour value. I've never used PGraphics before. The solution you give seems quite complicated for what I want to do - Is it the best solution if using SVG files and can it be done with SVG files? 

Thanks

Mark
There are essentially two approaches, mathematically equivalent for the color operations, but reversed in order...
 
1) draw in cmy, then invert, then subtract from white
2) draw in rgb, then add to black, then invert
 
One is likely to seem more straightforward depending on how you view the problem.  In either case, you'd set up an offscreen pgraphics workarea, draw the shape there, then use blend() to do the additive/subtractive into the final composit.
 
For example (using method 1 above):
 
Copy code
  1. PGraphics pgOffscreen;
    PShape shp;
  2. void setup() {
      size(400,400,JAVA2D);
      pgOffscreen = createGraphics(width,height,JAVA2D);
      // svg from the Basics-Shape-GetChild example..
      shp = loadShape("usa-wikipedia.svg");
      shp.disableStyle();
    }
  3. void renderShapeCMYSubtractive(PGraphics pg, PShape ps, float x, float y, float w, float h, color c) {
      pg.beginDraw();
      pg.background(255);
      pg.fill(c);
      pg.noStroke();
      pg.shape(ps,x,y,w,h);
      pg.endDraw();
      pg.filter(INVERT); // turn RGB-on-white into CMY-on-black
      blend(pg, 0,0,width,height, 0,0,width,height, SUBTRACT);
    }
  4. void draw() {
      background(255);
      renderShapeCMYSubtractive(pgOffscreen, shp, -10,100, 256,144, #00FFFF);
      renderShapeCMYSubtractive(pgOffscreen, shp,  50, 70, 256,144, #FF00FF);
      renderShapeCMYSubtractive(pgOffscreen, shp, 130,100, 256,144, #FFFF00);
    }
Thank you Dave.