OLD | NEW |
---|---|
1 /* ply-image.c - png file loader | 1 /* ply-image.c - png file loader |
2 * | 2 * |
3 * Copyright (C) 2006, 2007 Red Hat, Inc. | 3 * Copyright (C) 2006, 2007 Red Hat, Inc. |
4 * Copyright (C) 2003 University of Southern California | 4 * Copyright (C) 2003 University of Southern California |
5 * | 5 * |
6 * This program is free software; you can redistribute it and/or modify | 6 * This program is free software; you can redistribute it and/or modify |
7 * it under the terms of the GNU General Public License as published by | 7 * it under the terms of the GNU General Public License as published by |
8 * the Free Software Foundation; either version 2, or (at your option) | 8 * the Free Software Foundation; either version 2, or (at your option) |
9 * any later version. | 9 * any later version. |
10 * | 10 * |
(...skipping 24 matching lines...) Expand all Loading... | |
35 #include <errno.h> | 35 #include <errno.h> |
36 #include <fcntl.h> | 36 #include <fcntl.h> |
37 #include <string.h> | 37 #include <string.h> |
38 #include <stdbool.h> | 38 #include <stdbool.h> |
39 #include <stdint.h> | 39 #include <stdint.h> |
40 #include <stdlib.h> | 40 #include <stdlib.h> |
41 #include <sys/ioctl.h> | 41 #include <sys/ioctl.h> |
42 #include <sys/mman.h> | 42 #include <sys/mman.h> |
43 #include <sys/stat.h> | 43 #include <sys/stat.h> |
44 #include <sys/types.h> | 44 #include <sys/types.h> |
45 #include <time.h> | |
45 #include <unistd.h> | 46 #include <unistd.h> |
46 #include <math.h> | 47 #include <math.h> |
47 | 48 |
48 #include <png.h> | 49 #include <png.h> |
49 | 50 |
50 #include <linux/fb.h> | 51 #include <linux/fb.h> |
51 | 52 |
52 #include "ply-utils.h" | 53 #include "ply-utils.h" |
53 | 54 |
55 #define BILLION (1000 * 1000 * 1000) | |
56 | |
54 | 57 |
55 typedef union | 58 typedef union |
56 { | 59 { |
57 uint32_t *as_pixels; | 60 uint32_t *as_pixels; |
58 png_byte *as_png_bytes; | 61 png_byte *as_png_bytes; |
59 char *address; | 62 char *address; |
60 } ply_image_layout_t; | 63 } ply_image_layout_t; |
61 | 64 |
62 struct _ply_image | 65 struct _ply_image |
63 { | 66 { |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 theta -= theta_offset; | 428 theta -= theta_offset; |
426 old_x = center_x + d * cos (theta); | 429 old_x = center_x + d * cos (theta); |
427 old_y = center_y + d * sin (theta); | 430 old_y = center_y + d * sin (theta); |
428 new_image->layout.as_pixels[x + y * width] = | 431 new_image->layout.as_pixels[x + y * width] = |
429 ply_image_interpolate (image, width, height, old_x, old_y); | 432 ply_image_interpolate (image, width, height, old_x, old_y); |
430 } | 433 } |
431 } | 434 } |
432 return new_image; | 435 return new_image; |
433 } | 436 } |
434 | 437 |
438 ply_image_t * | |
439 ply_image_from_file(const char *path) | |
440 { | |
441 int exit_code; | |
442 ply_image_t *image = ply_image_new (path); | |
443 | |
444 if (!ply_image_load (image)) | |
445 { | |
446 exit_code = errno; | |
447 perror (path); | |
448 exit (exit_code); | |
449 } | |
450 return image; | |
451 } | |
452 | |
435 #include "ply-frame-buffer.h" | 453 #include "ply-frame-buffer.h" |
436 | 454 |
437 #include <math.h> | 455 #include <math.h> |
438 #include <signal.h> | 456 #include <signal.h> |
439 #include <stdio.h> | 457 #include <stdio.h> |
440 #include <sys/ioctl.h> | 458 #include <sys/ioctl.h> |
441 #include <sys/time.h> | 459 #include <sys/time.h> |
442 #include <values.h> | 460 #include <values.h> |
443 | 461 |
444 #include <linux/kd.h> | 462 #include <linux/kd.h> |
445 | 463 |
464 const int frame_rate = 20; /* Animation frames per second */ | |
465 int bad_clock = 0; /* Set to 1 if the clock ever returns an error */ | |
466 | |
467 void | |
468 ply_frame_buffer_show_file_at_xy(ply_frame_buffer_t *buffer, const char *path, | |
469 long x, long y) | |
470 { | |
471 ply_image_t *image; | |
472 uint32_t *data; | |
473 long width, height; | |
474 ply_frame_buffer_area_t area; | |
475 | |
476 image = ply_image_from_file (path); | |
477 | |
478 data = ply_image_get_data (image); | |
479 width = ply_image_get_width (image); | |
480 height = ply_image_get_height (image); | |
481 | |
482 ply_frame_buffer_get_size (buffer, &area); | |
483 area.x = (area.width / 2) - (width / 2); // + x; | |
484 area.y = (area.height / 2) - (height / 2); // + y; | |
485 area.width = width; | |
486 area.height = height; | |
487 | |
488 ply_frame_buffer_fill (buffer, &area, x, y, data); | |
489 ply_image_free (image); | |
490 } | |
491 | |
492 /* | |
493 * Compute the difference in microseconds between two timevals. Return 0 if | |
494 * the clock is not reliable. | |
495 */ | |
496 int64_t difference_nsec(struct timespec x, struct timespec y) | |
497 { | |
498 int64_t z; | |
499 | |
500 if (bad_clock) | |
501 { | |
502 return 0; | |
503 } | |
504 | |
505 z = x.tv_sec - y.tv_sec; | |
506 z *= BILLION; | |
507 z += x.tv_nsec - y.tv_nsec; | |
508 return z; | |
509 } | |
510 | |
511 | |
512 void gettime_check(struct timespec *ts) | |
513 { | |
514 int r = clock_gettime(CLOCK_MONOTONIC, ts); | |
515 if (r) | |
516 { | |
517 bad_clock = 1; | |
518 } | |
519 } | |
520 | |
521 | |
522 int usage(void) | |
523 { | |
524 fprintf(stderr, | |
525 "usage: ply-image --clear\n" | |
526 " ply-image <background> [<x-offset> <y-offset> " | |
527 "<frame-1> ... <frame-n>]\n"); | |
528 exit(1); | |
529 } | |
530 | |
446 | 531 |
447 int | 532 int |
448 main (int argc, | 533 main (int argc, |
449 char **argv) | 534 char **argv) |
450 { | 535 { |
451 ply_image_t *image = NULL; | 536 int exit_code = 0; |
537 int clear = 0; | |
538 int help = 0; | |
452 ply_frame_buffer_t *buffer; | 539 ply_frame_buffer_t *buffer; |
453 int exit_code; | 540 int i; |
454 ply_frame_buffer_area_t area; | 541 int xoff, yoff; |
455 uint32_t *data; | 542 char *endptr; |
456 long width, height; | |
457 | |
458 exit_code = 0; | |
459 | 543 |
460 // hide_cursor (); | 544 // hide_cursor (); |
461 | 545 |
462 if (argc != 2 || strcasecmp(argv[1], "-h") == 0 || strcasecmp(argv[1], "--help ") == 0) | 546 /* |
547 * Ad-hoc arg parsing, to keep the program small. | |
548 */ | |
549 | |
550 if (argc > 1) | |
463 { | 551 { |
464 perror ("usage: ply-image [--clear | <pngImageFile>]"); | 552 clear = strcasecmp (argv[1], "--clear") == 0; |
465 return 1; | 553 help = strcasecmp (argv[1], "--help") == 0 || |
554 strcasecmp (argv[1], "-h") == 0; | |
466 } | 555 } |
467 | 556 |
468 if (strcasecmp(argv[1], "--clear") != 0) | 557 if (help || argc == 1 || argc == 3 || argc == 4) |
469 { | 558 { |
470 image = ply_image_new (argv[1]); | 559 usage(); |
471 | |
472 if (!ply_image_load (image)) | |
473 { | |
474 exit_code = errno; | |
475 perror ("could not load image"); | |
476 return exit_code; | |
477 } | |
478 } | 560 } |
479 | 561 |
480 buffer = ply_frame_buffer_new (NULL); | 562 buffer = ply_frame_buffer_new (NULL); |
481 | 563 |
482 if (!ply_frame_buffer_open (buffer)) | 564 if (!ply_frame_buffer_open (buffer)) |
483 { | 565 { |
484 exit_code = errno; | 566 exit_code = errno; |
485 perror ("could not open framebuffer"); | 567 perror ("could not open framebuffer"); |
486 return exit_code; | 568 return exit_code; |
487 } | 569 } |
488 | 570 |
489 if (image == NULL) | 571 if (clear) |
490 { | 572 { |
491 ply_frame_buffer_clear (buffer); | 573 ply_frame_buffer_clear (buffer); |
492 } | 574 } |
493 else | 575 else |
494 { | 576 { |
495 data = ply_image_get_data (image); | 577 /* |
496 width = ply_image_get_width (image); | 578 * Display main image. |
497 height = ply_image_get_height (image); | 579 */ |
580 ply_frame_buffer_show_file_at_xy (buffer, argv[1], 0, 0); | |
498 | 581 |
499 ply_frame_buffer_get_size (buffer, &area); | 582 if (argc >= 4) |
500 area.x = (area.width / 2) - (width / 2); | 583 { |
501 area.y = (area.height / 2) - (height / 2); | 584 /* |
502 area.width = width; | 585 * Animate frames. |
503 area.height = height; | 586 */ |
587 struct timespec then, now; | |
588 int64_t error_nsec; | |
589 int64_t interval_nsec; | |
504 | 590 |
505 ply_frame_buffer_fill (buffer, &area, 0, 0, data); | 591 xoff = strtol (argv[2], &endptr, 10); |
506 ply_image_free (image); | 592 if (endptr == argv[2] || *endptr != '\0') |
593 { | |
594 usage (); | |
595 } | |
596 yoff = strtol (argv[3], &endptr, 10); | |
597 if (endptr == argv[3] || *endptr != '\0') | |
598 { | |
599 usage (); | |
600 } | |
601 | |
602 error_nsec = 0; | |
603 interval_nsec = BILLION / frame_rate; | |
604 gettime_check (&now); | |
605 | |
606 for (i = 4; i < argc; i++) | |
607 { | |
608 struct timespec req; | |
609 /* | |
610 * Before displaying the next frame, sleep for the inter-frame | |
611 * interval, adjusted by the error in the previous cycle. | |
612 * Positive error means the last cycle took longer than desired. | |
613 */ | |
614 req.tv_sec = (interval_nsec - error_nsec) / BILLION; | |
615 req.tv_nsec = (interval_nsec - error_nsec) % BILLION; | |
616 if (req.tv_nsec > 0) | |
Daniel Erat
2010/12/14 19:11:02
this is wrong if e.g. tv_sec is 1 and tv_nsec is 0
| |
617 { | |
618 nanosleep (&req, NULL); | |
619 } | |
620 ply_frame_buffer_show_file_at_xy (buffer, argv[i], xoff, yoff); | |
621 then = now; | |
622 gettime_check (&now); | |
623 error_nsec = difference_nsec (now, then) - interval_nsec; | |
Daniel Erat
2010/12/14 19:11:02
i'm not sure i understand this. say that 'frame_r
| |
624 } | |
625 } | |
507 } | 626 } |
508 | 627 |
509 ply_frame_buffer_close (buffer); | 628 // Skip these to save time. |
510 ply_frame_buffer_free (buffer); | 629 // ply_frame_buffer_close (buffer); |
630 // ply_frame_buffer_free (buffer); | |
511 | 631 |
512 return exit_code; | 632 return exit_code; |
513 } | 633 } |
OLD | NEW |