Rotate Your Movie

I have received by e-mail a rotated video in the ‘flv’ format. The video was supposed to be a vertical one, but it turned out to be horizontal, that is ROTATED. So, I wrote a little program to rotate it back using libming.
There are two things to take care of when processing the input FLV:

  • The video stream.
  • The sound stream.

Both can be taken from the FLV file.
The code is written in C++, but can be translated easily into PHP. Following is the code:

#include <iostream>
#include <mingpp.h>

using namespace std;

int main(){
  const char *flvFile ="/path/to/inputVideoFile.flv";

  // Get the video stream from the file. The input file can be in the FLV format.
  SWFVideoStream *stream = new SWFVideoStream(flvFile);

  SWFMovie mov (9);  // Create the movie object.

  // The method 'add' returns a display item.
  // Display items can be rotated, transformed, etc.
  SWFDisplayItem *di=mov.add(stream);  

  // Sound streams are taken from a file object. 
  FILE *soundFD = fopen(flvFile, "rb+");
  SWFSoundStream sound(soundFD);

  // The original dimensions of the video are 426 X 240.
  di->rotate(-90);  // Rotate the item 90 degrees clockwise
  di->move(240, 0);  // The rotation moves point (0,240) to (-240,0).


  mov.setSoundStream(&sound,0);  // Add the sound stream at the beginning
                                 // of the movie.

  // Show the frames one by one.
  int noFrames = stream->getNumFrames();
  for (int i=0; i<noFrames; i++)
      mov.nextFrame();

  mov.setDimension(240, 426); // The new dimensions.
  mov.save("/path/to/outputVideoFile.swf", 9);
  cerr<<"Fin\n";
  return 0;
}

This will create a real vertical movie. Don’t share it on YouTube or anywhere you cannot control your movie dimensions.

Advertisement

HTML5 Canvases & Transforms

Browsers supporting HTML5 allow you to draw on the browser’s screen without preparing an image file before. Drawing on a canvas is done using the wonderful Javascript language. If you want to draw a 2-dimensional image on canvas element ‘cnv’, get the drawing context using:

var ctx = cnv.getContext("2d")

And use that context to draw everything using the standard functions:

moveTo, lineTo, arc, fillRect, etc.

Learn more about drawing here.

You can use the functions to create more complicated shapes easily thanks to transform functions:

Transformations: Linear Algebra Made Easy

The origin(0,0) of the canvas is defined to be the top-left pixel of the canvas element. And the coordinates are given in number of pixels. This can change by using transforms.

The transformation functions are:

  • scale(x,y): this will make every shape x times wider and y time taller.
  • translate(x,y): now coordinate (0,0) will be shifted x units to the right, and y units down.
  • rotate(angle): will rotete the axes by given angle in radians.
  • transform(a,b,c,d,e,f): If you want to use a transformation matrix
  • setTransfrom(a,b,c,d,e,f): reset all transform, and perform transform(a,b,c,d,e,f).

a,b,c,d,e,f are values in the matrix:

Transform Matrix
The values a,b,c,d are used for rotating and scaling. e,f for translating.

Other useful methods of the context are:

  • ctx.save() – to save current transform in a stack (Last In First Out).
  • ctx.restore() – to retrieve the trnasform from the top of the stack.

An Example – The Koch Snowflake

The algorithm for drawing the Koch Snowflake can be found in the post Drawing The Koch Snowflake Fractal With GIMP.

Here’s an example in Javascript:

        function drawSide(ctx, len){
          if (len > 1) {
            var thirdOfLen = len / 3.;

            var rotationAngles = [0, -Math.PI / 3, 2 * Math.PI / 3., -Math.PI / 3];

            rotationAngles.forEach(function(val){
              
              if (val != 0){
                ctx.translate(thirdOfLen, 0);
                ctx.rotate(val);
              }
              ctx.save();
              drawSide(ctx, thirdOfLen);
              ctx.restore();
            });

          } else {
            ctx.moveTo(0,0);
            ctx.lineTo(len,0);
            //ctx.stroke();
          } 
        }

        ctx.translate(startX, startY);
        for (i=0; i<3; i++){
          ctx.save();
          drawSide(ctx, sideLength);
          ctx.restore();
          ctx.translate(sideLength,0);
          ctx.rotate(2*Math.PI/3);
        }
        ctx.stroke();
      }

Warning: using ctx.stroke() after every little line you draw might make your code inefficient, and slow down your browser.

Transformation functions are also part of the Processing language.