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