add screenshot command fbgrab
 add topic 'flickernoise'

TODO:
 * direct read fb memory
 * get more info by using ioctl

---
 src/main.c     |    2 +-
 src/shellext.c |  181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/shellext.h |    1 +
 3 files changed, 182 insertions(+), 2 deletions(-)

diff --git a/src/main.c b/src/main.c
index 6f9e6bc..9dd4ae0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -238,7 +238,7 @@ rtems_telnetd_config_table rtems_telnetd_config = {
 #define CONFIGURE_SHELL_COMMANDS_INIT
 #define CONFIGURE_SHELL_COMMANDS_ALL
 #define CONFIGURE_SHELL_COMMANDS_ALL_NETWORKING
-#define CONFIGURE_SHELL_USER_COMMANDS &shell_usercmd
+#define CONFIGURE_SHELL_USER_COMMANDS &shell_usercmd, &framebuffer_grab
 #include <rtems/shellconfig.h>
 
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
diff --git a/src/shellext.c b/src/shellext.c
index 863b359..3ec9dd1 100644
--- a/src/shellext.c
+++ b/src/shellext.c
@@ -24,6 +24,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <png.h>
 
 #include "shellext.h"
 
@@ -81,8 +83,185 @@ int main_erase(int argc, char **argv)
 rtems_shell_cmd_t shell_usercmd = {
        "erase",                        /* name */
        "erase device",                 /* usage */
-       "flash",                        /* topic */
+       "flickernoise",                 /* topic */
        main_erase,                     /* command */
        NULL,                           /* alias */
        NULL                            /* next */
 };
+
+static int write_PNG(unsigned char *outbuffer, char *filename,
+                    int width, int height, int interlace)
+{
+       int i;
+       int bit_depth = 0, color_type;
+       png_bytep row_pointers[height];
+       png_structp png_ptr;
+       png_infop info_ptr;
+       FILE *outfile;
+
+       for (i=0; i<height; i++)
+               row_pointers[i] = outbuffer + i * 4 * width;
+
+       outfile = fopen(filename, "w");
+       if (outfile == NULL) {
+               perror("Error: Couldn't fopen");
+               return -1;
+       }
+
+       png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, 
NULL);
+
+       if (!png_ptr) {
+               fprintf(stderr, "Error: Couldn't create PNG write struct");
+               return -1;
+       }
+
+       info_ptr = png_create_info_struct(png_ptr);
+       if (!info_ptr) {
+               png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
+               fprintf(stderr, "Error: Couldn't create PNG info struct");
+               return -1;
+       }
+
+       png_init_io(png_ptr, outfile);
+
+       png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+
+       bit_depth = 8;
+       color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+       png_set_invert_alpha(png_ptr);
+       png_set_bgr(png_ptr);
+
+       png_set_IHDR(png_ptr, info_ptr, width, height,
+                    bit_depth, color_type, interlace,
+                    PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+       png_write_info(png_ptr, info_ptr);
+
+       printf("Now writing PNG file...\n");
+
+       png_write_image(png_ptr, row_pointers);
+
+       png_write_end(png_ptr, info_ptr);
+       /* puh, done, now freeing memory... */
+       png_destroy_write_struct(&png_ptr, &info_ptr);
+
+       if (outfile != NULL)
+               fclose(outfile);
+
+       return 0;
+}
+
+static void convert565to32(int width, int height,
+                          unsigned char *inbuffer,
+                          unsigned char *outbuffer)
+{
+       unsigned int i;
+
+       for (i=0; i < height*width*2; i+=2)
+       {
+               /* BLUE  = 0 */
+               outbuffer[(i<<1)+0] = (inbuffer[i+1] & 0x1f) << 3;
+               /* GREEN = 1 */
+               outbuffer[(i<<1)+1] = 
+                       (((inbuffer[i] & 0x7) << 3) | (inbuffer[i+1] & 0xE0) >> 
5) 
+                       << 2;
+               /* RED   = 2 */
+               outbuffer[(i<<1)+2] = (inbuffer[i] & 0xF8);
+               /* ALPHA = 3 */
+               outbuffer[(i<<1)+3] = '\0';
+       }
+}
+
+static int convert_and_write(unsigned char *inbuffer, char *filename,
+                            int width, int height, int bits, int interlace)
+{
+       int ret = 0;
+
+       size_t bufsize = width * height * 4;
+
+       unsigned char *outbuffer = malloc(bufsize);
+       if (outbuffer == NULL) {
+               fprintf(stderr, "Not enough memory");
+               return -1;
+       }
+
+       memset(outbuffer, 0, bufsize);
+
+       printf("Converting image from %i\n", bits);
+
+       switch (bits) {
+       case 16:
+               convert565to32(width, height, inbuffer, outbuffer);
+               ret = write_PNG(outbuffer, filename, width, height, interlace);
+               break;
+       case 15:
+       case 24:
+       case 32:
+       default:
+               fprintf(stderr, "%d bits per pixel are not supported! ", bits);
+       }
+
+       free(outbuffer);
+
+       return ret;
+}
+
+int main_fbgrab(int argc, char **argv)
+{
+       int fd;
+       unsigned char *buf_p;
+       int ret = 0;
+
+       unsigned int bitdepth = 16;
+       size_t width = 640;
+       size_t height = 480;
+       size_t buf_size = width * height * 2;
+       int interlace = PNG_INTERLACE_NONE;
+
+       char *device = "/dev/fb";
+       char *outfile = NULL;
+
+        if(argc != 2) {
+               fprintf(stderr, "%s: you must specify a file name\n", argv[0]);
+               return 1;
+        }
+       outfile = argv[1];
+
+       fd = open(device, O_RDONLY);
+        if(fd == -1) {
+               perror("Unable to open /dev/fb");
+               return 2;
+        }
+
+       buf_p = malloc(buf_size);
+       if(buf_p == NULL) {
+               fprintf(stderr, "Unable to get %d bytes memory\n", buf_size);
+               ret = 3;
+               goto close0;
+       }
+
+       if(read(fd, buf_p, buf_size) != buf_size) {
+               perror("Unable to read device");
+               ret = 4;
+               goto free0;
+       }
+
+       ret = convert_and_write(buf_p, outfile,
+                         width, height, bitdepth,
+                         interlace);
+free0:
+       free(buf_p);
+close0:
+       close(fd);
+
+       return ret;
+}
+
+rtems_shell_cmd_t framebuffer_grab = {
+       "fbgrab",                       /* name */
+       "fbgrab file.png",              /* usage */
+       "flickernoise",                 /* topic */
+       main_fbgrab,                    /* command */
+       NULL,                           /* alias */
+       NULL                            /* next */
+};
diff --git a/src/shellext.h b/src/shellext.h
index 7c8541b..c0517df 100644
--- a/src/shellext.h
+++ b/src/shellext.h
@@ -19,5 +19,6 @@
 #define __SHELLEXT_H
 
 extern rtems_shell_cmd_t shell_usercmd;
+extern rtems_shell_cmd_t framebuffer_grab;
 
 #endif /* __SHELLEXT_H */
-- 
1.7.0.4

_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode
Twitter: www.twitter.com/milkymistvj
Ideas? http://milkymist.uservoice.com

Reply via email to