Monday, December 16, 2013

Video panning across your family tree chart (.jpg to .mp4)

Problem statement:
I have a large panoramic JPEG file (e.g. 8038 x 1145 or more) . How do I generate a video (.avi or preferably .mp4) to zoom in on a particular sub-section of the image (say 1920 x 1080 - size of my Full HD television screen) and slowly pan across the whole image?

I have been using MyHeritage's Family Tree Builder since 2008. I have their premium plus membership. Currently I have 401 individuals cataloged in my family tree.
Beginning last year, we starting organizing an annual family get together of the descendants of Mr Mool Chand Kalra (My mother's father's father) . Genealogically, this basically comprised of 1/4 branch of my extended family, I have 3 other such branches each comprising of the siblings (and their descendants) of my other 3 grandparents. But this particular branch has more individuals (Mr. Mool Chand Kalra had a big family, and his children had equally big ones as well) than the other 3 branches. It is also the best catalog in my family tree.
Last year, during the get together, we had a short presentation where in displayed sub branches of this big branch and showed how the members of the audience were related to each other. MyHeritage's Family Tree Builder allows you to generate awesome family charts. I used this feature to generate family charts for each sub-branch of my family tree. The charting feature allows you to configure lots of features of the chart : ancestors/descendants of a person, horizontal/vertical, hide/display facts, select font sizes, export type as PDF/JPG.

This year, we have decides we aggregated photos from all the members and decided to put it on a pendrive and let a big screen LCD TV loop through the slideshow. The LCD TV will be kept in one corner of the room and people could come take a look at their convenience - forcing them to sit through a long presentation of photos would keep them from catching up with each other and might be counter-productive.

I decided that as a refreshed, I would like to throw in a jpg of the chart as well, but when I generated the chart for my great grandfather, it was huge and when displayed on a screen limited to 1920 x 1080 pixels, you could hardly make out anything. I decided to generate a video panning across the whole family chart 1920x1080 pixels at a time. 

Here is what my original looked like (I have set the font size of names set to 1, essentially hiding them to protect the privacy of my relatives) :

The descendants of Mr. Mool Chand Kalra - 8038 x 1145 pixels
Click to view the original.
Here is the Full HD (1920 x 1080) .mp4 video panning across the image
Full HD video panning across the image.
Click to view in Full HD at Youtube

I didn't want to spend a single penny to create the above video and hence choose the freeware path. And to save time, I decided to use tools I was familiar with. Here is how I got it done:
  1. Export the image as JPEG from MyHeritage's Family Tree Builder.
  2. Download Processing 2 from www.processing.org and install it
  3. Execute the following sketch. Make sure your original JPEG is in the same folder as the sketch. The name of the folder in which you place the sketch (.pde file) and the name of the sketch must be the same. Edit the name of the JPEG file in the sketch to match the name of your JPEG file. You may adjust the panning parameters - frames per second and amount of pixels to shift by each time. The panning is preset to move left from center of the image towards left and then back on to the other side of the image. The code displays a FullHD worth region of the image each draw() loop and saves it to disk. At the end you will get a folder full of frames like so:
    JPEG frames
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    import processing.video.*; 
    
    int pan_step_px=2;
    int frame_speed=30;
    int screensize_rows=1080;
    int screensize_cols=1920;
    
    
    PImage img;
    int xoffset;
    int yoffset;
    
    int pan_y_ctr;
    
    int current_direction;
    
    boolean sketchFullScreen() {
      return true;
    }
    
    void setup() {
      smooth();
      frameRate(frame_speed);
      size(screensize_cols, screensize_rows);
      img = loadImage("mool.jpg");
      xoffset=img.width/2;
      yoffset=0;
      current_direction=LEFT;
      pan_y_ctr=0;
    }
    
    void draw() {
      image(img.get(xoffset, yoffset, 1920, 1080), 0, 0);
    
      if (current_direction == LEFT) {
        xoffset = xoffset-pan_step_px;
        if (xoffset <0) {
          xoffset = 0;
          pan_y_ctr=0;
          current_direction = DOWN;
        }
      } 
      else if (current_direction == DOWN) {
        if (xoffset == 0) {
          yoffset = yoffset+pan_step_px;
          pan_y_ctr += pan_step_px;
          if (yoffset+screensize_rows >= img.height) {
            yoffset = img.height - screensize_rows;
            pan_y_ctr = 0;
            current_direction = RIGHT;
          }
          if (pan_y_ctr >= screensize_rows) {
            pan_y_ctr = 0;
            current_direction = RIGHT;
          }
        } 
        else {
          yoffset = yoffset+pan_step_px;
          pan_y_ctr += pan_step_px;
          if (yoffset+screensize_rows >= img.height) {
            yoffset = img.height - screensize_rows;
            pan_y_ctr = 0;
            //Stop
            noLoop();
          }
          if (pan_y_ctr >= screensize_rows) {
            pan_y_ctr = 0;
            current_direction = LEFT;
          }
        }
      }
      else if (current_direction == RIGHT) {
        xoffset = xoffset+pan_step_px;
        if (xoffset+screensize_cols>img.width) {
          xoffset = img.width-screensize_cols;
          pan_y_ctr=0;
          current_direction = DOWN;
        }
      }
      saveFrame("line-######.jpg");
    }
    
  4. Copy the frame JPEGs to a Linux box. I used Ubuntu 13.10 32 bit running on a VirtualBox VM.
    Making the JPEGs available inside of a Linux VM
  5. Use avconv to assemble the JPEGs (line-xxxxxx.jpg) into a .mp4 file. Use the following command:
    avconv -r 30 -i line-%06d.jpg -qscale 2 -r 30 out.mp4
    Done creating .mp4 using avconv
    -r option is used twice to indicate the input and output frame rate. I have set it to 30 fps because that is what I specified in the Processing sketch. -qscale option specifies the quality of the video between 1 and 31, 1 being the best, 31 being the worst.

    - avconv can be run on Windows too: http://libav.org/download.html
    - Processing 2 is available for Linux too.
    - MyHeritage's Family Tree Builder works only on Windows

3 comments:

David New said...

Hello, my grandfather was called Narain Dass Kalra. His father was Behari Lal Kalra whose father was Mool Chand Kalra who was married to Bhandi Bai Kalra. I wonder if we are related.

David New said...

My husband is David New. He is an electronic engineer. He's much better with computers etc than I am. Kind regards to you all.

Todd Beach said...

I have pondered the same problem as you have. I have a very large ancestry.com tree of all of my friends and co-workers. I wanted to show that the world is a small place actually and that many local people are related to each other. I am in the process of creating a program where you load in the large image file and you click on the people you want to highlight on the overall path. You will also be able to zoom in to the people as well if you want. I am using Microsoft Movie Maker to create the video. We may be one of few people on the planet to consider this problem.

Todd Beach
beach20201@yahoo.com
Alabama, USA

Post a Comment