ShiftMatrix, Dreaming Big Video Display

xforce30164:
I'd be great if you could do the switch one so i can get an idea of your way or programming and thinking.

Yeah thats what I decided on so I spent some time reworking it so that it would work either way. I also added a switch so you could just run it onscreen and not actually output the serial, this made testing parts of the code much quicker. I have tried to comment as fully as possible, I have probably gone overboard :D. Let me know what you think. The Arduino part of the code is already up in other posts in this thread.

/*
* ShiftMatrixPWM Serial Video Transmit for Processing
* by Richard Black
* Built-in video library replaced with gsvideo by Andres Colubri
* Get it from: http://gsvideo.sourceforge.net/
*
* Loads a video file and downscales the frames and sends them
* via Serial to an Arduino setup with the ShiftMatrixPWM Library.
* For the Arduino, found at: http://arduino.cc/forum/index.php/topic,66988.0.html
* This displays three images in the window. The original, the down
* scaled and the final output. This code has been setup to work with
* video's in 4:3 ratio but you could adapt it for other ratios.
* It is currently set to output 32 levels of brightness. This can be changed.
*/

import codeanticode.gsvideo.*;
import processing.serial.*;

//SETTINGS START HERE!!!!!!!!!!
//currently I am building a square matrix. I left seperate height and width
//for future possible use.
boolean ColourMatrix = false; // true for colour, false for Mono
boolean OutputEnabled = false; // true for serial out, false no serial out(on screen only)
int mpHigh = 64; //Number of Rows High the Matrix is.
int mpWide = 64; //Number of Columns wide the Matrix is.
int movRate = 40; //Set the number of frames per sec to process
String comPort = "COM5"; //Set what port the Arduino is on
String movFile = "video.mp4"; //set which file to play. This needs to be in the projects data folder
int brightLevel = 32; //This is the number of levels required. On the Arduino this would be 0-31
//using this code bightLevel should be a multiple of 8 so it can be cleanly divided into 256 as further down
//SETTINGS END HERE!!!!!!!!!!!!

Serial matrixPort;
GSMovie theMovie; //Creates the GSvideo Movie object.
PImage smallFrame = new PImage(mpWide, mpHigh);
color pixelclr; //this is for color setup
int pixelbright; //this is for mono color setup
byte [] myFrame;
PFont font;
int divider = 256 / brightLevel; //This allows calculating the brightness levels in the code

void setup() {
 size(1000, 400, P3D);
 if (ColourMatrix==true){
  myFrame = new byte[mpWide*3*mpHigh];
} else {
  myFrame = new byte[mpWide*mpHigh];
}
 matrixPort = new Serial(this, comPort, 250000);// Initialise com port replace with your speed
 frameRate(movRate);//framerate set above in settings
 noStroke();
 background(0);
 theMovie = new GSMovie(this, movFile); //Initialises instance of the movie
 theMovie.loop(); // I have it looping. You can comment this out if you don't want looping
 //theMovie.play(); // Use this to have the movie only play once. No Repeat.
 ellipseMode(CORNER);
 font = loadFont("DejaVuSans-24.vlw"); //Change to whatever font file you have otherwise, comment out
 //comment out the next five lines if there is no font or above is commented out
 textFont(font);
 fill(0, 102, 153);
 text("Original", 15, theMovie.height+20); // Label
 text("Down Scaled", theMovie.width+20, (smallFrame.height*2)+20);// Label
 text("Output", theMovie.width+20, (height/2)-10);// Label
}

// Read new values from movie
void movieEvent(GSMovie m) {
  m.read();// Reads in the new Frame of the movie
  //This next line takes the movie frame and resizes it into a smaller PImage object.
  smallFrame.copy(m, m.width/8, 0, int(m.width-(m.width/4)), m.height, 0, 0, smallFrame.width, smallFrame.height);
  //This also only gets the center part of the video as the ratio is not a perfect
  //square. The left and right edges get trimed. Currently this is set for 4:3 ratio to square (ie the matrix)
}

// Display values from movie
void draw()  {
  image(smallFrame,theMovie.width+10,0,smallFrame.width*2,smallFrame.height*2); //Draws the small Frame
  //image(theMovie,0,0,theMovie.width/2,theMovie.height/2); //Draws the full movie Frame, half size optional
  image(theMovie,0,0);//Draws the full movie Frame
  for (int y = 0; y < smallFrame.height;y++) {
    for (int x = 0; x < smallFrame.width;x++) {
      if (ColourMatrix==false){
        pixelbright = int(brightness(smallFrame.pixels[(y*smallFrame.width)+x])/divider);
        myFrame[(y*smallFrame.width)+x]=byte(pixelbright);
        fill(pixelbright*divider);
      } else {
        pixelclr = smallFrame.pixels[(y*smallFrame.width)+x];
        if (red(pixelclr)/divider < 1) {
          myFrame[(y*smallFrame.width*3)+(x*3)]=byte(0);
        } else {
          myFrame[(y*smallFrame.width*3)+(x*3)]=byte(int(pow(31,(red(pixelclr)/divider)/31)));
        }
        if (green(pixelclr)/divider < 1) {
          myFrame[(y*smallFrame.width*3)+(x*3)+1]=byte(0);
        } else {
          myFrame[(y*smallFrame.width*3)+(x*3)+1]=byte(int(pow(31,(green(pixelclr)/divider)/31)));
        }
        if (blue(pixelclr)/divider < 1) {
          myFrame[(y*smallFrame.width*3)+(x*3)+2]=byte(0);
        } else {
          myFrame[(y*smallFrame.width*3)+(x*3)+2]=byte(int(pow(31,(blue(pixelclr)/divider)/31)));
        }
        fill((red(pixelclr)/divider)*divider,(green(pixelclr)/divider)*divider,(blue(pixelclr)/divider)*divider);
      }
      //The ellipse is for drawing the supposed output using the colour/brightness from the Fill above
      ellipse(x*((width/4)/mpWide)+(theMovie.width+10),(height/2)+(y*((height/2)/mpHigh)),((width/4)/mpWide)-1,((height/2)/mpHigh));
    }
  }
  //println(myFrame); //used to print frame data to the output panel, good for testing
  if (OutputEnabled==true){
    matrixPort.write('~'); // start Character. If using 127 levels you will
    //need to change the start Character to some higher ascii value.
    matrixPort.write(myFrame); // the frame data
  }
}

So next part for me is making it split the output into sections so I can run a modular matrix.
But this does run my 16x16 RGB matrix just as is. Hope this makes sense to people. :slight_smile: