Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(958)

Unified Diff: src/ply-image.c

Issue 5819001: Add frame-by-frame animation. (Closed) Base URL: http://git.chromium.org/git/ply-image.git@master
Patch Set: Fix units in comment. Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ply-frame-buffer.c ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ply-image.c
diff --git a/src/ply-image.c b/src/ply-image.c
index a9375ab9f97111794bf2df87ee1591b4a273be3c..58e1daea3d5050723e5024557fb555cbb1f46d1f 100644
--- a/src/ply-image.c
+++ b/src/ply-image.c
@@ -42,6 +42,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
#include <math.h>
@@ -51,6 +52,8 @@
#include "ply-utils.h"
+#define BILLION (1000 * 1000 * 1000)
+
typedef union
{
@@ -432,6 +435,21 @@ ply_image_rotate (ply_image_t *image,
return new_image;
}
+ply_image_t *
+ply_image_from_file(const char *path)
+{
+ int exit_code;
+ ply_image_t *image = ply_image_new (path);
+
+ if (!ply_image_load (image))
+ {
+ exit_code = errno;
+ perror (path);
+ exit (exit_code);
+ }
+ return image;
+}
+
#include "ply-frame-buffer.h"
#include <math.h>
@@ -443,38 +461,102 @@ ply_image_rotate (ply_image_t *image,
#include <linux/kd.h>
+const int frame_rate = 20; /* Animation frames per second */
+int bad_clock = 0; /* Set to 1 if the clock ever returns an error */
+
+void
+ply_frame_buffer_show_file_at_xy(ply_frame_buffer_t *buffer, const char *path,
+ long x, long y)
+{
+ ply_image_t *image;
+ uint32_t *data;
+ long width, height;
+ ply_frame_buffer_area_t area;
+
+ image = ply_image_from_file (path);
+
+ data = ply_image_get_data (image);
+ width = ply_image_get_width (image);
+ height = ply_image_get_height (image);
+
+ ply_frame_buffer_get_size (buffer, &area);
+ area.x = (area.width / 2) - (width / 2); // + x;
+ area.y = (area.height / 2) - (height / 2); // + y;
+ area.width = width;
+ area.height = height;
+
+ ply_frame_buffer_fill (buffer, &area, x, y, data);
+ ply_image_free (image);
+}
+
+/*
+ * Compute the difference in nanoseconds between two timevals. Return 0 if the
+ * clock is not reliable.
+ */
+int64_t difference_nsec(struct timespec x, struct timespec y)
+{
+ int64_t z;
+
+ if (bad_clock)
+ {
+ return 0;
+ }
+
+ z = x.tv_sec - y.tv_sec;
+ z *= BILLION;
+ z += x.tv_nsec - y.tv_nsec;
+ return z;
+}
+
+
+void gettime_check(struct timespec *ts)
+{
+ int r = clock_gettime(CLOCK_MONOTONIC, ts);
+ if (r)
+ {
+ bad_clock = 1;
+ }
+}
+
+
+int usage(void)
+{
+ fprintf(stderr,
+ "usage: ply-image --clear\n"
+ " ply-image <background> [<x-offset> <y-offset> "
+ "<frame-1> ... <frame-n>]\n");
+ exit(1);
+}
+
int
main (int argc,
char **argv)
{
- ply_image_t *image = NULL;
+ int exit_code = 0;
+ int clear = 0;
+ int help = 0;
ply_frame_buffer_t *buffer;
- int exit_code;
- ply_frame_buffer_area_t area;
- uint32_t *data;
- long width, height;
-
- exit_code = 0;
+ int i;
+ int xoff, yoff;
+ char *endptr;
// hide_cursor ();
- if (argc != 2 || strcasecmp(argv[1], "-h") == 0 || strcasecmp(argv[1], "--help") == 0)
+ /*
+ * Ad-hoc arg parsing, to keep the program small.
+ */
+
+ if (argc > 1)
{
- perror ("usage: ply-image [--clear | <pngImageFile>]");
- return 1;
+ clear = strcasecmp (argv[1], "--clear") == 0;
+ help = strcasecmp (argv[1], "--help") == 0 ||
+ strcasecmp (argv[1], "-h") == 0;
}
- if (strcasecmp(argv[1], "--clear") != 0)
+ if (help || argc == 1 || argc == 3 || argc == 4)
{
- image = ply_image_new (argv[1]);
-
- if (!ply_image_load (image))
- {
- exit_code = errno;
- perror ("could not load image");
- return exit_code;
- }
+ usage();
}
buffer = ply_frame_buffer_new (NULL);
@@ -486,28 +568,75 @@ main (int argc,
return exit_code;
}
- if (image == NULL)
+ if (clear)
{
ply_frame_buffer_clear (buffer);
}
else
{
- data = ply_image_get_data (image);
- width = ply_image_get_width (image);
- height = ply_image_get_height (image);
-
- ply_frame_buffer_get_size (buffer, &area);
- area.x = (area.width / 2) - (width / 2);
- area.y = (area.height / 2) - (height / 2);
- area.width = width;
- area.height = height;
-
- ply_frame_buffer_fill (buffer, &area, 0, 0, data);
- ply_image_free (image);
+ /*
+ * Display main image.
+ */
+ ply_frame_buffer_show_file_at_xy (buffer, argv[1], 0, 0);
+
+ if (argc >= 4)
+ {
+ /*
+ * Animate frames.
+ */
+ struct timespec then, now;
+ int64_t error_nsec;
+ int64_t interval_nsec;
+
+ xoff = strtol (argv[2], &endptr, 10);
+ if (endptr == argv[2] || *endptr != '\0')
+ {
+ usage ();
+ }
+ yoff = strtol (argv[3], &endptr, 10);
+ if (endptr == argv[3] || *endptr != '\0')
+ {
+ usage ();
+ }
+
+ /*
+ * Begin animation.
+ *
+ * The first time around, we don't know how long it takes to draw a
+ * frame, so we assume it's instantaneous. After that, we assume
+ * that the drawing time for the previous cycle is a good estimate
+ * for the next cycle. Errors may be introduced by different frame
+ * size and complexity (PNG decoding).
+ */
+ error_nsec = 0;
+ interval_nsec = BILLION / frame_rate;
+ gettime_check (&now);
+
+ for (i = 4; i < argc; i++)
+ {
+ /*
+ * Before displaying the next frame, sleep for the inter-frame
+ * interval, adjusted by the error in the previous cycle.
+ * Positive error means the last cycle took longer than desired.
+ */
+ if (interval_nsec - error_nsec > 0)
+ {
+ struct timespec req;
+ req.tv_sec = (interval_nsec - error_nsec) / BILLION;
+ req.tv_nsec = (interval_nsec - error_nsec) % BILLION;
+ nanosleep (&req, NULL);
+ }
+ ply_frame_buffer_show_file_at_xy (buffer, argv[i], xoff, yoff);
+ then = now;
+ gettime_check (&now);
+ error_nsec = difference_nsec (now, then) - interval_nsec;
+ }
+ }
}
- ply_frame_buffer_close (buffer);
- ply_frame_buffer_free (buffer);
+ // Skip these to save time.
+ // ply_frame_buffer_close (buffer);
+ // ply_frame_buffer_free (buffer);
return exit_code;
}
« no previous file with comments | « src/ply-frame-buffer.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698