Problem looping through a 4D array

Yes, interesting. I clicked on the demo lots of times, and the algorithm becomes obvious, but that hakmem175 isn’t. I’ll study it one day.

1 Like

OK, well I managed to spend a bit of time on this, but haven’t made a great deal of progress, and what I have done might be a backwards step!

I’ve merged the two sketches from @Chrisir, and used the function from @RichardDL that calculates 3 bits-on numbers…


// list uses gray scales as index. The list contains the
//different permuts for this gray scale (number of permuts can vary).
ListOfPermuts[] permuts = new ListOfPermuts[256];   

PixelRepresentation[][] myList; 
IntList myBinaryList;
int binaryListLength;
int num;
int count3 = 0;

PImage img;

void setup() {
  size(600, 600);
  noSmooth();
  noStroke();
  //frameRate(1);

  img = loadImage("fashion_MNist_01.png");
  img.resize (200, 200);

  myList = new PixelRepresentation[img.width][img.height];
  myBinaryList = new IntList();


  // RichardDL's code for finding 12 bit binary numbers with 3 bits ON
  for (num  = 0; num < 4096; num++) {
    if (is3bits(num)) {
      count3++;
      myBinaryList.append(num);
    }
  }


  // fill permuts 
  // i represents gray value 
  for (int i=0; i<256; i++) {
    permuts[i] = new  ListOfPermuts( i );
  }//for 

  for (int x = 0; x < img.width; x++) {
    for (int y = 0; y < img.height; y++ ) {
      // Calculate the 1D pixel location
      int loc = x + y*img.width;

      color c1=img.pixels[loc]; 
      myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
    }// for
  }// for
}// setup

void draw() {
  //image(img, 10, 10);

  color c1 = get(mouseX, mouseY); 

  for (int x = 0; x < img.width; x++) {
    for (int y = 0; y < img.height; y++ ) {
      myList[x][y].display();
    }// for
  }// for

  permuts[int(brightness(c1))].display();
  
}// draw


// ================================================================

class PixelRepresentation {

  //
  color col;
  float x, y;

  boolean[][] fieldArray = new boolean [ 4 ][ 3 ]; // !!!!!!!!!!!!  

  PixelRepresentation (color col_, 
    float x_, float y_) {
    col=col_;
    x=x_;
    y=y_;
  }

  void display() {
    // use fieldArray here 
    fill(col); 
    rect(x, y, 3, 3 );
  }
}//class
//


//================================================================

class ListOfPermuts {

  // class holds all permutations for ONE brighntness 

  // length can vary (therefore ArrayList)
  ArrayList<Field> listOfPermutations = new ArrayList();

  int brightnessOfField; 

  // counter or permut for display as an animation
  int permutNum;

  //constr 
  ListOfPermuts (int brightnessOfField_) {

    brightnessOfField = 
      brightnessOfField_;

    // random number of permuts for this brightness.....
    // replace by something that gives the permuts for the brightnessOfField_

    binaryListLength = myBinaryList.size();

    for (int i = 1; i < binaryListLength; i++) {      
      Field f1 = new Field(brightnessOfField);
      listOfPermutations.add(f1);
    } //for
  } // constr ---------

  void display() {
    int xoffset = 330;
    int yoffset = 300;

    // make a horizontal list
    for (Field f1 : listOfPermutations) {
      f1.display(xoffset, yoffset); 
      xoffset += 40;
    }//for

    // Animation 
    Field f1 = listOfPermutations.get(permutNum%listOfPermutations.size()); 
    f1.display(330, height-139);
    permutNum++;
    //
  } // func  
  //
} //class 

//================================================================

class Field {

  // ONE 3x4 Field 

  boolean [][] field = new boolean [3][4];  

  //constr 
  Field (int brightnessOfField_) {

    // replace by something that gives the permuts for the brightnessOfField_
    for (int x = 0; x < field.length; x++) {
      for (int y = 0; y < field[0].length; y++ ) {
        field[x][y] = false;
        int position = x + (y * field.length);
        
        // bitwise trick to iterate over binary digits
        int onOrOff = ((myBinaryList.get(0) & 1<<position) >> position);
        
        if (onOrOff > 0) 
          field[x][y] = true;
      }
    }
  }//constr ---------

