Merge commit 'gzv/master'
authorThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Sat, 16 Aug 2008 20:18:58 +0000 (17:18 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Sat, 16 Aug 2008 20:18:58 +0000 (17:18 -0300)
gdk.c [new file with mode: 0644]
movie.c [new file with mode: 0644]
point.h [new file with mode: 0644]
scale.c [new file with mode: 0644]

diff --git a/gdk.c b/gdk.c
new file mode 100644 (file)
index 0000000..d364a27
--- /dev/null
+++ b/gdk.c
@@ -0,0 +1,125 @@
+/*
+ *  Copyright (C) 2008  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "point.h"
+
+struct ctx
+{
+  GtkWidget *draw;
+  GdkPixbuf *picture;
+  GArray *points;
+  int i;
+  gboolean move;
+};
+
+#define FILENAME "/home/cascardo/fotos/debconf.jpg"
+#define WIDTH 800
+#define HEIGHT 600
+
+gboolean
+queue (gpointer data)
+{
+  struct ctx *ctx;
+  ctx = (struct ctx *) data;
+  gtk_widget_queue_draw (GTK_WIDGET (ctx->draw));
+  ctx->move = TRUE;
+  return FALSE;
+}
+
+gboolean
+expose (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+  GdkPixbuf *screen;
+  struct ctx *ctx;
+  Point point;
+  int w, h;
+  ctx = (struct ctx *) data;
+  gdk_drawable_get_size (GDK_DRAWABLE (event->window), &w, &h);
+  if (ctx->move)
+    ctx->i = (ctx->i >= ctx->points->len) ? 0 : ctx->i + 1;
+  point = g_array_index (ctx->points, Point, ctx->i);
+  screen = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+                           event->area.width, event->area.height);
+  gdk_pixbuf_scale (ctx->picture, screen, 0, 0,
+                    event->area.width, event->area.height,
+                   -point.x + w/2 - event->area.x,
+                   -point.y + h/2 - event->area.y,
+                   point.rx, point.ry, GDK_INTERP_BILINEAR);
+  gdk_draw_pixbuf (widget->window, NULL, screen, 0, 0,
+                   event->area.x, event->area.y,
+                  event->area.width, event->area.height,
+                   GDK_RGB_DITHER_NONE, 0, 0);
+  gdk_pixbuf_unref (screen);
+  if (point.name)
+    {
+      if (ctx->move)
+        g_timeout_add (3000, queue, ctx);
+    }
+  else
+    {
+      if (ctx->move)
+        g_timeout_add (10, queue, ctx);
+    }
+  ctx->move = FALSE;
+  return FALSE;
+}
+
+#define FPF 40
+
+int
+main (int argc, char **argv)
+{
+  char *filename;
+  GdkColorspace colorspace;
+  gboolean has_alpha;
+  int bits_per_sample;
+  int width, height;
+  GtkWidget *window;
+  struct ctx ctx;
+  gtk_init (&argc, &argv);
+  if (argc < 2)
+    filename = FILENAME;
+  else
+    filename = argv[1];
+  ctx.points = ReadPoints ("pro-gnu");
+  ctx.points = drop_dup_frames (ctx.points, FPF);
+  rescale_points (ctx.points, get_scales (FPF));
+  ctx.picture = gdk_pixbuf_new_from_file (filename, NULL);
+  ctx.i = ctx.points->len;
+  colorspace = gdk_pixbuf_get_colorspace (ctx.picture);
+  has_alpha = gdk_pixbuf_get_has_alpha (ctx.picture);
+  bits_per_sample = gdk_pixbuf_get_bits_per_sample (ctx.picture);
+  width = WIDTH;
+  height = HEIGHT;
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  g_signal_connect (G_OBJECT (window), "destroy",
+                    G_CALLBACK (gtk_main_quit), NULL);
+  ctx.draw = gtk_drawing_area_new ();
+  gtk_widget_set_size_request (ctx.draw, width, height);
+  gtk_container_add (GTK_CONTAINER (window), ctx.draw);
+  gtk_widget_show_all (window);
+  g_signal_connect (G_OBJECT (ctx.draw), "expose_event",
+                    G_CALLBACK (expose), &ctx);
+  g_timeout_add (10, queue, &ctx);
+  gtk_main ();
+  gdk_pixbuf_unref (ctx.picture);
+  return 0;
+}
diff --git a/movie.c b/movie.c
new file mode 100644 (file)
index 0000000..08531fe
--- /dev/null
+++ b/movie.c
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (C) 2008  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+
+#include "point.h"
+
+#define SWAP(x, y) do { \
+       x ^= y; y ^= x; x ^= y; \
+       } while (0)
+
+void
+InsertLine (GArray *points, Point *src, Point *dst)
+{
+  Point rect;
+  int inc, err, thre, swap;
+  int x1, y1, x2, y2;
+  int x, y;
+  rect.name = NULL;
+  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;
+    }
+  }
+}
+
+GArray *
+ReadPoints (char *filename)
+{
+  GArray *points;
+  FILE *file;
+  char *buffer;
+  char *next;
+  size_t len;
+  ssize_t r;
+  int i = 0;
+  Point last;
+  Point rect;
+  file = fopen (filename, "r");
+  points = g_array_new (FALSE, TRUE, sizeof (Point));
+  buffer = NULL;
+  len = 0;
+  rect.x = rect.y = 0;
+  rect.name = NULL;
+  last = rect;
+  while (!feof (file))
+  {
+    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);
+    while (isspace (*next)) next++;
+    rect.name = g_strdup (next);
+    if (i > 0)
+      InsertLine (points, &last, &rect);
+    g_array_append_val (points, rect);
+    last = rect;
+    i++;
+  }
+  fclose (file);
+  return points;
+}
+
+GArray *
+drop_dup_frames (GArray *points, int n)
+{
+  GArray *frames;
+  Point *point;
+  Point *next;
+  int i;
+  int j;
+  int inc;
+  int thre;
+  int err;
+  inc = n;
+  frames = g_array_new (FALSE, TRUE, sizeof (Point));
+  for (i = 0; i < points->len;)
+    {
+      j = i + 1;
+      point = next = &(g_array_index (points, Point, j));
+      while (next->name == NULL && j < points->len)
+        {
+         j++;
+          next = &(g_array_index (points, Point, j));
+       }
+      thre = j - i;
+      err = 0;
+      g_array_append_val (frames, g_array_index (points, Point, i));
+      for (; i < j; i++)
+        {
+         err += inc;
+         while (err > thre)
+           {
+             err -= thre;
+              g_array_append_val (frames, g_array_index (points, Point, i));
+           }
+       }
+    }
+  return frames;
+}
+
+GArray *
+get_scales (int n)
+{
+  GArray *scales;
+  double scale;
+  double factor;
+  scales = g_array_new (FALSE, TRUE, sizeof (double));
+  factor = pow (4.0, 1.0/((double) n/2));
+  factor = 1.0/factor;
+  for (scale = 4.00; scale > 1.0 && scales->len < n/2; scale *= factor)
+    scales = g_array_append_val (scales, scale);
+  factor = 1.0/factor;
+  for (scale = 1.0; scale < 4.0 && scales->len < n; scale *= factor)
+    scales = g_array_append_val (scales, scale);
+  return scales;
+}
+
+void
+rescale_points (GArray *points, GArray *scales)
+{
+  Point *point;
+  double scale;
+  int i;
+  for (i = 0; i < points->len; i++)
+    {
+      point = &(g_array_index (points, Point, i));
+      scale = g_array_index (scales, double, (i % scales->len));
+      point->rx = scale;
+      point->ry = scale;
+      point->x *= point->rx;
+      point->y *= point->ry;
+    }
+}
diff --git a/point.h b/point.h
new file mode 100644 (file)
index 0000000..24a3f78
--- /dev/null
+++ b/point.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2008  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef POINTS_H
+#define POINTS_H
+
+#include <glib.h>
+
+typedef struct
+{
+  int x, y;
+  double rx, ry;
+  char *name;
+} Point;
+
+GArray * ReadPoints (char *);
+void rescale_points (GArray *, GArray *);
+GArray * drop_dup_frames (GArray *, int);
+GArray *get_scales (int);
+
+#endif
diff --git a/scale.c b/scale.c
new file mode 100644 (file)
index 0000000..7777f42
--- /dev/null
+++ b/scale.c
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (C) 2008  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cairo.h>
+#include <SDL.h>
+#include <SDL_image.h>
+cairo_surface_t *
+CairoFromSDL (SDL_Surface *surface)
+{
+  return cairo_image_surface_create_for_data (surface->pixels,
+                                             CAIRO_FORMAT_ARGB32,
+                                             surface->w, surface->h,
+                                             surface->pitch);
+}
+
+SDL_Surface *
+CairoToSDL (cairo_surface_t *surface)
+{
+  return SDL_CreateRGBSurfaceFrom (cairo_image_surface_get_data (surface),
+                                   cairo_image_surface_get_width (surface),
+                                  cairo_image_surface_get_height (surface),
+                                  32,
+                                  cairo_image_surface_get_stride (surface),
+                                  0x00ff0000, 0x0000ff00, 0x000000ff,
+                                  0xff000000);
+}
+
+SDL_Surface *
+CairoTarget (SDL_Surface *image, double scale)
+{
+  unsigned char *data = NULL;
+  cairo_surface_t *surface = NULL;
+  cairo_t *ctx = NULL;
+  cairo_surface_t *source;
+  SDL_Surface *dest;
+  int w, h;
+  w = image->w * scale;
+  h = image->h * scale;
+  data = malloc (w * h * 4);
+  surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
+                                                w, h, w * 4);
+  ctx = cairo_create (surface);
+  cairo_scale (ctx, scale, scale);
+  source = CairoFromSDL (image);
+  cairo_set_source_surface (ctx, source, 0, 0);
+  cairo_paint (ctx);
+  cairo_surface_destroy (source);
+  dest = CairoToSDL (surface);
+  cairo_surface_destroy (surface);
+  cairo_destroy (ctx);
+  return dest;
+}
+
+SDL_Surface *
+CairoScale (SDL_Surface *image, double scale)
+{
+  SDL_Surface *newfmt;
+  SDL_Surface *slice;
+  SDL_Surface *scaled_image;
+  newfmt = SDL_CreateRGBSurface (SDL_SWSURFACE, 1, 1,
+                                 32,
+                                0x00ff0000,
+                                0x0000ff00,
+                                0x000000ff,
+                                0xff000000);
+  slice = SDL_ConvertSurface (image, newfmt->format, SDL_SWSURFACE);
+  SDL_FreeSurface (newfmt);
+  scaled_image = CairoTarget (slice, scale);
+  SDL_FreeSurface (slice);
+  return scaled_image;
+}