Calculates the points before showing the video
authorThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Wed, 13 Aug 2008 22:32:51 +0000 (19:32 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Wed, 13 Aug 2008 22:32:51 +0000 (19:32 -0300)
Instead of calculating each point just before showing a frame, calculate
all of them and store them on an array that we use to get the next
center of image.

movie.c

diff --git a/movie.c b/movie.c
index f5ef008..b2d85e3 100644 (file)
--- a/movie.c
+++ b/movie.c
 
 #define WIDTH 800
 #define HEIGHT 600
+#define FPS (200)
+#define FRAME_INTERVAL (1000/FPS)
+
+#include <glib.h>
 
 #include <stdio.h>
 #include <stdlib.h>
        x ^= y; y ^= x; x ^= y; \
        } while (0)
 
-#define ABS(x) ((x) < 0 ? -(x) : (x))
-
 #define IS_CENTER(cx, cy, x, y) \
        ((x + WIDTH/2 == cx) && (y + HEIGHT/2 == cy))
 
-SDL_Rect *points;
-int psize;
+GArray *points;
+GPtrArray *names;
+
+void
+InsertLine (GArray *points, SDL_Rect *src, SDL_Rect *dst)
+{
+  SDL_Rect rect;
+  int inc, err, thre, swap;
+  int x1, y1, x2, y2;
+  int x, y;
+  rect.w = WIDTH;
+  rect.h = HEIGHT;
+  err = 0;
+  swap = 0;
+  x1 = src->x;
+  y1 = src->y;
+  x2 = dst->x;
+  y2 = dst->y;
+  inc = y2 - y1;
+  thre = x2 - x1;
+  if (ABS (inc) > ABS (thre))
+  {
+    SWAP (inc, thre);
+    SWAP (x1, y1);
+    SWAP (x2, y2);
+    swap = 1;
+  }
+  for (y = y1, x = x1; (x2 < x1) ? (x >= x2) : (x <= x2); (x2 < x1) ? x-- : x++)
+  {
+    rect.x = (swap ? y : x);
+    rect.y = (swap ? x : y);
+    g_array_append_val (points, rect);
+    err += ABS (inc);
+    if (err >= ABS (thre))
+    {
+      err -= ABS (thre);
+      y += (inc < 0) ? -1 : 1;
+    }
+  }
+}
 
 void
 ReadPoints (char *filename)
@@ -43,104 +83,93 @@ ReadPoints (char *filename)
   char *buffer;
   char *next;
   size_t len;
-  int i;
+  ssize_t r;
+  int i = 0;
+  SDL_Rect last;
+  SDL_Rect rect;
   file = fopen (filename, "r");
-  fscanf (file, "%d\n", &psize);
-  points = malloc (sizeof (SDL_Rect) * psize);
-  if (points == NULL)
-    abort ();
+  points = g_array_new (FALSE, TRUE, sizeof (SDL_Rect));
+  names = g_ptr_array_new ();
   buffer = NULL;
   len = 0;
-  for (i = 0; i < psize; i++)
+  rect.x = rect.y = rect.w = rect.h = 0;
+  last = rect;
+  while (!feof (file))
   {
-    getline (&buffer, &len, file);
-    points[i].x = strtol (buffer, &next, 0);
-    points[i].y = strtol (next+1, NULL, 0);
+    r = getline (&buffer, &len, file);
+    buffer[r - 1] = '\0';
+    rect.x = strtol (buffer, &next, 0);
+    rect.y = strtol (next+1, &next, 0);
+    strtol (next, &next, 0);
+    if (i > 0)
+      InsertLine (points, &last, &rect);
+    while (isspace (*next)) next++;
+    g_ptr_array_add (names, strdup (next));
+    last = rect;
+    i++;
   }
   fclose (file);
 }
 