  void display( int xoffset, int  yoffset) {
    //
    for (int x = 0; x < field.length; x++) {
      for (int y = 0; y < field[0].length; y++ ) {
        //
        fill(0); 

        if (field[x][y]) fill(255); // WHITE 
        rect(xoffset + x*5, yoffset +  y*5, 4, 4);
      }
    }
  }//func
  //
}//class
//


// ================================================================


// RichardDL's code for finding 12 bit binary numbers with 3 bits ON - function

boolean is3bits(int no)
{
  // return true if given number has 3 bits set.
  int ix;
  int tot = 0;
  for (ix = 0; ix < 12; ix++) {
    if ((no & 1) == 1) tot++;
    no = no >> 1;
  }
  return tot == 3;
}

I am now able to fill the Field object with correct numbers for 3-bits-on, but am filling it with only ONE configuration over and over… I realise this is because I am just using the ‘0th’ item in myBinaryList, but I’m not quite sure what to do to add ALL 220 items in myBinaryList here…

int onOrOff = ((myBinaryList.get(0) & 1<<position) >> position);

I’ll try and break my code down and explain it a bit better tomorrow, but for now, I’m screened out!

1 Like

Hello,

You are almost there I think.

I don’t understand this code by @RichardDL ; therefore I have difficulties to help:

  // RichardDL's code for finding 12 bit binary numbers with 3 bits ON
  for (num  = 0; num < 4096; num++) {
    if (is3bits(num)) {
      count3++;
      myBinaryList.append(num);
    }
  }

Does this make all patterns for ONE gray scale? I don’t understand.

In my code

