Return value between 0 and 255 indicating shade of image at specified location

Viewed 147

I have a monochrome (black and white) image that I am trying to extract a value between 0 and 255 indicating the shade of the pixel, with 0 being black and 255 being white. I import the image as follows:

PImage img;

void setup() {
  size(1000, 1000);
  img = loadImage("myimage.jpg");
  x_location = 50;
  y_location = 230;
  // add code to extract shade from img here
}

I am trying to use get() to extract the shade. Unfortunately, when I try to use img.get(x_location, y_location) it returns a very large negative number (on the order of -1000000). Is there a way to ensure that get() returns some normalized (understandable) value?

2 Answers

This is very interesting. Here's some skeleton code which will help you get what you want:

PImage img;
color currentColor;

void setup() {
  size(656, 354);
  currentColor = color(0);
  img = loadImage("bean.jpeg");
}

void draw() {
  background(0);
  image(img, 0, 0);
  
  fill(currentColor);
  stroke(200);
  strokeWeight(2);
  ellipse(30, 30, 40, 40);
  fill(0);
  text("A  " + alpha(currentColor), 10, 65);
  text("R  " + red(currentColor), 10, 75);
  text("G  " + green(currentColor), 10, 85);
  text("B  " + blue(currentColor), 10, 95);
}

void mouseClicked() {
  currentColor = img.get(mouseX, mouseY);
}

Which looks like this:

Picking colors!

The magic here is to know that you can extract the ARGB info which are part of the color. Yet, I also wondered why it was a negative number. Here's why (emphasis mine):

Colors, in Processing, are stored actually in simple Java ints, 32-bit values. The color pseudo-type is actually replaced by Processing with int when generating Java code before compilation.

This type has a width of 32 bits, which is perfect as we can put 4 channels of 8 bits each inside. 8 bits allow a range of of values from 0 to 255 (included). The 4 channels are alpha (opacity), red, green, blue, the whole being often abbreviated as ARGB.

Low value of color channel means "low intensity", darkness. High value means "high intensity", lightness. So if all channels are 0, we have black; if they are all at 255, we have white. Alpha channel is different: 0 means low opacity, fully transparent, while 255 means high opacity, normal opaque color.

In Java, numbers are always signed. In computing, negative numbers are marked by setting the highest bit to 1. So, opaque colors, the most common kind, the default if no opacity is given, is 0xFF = 255, the high bit is set to 1, the color value is negative. Hence the answer to the first question...

The strange values are the result of combining all the values of the channels. Let's take a simple yellowish color. Alpha is 255 (opaque), red is 250, green is 230 and blue is, say, 20. These values are 0xFF, 0xFA, 0xE6 and 0x14. Combined to make an int, it gives 0xFFFAE614, ie. -334316. Hence a strange number, not very easy to decipher.

You can use any part of the RGB info if your image is really in grayscale. Have fun!

Here a little code to understand how work Processing with color arguments. I hope tha's can help you.

void setup() {
  colorMode(RGB,255,255,255,255);
  println("colorMode",g.colorModeX,g.colorModeY,g.colorModeZ,g.colorModeA);
  background(random(g.colorModeX),random(g.colorModeY),random(g.colorModeZ),random(g.colorModeA));
  int color_arg = get((int)random(width),(int)random(height));
  println("color_arg: ",color_arg);
  println("color_arg rgb_a:",red(color_arg),green(color_arg),blue(color_arg),alpha(color_arg));
  println("color_arg hsb_a:",hue(color_arg),saturation(color_arg),brightness(color_arg),alpha(color_arg));
}
Related