How to stop RGB from being multiplied by Alpha

edited October 2016 in Library Questions

Hey everyone,

Goal : Pack 32bit values into a single pixel and send via texture over Spout.

Problem : The RGB values of color() are multiplied by the alpha, so even if R, G, and B are set to 255, if the Alpha is set to 0, get() returns R,G,B values of 0.

Question : Is there a way to prevent RGB from being multiplied by Alpha? I've tested this in different software and it works fine.

I've made an example :

Sender > The canvas is split into 2, the left side has 0 Alpha, and the right has full Alpha. Other than that they are the same.

import spout.*;

Spout spout;

float rate = 1.0;
float amplitude = 255;

void setup() {

  size(640, 360, P3D);
  colorMode(RGB, 255);
  frameRate(30);

  // spout object
  spout = new Spout(this);
  // name sender
  spout.createSender("Spout Processing");

} // end setup

void draw() {

  background(0,0,0,0);

  int m = millis();
  float Hz = rate  * 1000;
  float lfo = map(sin(radians(360) * m % Hz), -1, 1, 0, amplitude); //Sinewave LFO

  // left -- 0 alpha 
  noStroke();
  fill(lfo,lfo,lfo,0);
  rect(0,0,320,360);

  // right -- full alpha
  noStroke();
  fill(lfo,lfo,lfo,255);
  rect(321,0,640,360);

  spout.sendTexture();

} // end draw

Receiver > Captures the texture via spout and analyzes pixels from each half and prints out the values in the textport.

import spout.*;

Spout spout;

void setup() {

  size(640, 360, P3D);
  colorMode(RGB, 255);
  frameRate(30);

  spout = new Spout(this);

} // end setup 

void draw() {

    background(0,0,0,0);

    spout.receiveTexture();

    // left -- 0 alpha
    color l = get(0,0);
    // right -- full alpha
    color r = get(321,0);

    print("0 ALPHA >>> ");
    print(red(l), blue(l), green(l), alpha(l));

    print(" --- FULL ALPHA >>> ");
    println(red(r), blue(r), green(r), alpha(r));

} // end draw

Thanks!

Answers

  • edited October 2016 Answer ✓

    @nousbalance -- Unfortunately, I cannot test this (I'm not on Windows).

    However, your problem isn't spout -- it is that you are drawing to the Processing surface, then expecting to be able to recover RGB separate from A.

    It looks like you are using spout to draw onto the main drawing surface, then trying to recover RGB values independent of the alpha channel. The Processing surface doesn't work that way. The surface doesn't have an alpha channel (there is nothing 'behind' it) -- so anything with transparency gets mixed into whatever pixel is already there and becomes flat RGB values.

    background(): It is not possible to use the transparency alpha parameter with background colors on the main drawing surface. It can only be used along with a PGraphics object and createGraphics().

    Thus a perfectly transparent RGB pixel becomes a whatever-was-there-before pixel (e.g. grey). Then, when you check RGB on the pixel, you find grey at full-alpha rather than the original data.

    Here is a simple sketch similar to your two test sketches to let you inspect how this works.

    void setup() {
      size(640, 360, P3D);
      colorMode(RGB, 255);
      noStroke();
      noLoop();
    }
    
    void draw(){
      // without a background, canvas defaults to grey (204,204,204)
      // background(0);
    
      // replace background with new color
      fill(100,128,255,255);
      rect(0,0,width/2,height);
      printPixel(width/4,height/2);
    
      // background remains unchanged by adding pixels at 0 alpha
      fill(100,128,255,0);
      rect(width/2,0,width,height);
      printPixel(3*width/4,height/2);
    }
    
    void printPixel(float x, float y){
      int c = get(int(x),int(y));
      println("R:", red(c), "G:", green(c), "B:", blue(c), "A:", alpha(c), "raw:", c);
    }
    

    Options to solve your problem:

    1. Can you use spout to write to a PGraphics or PImage, which supports alpha, then draw that onto the sketch surface using image()?

    2. ...could this be related to the difference between using receiveTexture and receiveImage?

  • @jeremydouglass,

    This is great info. PImage is working out exactly how I hoped.

    Thank you very much for your help

  • @nousbalance -- great! Glad to hear that using PImage preserved your alpha channel. If you can, please share your specific solution -- it might be helpful to future Spout users.

Sign In or Register to comment.