In my code, I assume you have a list “permuts” that holds for each gray scale ALL the permuts (in the class “ListOfPermuts ”.

Therefore you’d say:

in the constr of class “ListOfPermuts” loop over all the patterns in myBinaryList (but only for the current gray scale!!! So the myBinaryList must be made new within the for loop in draw???
This is the for loop I am referring to

  // fill permuts 
  // i represents gray value 
  for (int i=0; i<256; i++) {
    // make new myBinaryList here? 
    permuts[i] = new  ListOfPermuts( i );  // constr uses myBinaryList? 
  }//for

)

and then in the constr I mentioned:


    binaryListLength = myBinaryList.size();

    for (int i = 1; i < binaryListLength; i++) {

      println(myBinaryList.get(i));

      // USE myBinaryList here !!!!
      Field f1 = new Field(   myBinaryList.get(i)   );  // but in the constr of class Field I don't know how to get the bits from the int? 
      listOfPermutations.add(f1);
    } //for

but in the constr of class Field I don’t know how to get the bits from the int to make the pattern


One fault

One fault (I think): my bad.

PixelRepresentation carries
boolean[][] fieldArray = new boolean [ 4 ][ 3 ]; // !!! should be 3 4
as part of representing an image

but class Field also has this
as part of representing permutations.

Chrisir

1 Like

I did something similar with arduino and a led matrixBicolor,
I create 3x4 in hexa to display my font.
maybe it can help : bicolorMatrix on youtube
the code : bicolor on github

1 Like

Hi @Chrisir - thanks again for your help - I REALLY appreciate it - but I think I’ve got myself into a bit of a mess. :slight_smile:

The problem is I don’t really understand exactly what your code as doing - my fault!

I will try to work through it and answer your questions, but right now I feel out of my depth… :slight_smile:

1 Like

:wink:

MY problem is that I don’t really understand what @RichardDL 's code is doing!

Is it making the patterns for ONE gray scale (which one, 12??) or for all?

I suggested to make the result of brightness(fromPixel) to int to get 0 to 255 as a result.
Then we would need 256 different sets of patterns.

My approach

My approach is simple:

First Line of thought

  • PixelRepresentation[][] myList; holds the image as patterns (2D array)
  • PixelRepresentation contains a 2D array of the pattern (probably this is unnecessary because we have ListOfPermuts)

The 2nd Line of thought

  • ListOfPermuts[] permuts holds a 256 long list (one for each int(brightness()) )
  • ListOfPermuts holds an ArrayList to hold the patterns for each brightness (different numbers)

The 3rd Line of thought

  • To bring this together, we for loop-for loop over the image and fill PixelRepresentation[][] myList; with brightnesses
  • We fill ListOfPermuts[] permuts with permuts for each brightness
  • We display myList which uses the permuts with its brightness and animates over the patterns in its ArrayList

I hope this helps!

Chrisir

1 Like

Thanks for sticking with me @Chrisir!

For the moment, I won’t use RichardDL’s code - it only gives values for 3 pixels on in a 12-pixel grid, and we need ALL permutations for ALL ‘numbers of pixels on’.

I wrote some python code which generates all this data - so I think I should use that for now.

Yes, this makes sense - but because (for a 12-pixel matrix) there are 256 greyscale levels but only 12 pixels, so the number of ‘actual’ grayscale values will be 256/12 ≈ 21.

Thanks for your breakdown above. I’ve got the weekend free, so I hope to get to grips with it!

Here’s an image fo how I see it… Have I got the hierarchy right?

1 Like

Maybe you could restate your problem / goal.

What, concretely are you trying to produce as output? A single grid of boxes, of arbitrary dimensions, that represents a 255 brightness value?

And then you want to display that one single grid on the screen – e.g. the whole sketch canvas taken up by a single 8x8 grid of rectangles, with 64 values, representing a 0-255 brightness?

And then you want to animate it by permutations for that one pixel that you are measuring? So the pixel is 101/255, so you round that to 25 and permute 25 bright boxes across a grid of 64 boxes?

Is that right?

What happens once you have animated through all the permutations of that one pixel? Do you move on to the next pixel in the image and start over?

2 Likes

Hi @jeremydouglass, @chrisir

Thanks for your request to restate/clarify my problem. @Chrisir has given code that solves the problem I posed, and explained it very well, however, I have not been able to fully understand what the code is doing - my fault - I’m just not that familiar with using classes and arrays and constructors to really understand how I can modify it.

This is what I would like to do:





generatePermutations.py [gist]


I haven’t really been able get to grips with @Chrisir’s code, although I know it shows me a better way to represent my data using classes, and it solves most of my problems.

What I’d like to ask @Chrisir is if you could show me how to join your two pieces of code, and how I can ‘add’ my data into the code to fill the listOfPermuts…

If we could just go one step at at time?

1 Like

Almost there.

When you have all permuts: Are these of one brightness? or of how many?

can you post either your permut py sketch as processing sketch here or the results?

1 Like

As I mentioned a few times and didn’t get ANY answer from you: What is Richard’s code doing and for which gray scales?

I mean he provides 220 permuts but how to tell which to use for the brightness?

Are you okay when instead of 256 brightness steps we just work with / or so?

1 Like

got it I think

press any key to toggle between two views:

  • debug view to see all permuts
  • real view of animated graphic

Explanation

the 3x4 grid holds 12 bits, 4096 permutations.

The number of bits that are 1 decide the brightness of the 3x4 grid. If more bits are ON, the grid appears more bright. So there are 12 levels of brightness.

Therefore I use these 12 brightness instead of 256 levels of brightness/gray scales. I use map() command to change from 255 to 12 scale.

The 12 brightnesses each have a different number of permuts (the different grids), between 1 and 220 different grids.

The animation loops between the different grids

I hope this helps.

Chrisir

// list uses gray scales as index. The list contains the
//different permuts for this gray scale (number of permuts can vary).
ListOfPermuts[] permuts = new ListOfPermuts[256];  // ONLY 12 used !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 

PixelRepresentation[][] myList;    // image !!!!!!!!

PImage img;

int state = 1; 

void setup() {
  size(1900, 800);
  background(0) ; 
  noSmooth();
  noStroke();
  frameRate(13);

  img = loadImage("process1.png"); // "fashion_MNist_01.png");
  img.resize (200, 200);

  // fill image grid
  myList = new PixelRepresentation[img.width][img.height];

  // fill permuts 
  for (int i=0; i<256; i++) {
    permuts[i] = new  ListOfPermuts( i );
  }//for
  fillpermuts () ;

  for (int x = 0; x < img.width; x++) {
    for (int y = 0; y < img.height; y++ ) {
      // Calculate the 1D pixel location
      int loc = x + y*img.width;
      color c1=img.pixels[loc]; 
      myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
    }// for
  }// for
}// setup

void draw() {

  background(0) ; 

  switch(state) {
  case 0: 
    for (int x = 0; x < img.width; x++) {
      for (int y = 0; y < img.height; y++ ) {
        myList[x][y].display();
      }// for
    }// for
    break; 

  case 1: 
    // for debug / press any key to toggle 
    background(111); 
    for (int i=0; i<256; i++) {
      fill(0); 
      text(i+"   "+permuts[i].listOfPermutations.size(), 
        17, i*20+22);
      fill(255); 
      text("Permutations Overview.\nTable shows number of gray scale and the number of permutations for that number and the permuts as pixels. \nHit any key to toggly view", 
        140, 299);
      permuts[i].displayLong(i);
    }
    break;
  }//switch
}// draw

// ----------------------------------------------------------------

void keyPressed() {
  //toggle
  if (state==0) 
    state=1; 
  else 
  state=0;
}

// ----------------------------------------------------------------

void fillpermuts () {
  // solution by RichardDL
  int num;
  int count3 = 0;
  for (num  = 0; num < 4096; num++) {
    // RUN ALWAYS, the if is not working / is always true 
    //if (true||is3bits(num)) {
    count3++; 
    // println(String.format("%4d %s %4d", num, binary(num, 12), count3), count(num)  );
    // println(count(num));  
    permuts[count(num)].listOfPermutations.add  ( new Field ( binary(num, 12) ));
    //}//if
  }//for
  //
}

// ================================================================

class PixelRepresentation {

  // represents the entire image 
  color col;
  float x, y;
  int brightnessOnScale12 ; 

  PixelRepresentation (color col_, 
    float x_, float y_) {
    col=col_;
    brightnessOnScale12 = int(map(brightness(col), 0, 255, 0, 12)); 
    x=x_;
    y=y_;
  }

  void display() {
    permuts[brightnessOnScale12].display(x, y);
  }
}//class
//
//================================================================

class ListOfPermuts {

  // class holds all permutations for ONE brighntness 

  // length can vary (therefore ArrayList)
  ArrayList<Field> listOfPermutations = new ArrayList();

  // counter or permut for display as an animation
  int permutNum;

  //constr 
  ListOfPermuts (int brightnessOfField_) {
    //
  } // constr ---------

  void display(float x_, float y_) {
    // Animation 
    Field f1 = listOfPermutations.get(permutNum%listOfPermutations.size()); 
    f1.display(x_, y_);
    permutNum++;
    //
  } // func

  void displayLong(int i_) {
    int xoffset = 70;
    int yoffset = i_*20+20;

    // make a horizontal list - just to get an overview
    for (Field f1 : listOfPermutations) {
      f1.display(xoffset, yoffset); 
      xoffset += 20;
    }//for
  }//method
  //
} //class 

//================================================================

class Field {

  // ONE 3x4 Field 

  boolean [][] field = new boolean [3][4];  

  //constr 
  Field(String s1_) {

    // reads a String: binary data

    int counter=0; 
    // 
    for (int x = 0; x < field.length; x++) {
      for (int y = 0; y < field[0].length; y++ ) {
        field[x][y] = false;

        if (s1_.charAt(counter)=='1') {
          field[x][y] = true;
        }
        counter++;
      }
    }
  }//constr 

  void display( float  xoffset, float   yoffset) {
    //
    for (int x = 0; x < field.length; x++) {
      for (int y = 0; y < field[0].length; y++ ) {
        //
        fill(0);
        stroke(0); 
        if (field[x][y]) {
          fill(255); // WHITE
          stroke(255);
        }
        //rect(xoffset + x*5, yoffset +  y*5, 4, 4);
        point(xoffset +x, yoffset + y);
      }
    }
  }//func
  //
}//class

// ================================================================

// RichardDL's code for finding 12 bit binary numbers with 3 bits ON - function

//boolean is3bits(int no)
//{
//  // return true if given number has 3 bits set.
//  int ix;
//  int tot = 0;
//  for (ix = 0; ix < 12; ix++) {
//    if ((no & 1) == 1) tot++;
//    no = no >> 1;
//  }
//  return tot == 3;
//}

int count(int no)
{
  // return from  given number the  bits set Number
  int ix;
  int tot = 0;
  for (ix = 0; ix < 12; ix++)
  {
    if ((no & 1) == 1) {
      tot++;
    }
    no = no >> 1;
  }
  return tot ;
}
1 Like

@Chrisir - you are amazing - and your solution is beautiful:


VIDEO:
https://youtu.be/2_eleGCoSwE


HUGE thanks to all who have helped on this - @Chrisir @RichardDL @jeremydouglass @glv

This has been part of a personal project I have been working on during the COVID-19 lockdown using LCD Character Displays… a couple of images here:

VIDEO:
(https://www.youtube.com/watch?v=vbP9f3YmiEs)


However - I can not call this project my own until I can reproduce what @Chrisir et-al have done. That is my task on-going, and you have given me all the clues I need to do so. Thank you!

2 Likes

Hello,

How cool is that hardware! I may contact you to discuss…
If you can find an investor consider replacing those LCDs with OLEDs. Better viewing angles and great in light and the dark! I have done this for a few high profile projects.

You will be able to code this from scratch! Glean insight where needed and make it your own.

I liked Richards approach to finding bits.

What is communicating with the LCDs?

I see permutations used a lot in this topic; it should be combinations.
Too many permutations!

Permutation Calculator
Combination Calculator

:)

1 Like

Thank you for your kind words, was a pleasure to work with you. :wink:

Warm regards,

Chrisir

P.S.

When you look at setup() again

void setup() {
  size(1900, 800);
  background(0) ; 
  noSmooth();
  noStroke();
  frameRate(13);

  img = loadImage("process1.png"); // "fashion_MNist_01.png");
  img.resize (200, 200);

  // fill image grid
  myList = new PixelRepresentation[img.width][img.height];

  // fill permuts 
  for (int i=0; i<256; i++) {
    permuts[i] = new  ListOfPermuts( i );
  }//for
  fillpermuts () ;

  for (int x = 0; x < img.width; x++) {
    for (int y = 0; y < img.height; y++ ) {
      // Calculate the 1D pixel location
      int loc = x + y*img.width;
      color c1=img.pixels[loc]; 
      myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
    }// for
  }// for
}// setup

from an aesthetically point of view:

the parts concerning

  • image, img and PixelRepresentation (it’s for image) should be one section,
  • and only after that the section with permuts;
    so better version:
void setup() {
  size(1900, 800);
  background(0) ; 
  noSmooth();
  noStroke();
  frameRate(13);

  // load image 
  img = loadImage("process1.png"); // "fashion_MNist_01.png");
  img.resize (200, 200);

  // prepare and fill image grid "myList"
  myList = new PixelRepresentation[img.width][img.height];
  for (int x = 0; x < img.width; x++) {
    for (int y = 0; y < img.height; y++ ) {
      // Calculate the 1D pixel location
      int loc = x + y*img.width;
      // get color 
      color c1 = img.pixels[loc]; 
      // store color and future position 
      myList[x][y] = new PixelRepresentation (c1, x*5, y*5);
    }// for
  }// for

  // prepare and fill permuts 
  for (int i=0; i<256; i++) {
    permuts[i] = new  ListOfPermuts( i );
  }//for
  fillpermuts () ;

}// setup

Remark

Also I made the function int count(int no) which is a variation of Richard’s is3bits().

It counts how many 1’s there are in a bit pattern thus determine also its brightness (from 0 to 12).

I use this an index for permuts[] array.

When retrieving data from permuts I map (use map() command) the brightness from 0…255 to 1…12 to use this as an index for permuts[].

Remark

Since binary() gives you the bit pattern as a String (length 12) I use this (with charAt()) to fill the 3x4 fields representing the patterns for each pixel.

1 Like