-SDL_Rect *
-GetNextPoint (void)
-{
-  static SDL_Rect rect = {0, 0, WIDTH, HEIGHT};
-  static int cur = -1;
-  static int inc, err, thre, swap;
-  static int x1, y1, x2, y2;
-  static int x, y;
-  int next;
-  next = (cur + 1) % psize;
-  if ((points[next].x == rect.x && points[next].y == rect.y) || cur == -1)
-  {
-    cur = next;
-    next = (cur + 1) % psize;
-    err = 0;
-    swap = 0;
-    x1 = points[cur].x;
-    y1 = points[cur].y;
-    x2 = points[next].x;
-    y2 = points[next].y;
-    inc = y2 - y1;
-    thre = x2 - x1;
-    if (ABS (inc) > ABS (thre))
-    {
-      SWAP (inc, thre);
-      SWAP (x1, y1);
-      SWAP (x2, y2);
-      swap = 1;
-    }
-    x = x1;
-    y = y1;
-  }
-  rect.x = (swap ? y : x);
-  rect.y = (swap ? x : y);
-  (x2 < x1) ? x-- : x++;
-  err += ABS (inc);
-  if (err >= ABS (thre))
-  {
-    err -= ABS (thre);
-    y += (inc < 0) ? -1 : 1;
-  }
-  return &rect;
-}
-
 void
-ShowPoint (SDL_Surface *screen, SDL_Surface *image, SDL_Rect *rect)
+ShowPoint (SDL_Surface *screen, SDL_Surface *image, SDL_Rect center, double scale)
 {
-  SDL_BlitSurface (image, rect, screen, NULL);
+  center.x = (center.x - WIDTH/2) * scale;
+  center.y = (center.y - HEIGHT/2) * scale;
+  center.w = WIDTH;
+  center.h = HEIGHT;
+  SDL_BlitSurface (image, &center, screen, NULL);
   SDL_UpdateRect (screen, 0, 0, 0, 0);
 }
 
-Uint32
-ShowNext (Uint32 interval, void *data)
-{
-  SDL_UserEvent event;
-  event.type = SDL_USEREVENT;
-  event.code = 0;
-  SDL_PushEvent ((SDL_Event *) &event);
-  return 33;
-}
-
 int
 main (int argc, char **argv)
 {
   SDL_Surface *screen;
   SDL_Surface *image;
+  SDL_Rect rect;
   SDL_Event event;
+  Uint32 last, now, deslast, start;
+  int i, des, desl;
   ReadPoints ("pro-gnu");
   SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER);
   screen = SDL_SetVideoMode (800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
   image = IMG_Load ("/home/cascardo/fotos/debconf.jpg");
-  SDL_AddTimer (0, ShowNext, NULL);
-  while (SDL_WaitEvent (&event))
+  start = deslast = last = SDL_GetTicks ();
+  desl = des = i = 0;
+  while (1)
   {
-    if (event.type == SDL_KEYDOWN)
-      break;
-    else if (event.type == SDL_USEREVENT)
-      ShowPoint (screen, image, GetNextPoint ());
+    if (SDL_PollEvent (&event))
+    {
+      if (event.type == SDL_KEYDOWN)
+        break;
+    }
+    now = SDL_GetTicks ();
+    /* skip */
+    if (now > deslast + 1000)
+    {
+      printf ("%f %f\n", (double) (now - start) / (double) des, (double) (now - deslast) / (double) (des - desl));
+      desl = des;
+      deslast = now;
+    }
+    while (now > last + FRAME_INTERVAL)
+    {
+      last += FRAME_INTERVAL;
+      i++;
+    }
+    if (i > points->len)
+      i = 0;
+    rect = g_array_index (points, SDL_Rect, i);
+    ShowPoint (screen, image, rect, 1.0);
+    SDL_Delay (FRAME_INTERVAL - (now - last));
+    i++;
+    des++;
   }
   SDL_FreeSurface (image);
   SDL_Quit ();
-  free (points);
+  g_array_free (points, TRUE);
+  for (i = 0; i < names->len; i++)
+    free (g_ptr_array_index (names, i));
+  g_ptr_array_free (names, TRUE);
   return 0;
 }