Colouring pixels

I want to colour the pixels of a 255 px x 255 px square so the x axis (left to right) shows red from 0 to 255 and the y axis (top to bottom) shows green from 0 to 255.

step_1

This is only the first step of an ambitious project so I want to work from robust foundations.

Q1 Is Pimage the best way to do this (see below), or should I draw a shape, or just use the background? Or other?

Q2 Currently I have the size of the sketch the same as the size of the image. I actually want the sketch to be much larger than the image. The image will still be 255 x 255. How do I do that?

My code:

PImage img;
String filename = str(month()) + str(day());

void setup() {
  size(255, 255); //I want a white margin. This is currently same size as image.
  noLoop();
  img = loadImage("blank.png"); // this is just a blank image 255 px by 255 px
  colorMode(RGB, 255, 255, 255);
}

void draw() {
  loadPixels();
  img.loadPixels();
  for (int y = 0; y < height; y++ ) {
    for (int x = 0; x < width; x++ ) {
      int loc = x + y*width;
      pixels[loc] = color(loc%width, (loc - (loc%width))/width, 0); //
    }
  }

  updatePixels();
  save(filename + ".jpg");
  println("done");
}
1 Like

Check this out:
https://processing.org/examples/rgbcube.html

I had some fun with the cube and animated it:
RGB Cube

:slight_smile:

Please note that there are a few errors in the code

you should apply your operations to img not to the canvas

This means that you have to put img. in front of width and height and save and updatePixels

1 Like

yes, @Chrisir good idea:

int w = 255;
PImage img = createImage(w, w, ARGB);

void make_image() {
  img.loadPixels();
  for (int i = 0; i < img.pixels.length; i++) 
    img.pixels[i] = color(i%w, (i - (i%w))/w, 0);
  img.updatePixels();
}

void setup() {
  size(300, 300); //I want a white margin.
  make_image();
}

void draw() {
  background(255);
  image(img, (width-w)/2, (height-w)/2);
  fill(0);
  int mx = mouseX;
  int my = mouseY;
  color c = get(mx,my);
  text("mouse: X "+mx+" Y "+my+" color("+(int)red(c)+","+(int)green(c)+","+(int)blue(c)+")",10,height-10);
}

void keyPressed() {
  if ( key == 's' ) {
    String filename = "data/"+year()+month() + day()+".jpg";
    save(filename);
    println("save "+filename);
  }
}


1 Like

Mmm. I did that @Chrisir (see below) but it returns a blank image. If I remove the img from the updatePixels(), I get something but it is wrong.

Here is the ‘wrong’ result. I include it because it suggests (to me) that my problems are in the line that starts pixels[loc] =
39

PImage img;
String filename = str(month()) + str(day());

void setup() {
  size(455, 455); //I want a white margin. This is currently same size as image.
  noLoop();
  img = loadImage("blank.png"); // this is just a blank image 255 px by 255 px
  colorMode(RGB, 255, 255, 255);
}

void draw() {
  loadPixels();
  img.loadPixels();
  
  int myWidth = img.width;
  println(myWidth);
  
    int myHeight = img.height;
  println(myHeight);

  
  for (int y = 0; y < myHeight; y++ ) {
    for (int x = 0; x < myWidth; x++ ) {
      int loc = x + y*myWidth;
      pixels[loc] = color(loc%myWidth, (loc - (loc%myWidth))/myWidth, 0); //
    }
  }

  img.updatePixels();
  img.save(filename + ".jpg");
  println("done");
}

That works perfectly. createImage() is way better than new PImage(). And, make_image as a function is very interesting. Are you anticipating that make_image might be called a number of times as the project grows or is it a good idea anyway?

if it is static you call it once from setup();
so it only is for readability

if you give it parameters ( like for different colors… )
you might call it again at keyPressed()

but doing it in
draw() && noLoop()
makes at first no difference, but i think it
is a very limited project design.

make it in draw() with 60 loops per sec ( or less )
wastes your cpu power.


PImage img;
color cb=color(255);

void make_image(int w,int b) {
  img = createImage(w, w, ARGB);
  colorMode(RGB,w);
  img.loadPixels();
  for (int i = 0; i < img.pixels.length; i++) 
    img.pixels[i] = color(i%w, (i - (i%w))/w, b);
  img.updatePixels();
}

void setup() {
  size(300, 300);
  fill(0);
  imageMode(CENTER);
  make_image(255,0); //___ size and color range 255, blue 0 
}

void draw() {
  background(cb);
  image(img,width/2,height/2);
  int mx = mouseX;
  int my = mouseY;
  color c = get(mx,my);
  text("mouse: X "+mx+" Y "+my+" color("+(int)red(c)+","+(int)green(c)+","+(int)blue(c)+")",10,height-10);
}

void keyPressed() {
  if ( key == 's' ) {
    String filename = "data/"+year()+month() + day()+".jpg";
    save(filename);
    println("save "+filename);
  }
  if ( key == 'r' ) make_image(100,80); //___ size and color range 100, blue 80 of 100
}

