Found BUG with get() and red() / blue() / green()

edited September 2016 in Questions about Code

Hello

I recently discovered a bug with get() and the functions red green and blue. When I was looking in to why my program wasn't working, I found out that on the api the function get returns a int (or PImage but doesn't matter here). While the functions red green and blue return a float. This is I think my program isn't working.

Could somebody please look into this.

I posted the code below:

PImage pic;

color c1, c2, c3;

int r1, r2, r3; int g1, g2, g3; int b1, b2, b3;

float alternation=2;

void setup() { size(500, 500); pic=loadImage("meme.jpg"); pic.resize(500, 500); image(pic, 0, 0); pic.loadPixels(); }

void draw() { for (int i=0; i<width-1; i++) { for (int j=0; j<height-1; j++) {

  c1=pic.get(i, j);
  r1=red(c1);
  g1=green(c1);
  b1=blue(c1);

  c2=pic.get(i+1, j);
  r2=red(c2);
  g2=green(c2);
  b2=blue(c2);

  c3=pic.get(i, j+1);
  r3=red(c3);
  g3=green(c3);
  b3=blue(c3);

  if ((sqrt(sq(r1-r2)+sq(g1-g2)+sq(b1-b2)))>=alternation 
    || (sqrt(sq(r1-r2)+sq(g1-g2)+sq(b1-b2)))>=alternation) {
    set(i, j, 255);
    println("#000000");
  } else {
    set(i, j, 0);
    println("#FFFFFF");
  }
}

} }

Answers

  • edited October 2016

    This is intended behaviour, as stated here in the docs:

    The value is always returned as a float, so be careful not to assign it to an int value.

    The int returned by get(...) is not an actual integer (number), but rather a color. The numeric value itself is pretty meaningless (at least for us) and the micro-optimizations in Processing's code are to blame for it. It would make much more sense if get(...) returned an object of a new class like Color, but for some reason whoever made that API decided against it.

    The float returned by red(...) on the other hand IS a number, not a color. It says how much red is in the color (int) you passed.

    As for why your code doesn't work: You are effectively doing the same check twice here:

    if ((sqrt(sq(r1-r2)+sq(g1-g2)+sq(b1-b2)))>=alternation 
        || (sqrt(sq(r1-r2)+sq(g1-g2)+sq(b1-b2)))>=alternation) {
    

    (line 16-17)

    This is likely what causes the problem. What you meant was likely something like this:

    if ((sqrt(sq(r1-r2)+sq(g1-g2)+sq(b1-b2)))>=alternation 
        || (sqrt(sq(r1-r3)+sq(g1-g3)+sq(b1-b3)))>=alternation) {
    

    If it still doesn't work, what exactly happens if you try your code? Are there any error messages?

    . . .

    Quick sidenote: One could perform a code clean-up and remove the costy square root operation by squaring alternation instead, but that's probably a bit overkill - after all, it's your code. Anyway, here's how it could've been done for better performance and more extendability:

    float alternationSquared = sq(alternation);
    if (squareLength(r1-r2, g1-g2, b1-b2))>=alternationSquared 
        || (squareLength(r1-r3, g1-g3, b1-b3)>=alternationSquared) {
        // ...
    }
    
    
    
    // somewhere in the code
    float squareLength(float... values) {
        float result = 0;
        for (float value : values) {
            result += sq(value);
        }
        return result;
    }
    
Sign In or Register to comment.