Output in Text file or spreadsheet possible with Processing?

Hello dear Processing-Community!
I am completely new to Processing as well as relatively new to programming in general. Someone suggested to use Processing for a task I wanted to achieve but now other people are telling me it is difficult or easier to do with other tools.
So here’s my task and the related questions:
What I want to do is

  • take any b&w photo (greyscale rather) and load it into the programm
  • get the size in pixel of the image
  • create an array (I think) which is the size of the image (say 600 pixel x 400 pixel)
  • write the greyscale numbers (from 0 to 255) into that array
  • save the array in a text file (table) so that the greyscale value is taking the place of the equivalent pixel
  • create a second output file that lists next to a certain greyscale number all the coordinates of all the pixels that are in that greyscale.

To illustrate what I want, I have created a small graphic:

Is this possible with Processing?
If yes, then is there maybe someone who can help me with it (paid of course) or do you know where I can find someone who could help me with it?

Hope I made myself clear, thanks in advance!
Astrid

1 Like

It’s completely possible, and pretty easy. It might not be the fastest or most efficient way to do this, as streams, readers, writers and other raw Java stuff can accomplish this better, but it’s certainly understandable.

Hold on, I’ll reply to this thread in a few minutes with a Processing sketch that does everything.

Oh, thanks! Already good to know it can be done!

Well, about an hour later, I’m done.
The code below does the task, with some commentaries to tell what’s going on.
For the “second output file”, I decided to go with (2, 1); style coordinates instead of B1; as otherwise it tries to use characters beyond letter Z if the image is too wide, which results in a bunch of punctuation characters, followed by lowercase letter set, followed with more technical symbols and letters from other languages your computer may not understand.
Although if you need that, you can uncomment a few lines that are pointed by the comments in the code.

Save it as a sketch somewhere, go to “Sketch” submenu at the top of Processing and in there select “Show sketch folder”, drop your image named the same as what’s in the code into the folder that opens, and run to get 2 additional files near it.

void setup(){
  
  
  //This is not the most efficient way to do the given task,
  //as this code loads the image, converts it to a 2D array,
  //and converts that to a bunch of strings - 
  //but it's the most readable way to do this.
  
  String imageName = "image.png"; //Type your image's name here!

  PImage test = loadImage(sketchPath(imageName)); //Load the image
  
  short[][] pixelsArray = new short[test.width][test.height]; //Create a 2D array with the size of the image
  //"short" actually stores up to 32767, but "byte" stores up to 127 and for this example I don't want to deal with signed/unsigned stuff.
  
  for(int i=0; i<test.width; i++){ //Iterate from left to right on the image
    for(int u=0; u<test.height;u++){ //Iterate from up to down on the image
    
      color thisPixelColor = test.get(i,u); //Get color of current pixel
      
      short average = (short) round((red(thisPixelColor) + green(thisPixelColor) + blue(thisPixelColor)) / 3);
      //Get the average of 3 colors, greyscale.


      pixelsArray[i][u] = average; //Put that average into its spot in the array.
    }
  }
  
  //We now have an array "pixelsArray" with all the pixels in greyscale. Let's iterate on it to do the 2 tasks.
  
  //As we have the array now, we don't need the image, so we can drop it from the memory to free some for the next things.
  test = null;
  //This causes the image to be inaccessible from anywhere, making Java(i.e. Processing) "garbage-collect" it from the memory when it's needed.
  
  
  //Saving it into a table:
  String[] tableStrings = new String[pixelsArray[0].length]; //Create an array of strings - 1 string is 1 line in the table, and also 1 row of pixels
  
  
  for(int i=0; i<pixelsArray[0].length; i++){ //Iterate in the second dimension of the array //i.e. up to down
    tableStrings[i] = ""; //Actually make our current string
    for(int u=0; u<pixelsArray.length; u++){ //Iterate in the first dimension of the array
      tableStrings[i] += pixelsArray[u][i] + "\t";
      //Take current line from our table, and add to it the value of a pixel in respective place.
      // \t is a special "tab" character that makes text editors align strings nicer and more readable.
    }
  }
  
  saveStrings(sketchPath("imageTable.tsv"),tableStrings); //Save table as a bunch of strings.
  //It can both be viewed from usual notepad, and from something like Microsoft Office Excel as a table, as both understand this format nicely.

  //Again, we don't need the strings now, so we are going to drop them.
  tableStrings = null;
  
  //Now, to make a list of values and cells that have it, we can make another string.
  String[] list = new String[256]; //From 0 to 255
  
  for(int i=0; i<list.length; i++){ //Iterate through the empty list
    list[i] = i + "\t"; //Prepend the position to each line with the tab character
  }
  
  for(int i=0; i<pixelsArray.length; i++){ //Iterate in the first dimension of the array
    for(int u=0; u<pixelsArray[0].length; u++){ //Iterate in the second dimension of the array
      list[pixelsArray[i][u]] += "("+i+","+u+"); "; //Puts them in the format where (50,20) means that pixel in place X 50 and Y 20 is of this value
      //I'm not using letters for X position as the image might be wider than latin alphabet. :D
      //However, if you need specifically letters, provided your image aren't as wide as the alphabet, comment the line above by adding // before it, and uncomment these 2 below by removing // before them:
      //You may see some funky coordinates though!
      //list[pixelsArray[i][u]] += (char) ( (int)'A' + i ) //Takes 'A' character, turns it into an "int" number, adds our current horisontal position to it, and then converts the result to a character
      //                            +""+u+"; "; //Adds our vertical position, semicolon and a spacebar
      
      
    }
  }
  
  saveStrings(sketchPath("imageValues.txt"),list); //Save it to the disk.
  
  //Clear it from the memory. (actually, unneeded because of the next thing we are doing)
  list = null;
  
  exit(); //Close the sketch.
  
}

It seems to finish near-instant with a 100 by 100 size image. Not sure how long it will take for bigger images though, but shouldn’t be too long.
Have fun!

2 Likes

Hi Architektor-4 - wow, I’m impressed! Works perfectly! You don’t know how long I have been thinking about how I could solve this :smirk:
I will study the code to learn :smile:
Don’t know but can I do anything for you in return?

No problem!
If you don’t get what is something or how something works, Processing reference can be really handy.
https://processing.org/reference/
Or, right in the code editor, right-click a function and press “Find in reference” to have it instantly open in your browser - available without internet - really handy!

About anything in return, honestly I don’t know myself - I’d feel bad taking anything from someone on the internet as reward for writing a bunch of simple(for me, at least) code… ._.

1 Like

Well then, thanks a lot!

@Astrid – do you mind sharing what you use case is for this kind of pixel analysis? Is it for an art project, or for data analysis or forensics of some kind?

I recently started using JSON objects to store and extract nested objects inside of my Processing projects. I have an example of it with the code available on github.
JSON UI Encapsulation

saving a json object
js1
loading it and displaying it
js2
what the json object looks like
unknown

doesn’t answer your question but I hope it inspires a bit.

1 Like

@jeremydouglass - it is for an art project. Quite simple actually - and still working on it…