1 Like

Is your first solution robust enough for expanding into a larger project? Or, is there a better way to do this?

that would very much depend on the project.

a program flow with
++ setup
++ draw
++ keyPressed
++ mousePressed
has something to do with interaction, animation…

your layout with
++ setup noLoop
++ draw with make image and save image (end)
would be for creating one image file,
possibly more lengthy hardcoded operations coming.


sometimes i get my own idea wrong and have to redo it from start,
what is bad with this?

1 Like

that was one problem in the old code: it must be img.pixels

OK, thank you, almost there

I have marked the code as section 1, 2 and 3
Strangely, the file that is saved is correct, so section 2 is working but there is no screen image in the sketch window!

What am I doing wrong? Or is the right code in the wrong place?

PImage img;
String filename = str(month()) + str(day());

//section 1
void setup() {
  size(455, 455); //I want a white margin.
  noLoop();
  img = loadImage("blank.png"); // this is just a blank image 255 px by 255 px
  colorMode(RGB, 255, 255, 255);
}

//section 2
void draw() {
  loadPixels();
  img.loadPixels();

  int myWidth = img.width;
  //println(myWidth);

  int myHeight = img.height;
  //println(myHeight);


  for (int y = 0; y < myHeight; y++ ) {
    for (int x = 0; x < myWidth; x++ ) {
      int loc = x + y*myWidth;
      img.pixels[loc] = color(loc%myWidth, (loc - (loc%myWidth))/myWidth, 0);
    }
  }

  //section 3
  img.updatePixels();
  img.save(filename + ".jpg");
  println("done");
}
1 Like

These are the proposed steps, but not necessarily in the right order. What do you suggest I do first, or does it all have to happen at the same time?

1/ make the red green colour space larger. It is currently 255 x 255 because there is a 1:1 mapping between the colour value and the distance, but I would like a larger image.

2/ add a way of entering a colour, presumably as a hex().

3/ when the colour is entered it will show both as a disc (small unfilled circle) in the colour space and as a swatch to the side of the colour space. Text near to the swatch will show the three values as RGB or hex (and maybe more).

the colour space will not be RGB, more likely to be Hue, Chroma, Lightness

Note: As the colour is entered as a hex, the values will need to be changed to HCL. I do not want to enter as HCL as user is unlikely to know these values. The initial hex need not be precise as values can be adjusted later (4)

4/
When the disc is moved, the values of the colour (and so also the swatch) will change.

5/
There will be a slider under the two-dimensional colour space. The slider will determine the third dimension of a colour space. So, for example in the RGB colour space, the two dimensions are red and green, and the slider would vary the blue from minimum to maximum.

The first version will have a Hue-Lightness planar surface and a Chroma slider.

Note: when the initial colour is entered, the slider will need to move to the correct value in the third dimension of the colour space

6/ Some colours are outside the RGB colour space. These will need to be clipped and the relevant pixels shown as white.

Later…

7/ When the first disc is placed (as a result of entering a colour), a second disc will be automatically placed at some algorithmically random distance and angle from the first disc. There will be a second swatch to show this colour. This disc is moveable in the same way as the first disc.

Even later…
8/ A line will be automatically drawn between the centres of disc 1 and disc 2. This length of this line will be divided into segments of equal length. These points will be used to determine the colours between colour 1 and colour 2 and the interpolation will also be shown as swatches. Number of steps can be increased and decreased.

1 Like

Because you have noLoop(); in setup()

Delete this

What you have in draw now should be better in setup ()

Also in draw you need image(img,…); to display the changed image

so in short form:
you want make a interactive color super wheel program

but your program flow as seen again and i described as “MAKE PICTURE” program
can not be used for this.

also you not want use my provided code where you already have the beginning of a

void make_image(int w,int b) {}

more variable function ( resize image and color range )


OK, noLoop is gone.

What is image(img); ?? I tried
image(img,0,0);
but still no screen image.

Show your entire code please

PImage img;
String filename = str(month()) + str(day());

void setup() {
  size(455, 455); //I want a white margin. This is currently same size as image.
  //noLoop();
  img = loadImage("blank.png"); // this is just a blank image 255 px by 255 px
  colorMode(RGB, 255, 255, 255);
}

void draw() {
  loadPixels();
  img.loadPixels();

  image(img, 50, 50);// just testing

  int myWidth = img.width;
  println(myWidth);

  int myHeight = img.height;
  println(myHeight);


  for (int y = 0; y < myHeight; y++ ) {
    for (int x = 0; x < myWidth; x++ ) {
      int loc = x + y*myWidth;
      img.pixels[loc] = color(loc%myWidth, (loc - (loc%myWidth))/myWidth, 0); //
    }
  }

  updatePixels();
  img.save(filename + ".jpg");
  println("done");
}

As I said bring your draw content to setup

In draw only the image(img, …); remains

Here an img. is missing!!!

At least make this line the last line in draw()