/src/os/sylixos/gsnap.c

http://ftk.googlecode.com/ · C · 329 lines · 227 code · 64 blank · 38 comment · 28 complexity · 0a0a58b4681c1e855f0efaf19438a538 MD5 · raw file

  1. /*
  2. * File: gsnap.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: snap the linux mobile device screen.
  5. *
  6. * Copyright (c) 2009 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2009-08-20 Li XianJing <xianjimli@hotmail.com> created
  28. * 2011-02-28 Li XianJing <xianjimli@hotmail.com> suppport RGB888 framebuffer.
  29. * 2011-04-09 Li XianJing <xianjimli@hotmail.com> merge figofuture's png output.
  30. * ref: http://blog.chinaunix.net/space.php?uid=15059847&do=blog&cuid=2040565
  31. * 2011-08-03 Jiao JinXing <jiaojinxing1987@gmail.com> port to sylixos
  32. */
  33. #include <png.h>
  34. #include <fcntl.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <unistd.h>
  38. #include <string.h>
  39. #include <jpeglib.h>
  40. #include <sys/mman.h>
  41. #include <sys/stat.h>
  42. #include <sys/types.h>
  43. struct _FBInfo;
  44. typedef struct _FBInfo FBInfo;
  45. typedef int (*UnpackPixel)(FBInfo* fb, unsigned char* pixel,
  46. unsigned char* r, unsigned char* g, unsigned char* b);
  47. struct _FBInfo
  48. {
  49. int fd;
  50. UnpackPixel unpack;
  51. unsigned char *bits;
  52. LW_GM_VARINFO vi;
  53. LW_GM_SCRINFO fi;
  54. };
  55. #define fb_width(fb) ((fb)->vi.GMVI_ulXRes)
  56. #define fb_height(fb) ((fb)->vi.GMVI_ulYRes)
  57. #define fb_bpp(fb) ((fb)->vi.GMVI_ulBitsPerPixel >> 3)
  58. #define fb_size(fb) ((fb)->vi.GMVI_ulXRes * (fb)->vi.GMVI_ulYRes * fb_bpp(fb))
  59. static int fb_unpack_rgb565(FBInfo* fb, unsigned char* pixel,
  60. unsigned char* r, unsigned char* g, unsigned char* b)
  61. {
  62. unsigned short color = *(unsigned short*)pixel;
  63. *r = ((color >> 11) & 0xff) << 3;
  64. *g = ((color >> 5) & 0xff) << 2;
  65. *b = (color & 0xff )<< 3;
  66. return 0;
  67. }
  68. static int fb_unpack_rgb24(FBInfo* fb, unsigned char* pixel,
  69. unsigned char* r, unsigned char* g, unsigned char* b)
  70. {
  71. *r = pixel[0];
  72. *g = pixel[1];
  73. *b = pixel[2];
  74. return 0;
  75. }
  76. static int fb_unpack_argb32(FBInfo* fb, unsigned char* pixel,
  77. unsigned char* r, unsigned char* g, unsigned char* b)
  78. {
  79. *r = pixel[1];
  80. *g = pixel[2];
  81. *b = pixel[3];
  82. return 0;
  83. }
  84. static int fb_unpack_none(FBInfo* fb, unsigned char* pixel,
  85. unsigned char* r, unsigned char* g, unsigned char* b)
  86. {
  87. *r = *g = *b = 0;
  88. return 0;
  89. }
  90. static void set_pixel_unpacker(FBInfo* fb)
  91. {
  92. if(fb_bpp(fb) == 2)
  93. {
  94. fb->unpack = fb_unpack_rgb565;
  95. }
  96. else if(fb_bpp(fb) == 3)
  97. {
  98. fb->unpack = fb_unpack_rgb24;
  99. }
  100. else if(fb_bpp(fb) == 4)
  101. {
  102. fb->unpack = fb_unpack_argb32;
  103. }
  104. else
  105. {
  106. fb->unpack = fb_unpack_none;
  107. printf("%s: not supported format.\n", __func__);
  108. }
  109. return;
  110. }
  111. static int fb_open(FBInfo* fb, const char* fbfilename)
  112. {
  113. fb->fd = open(fbfilename, O_RDWR);
  114. if (fb->fd < 0)
  115. {
  116. fprintf(stderr, "can't open %s\n", fbfilename);
  117. return -1;
  118. }
  119. if (ioctl(fb->fd, LW_GM_GET_SCRINFO, &fb->fi) < 0)
  120. goto fail;
  121. if (ioctl(fb->fd, LW_GM_GET_VARINFO, &fb->vi) < 0)
  122. goto fail;
  123. fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0);
  124. if (fb->bits == MAP_FAILED)
  125. goto fail;
  126. set_pixel_unpacker(fb);
  127. return 0;
  128. fail:
  129. printf("%s is not a framebuffer.\n", fbfilename);
  130. close(fb->fd);
  131. return -1;
  132. }
  133. static void fb_close(FBInfo* fb)
  134. {
  135. munmap(fb->bits, fb_size(fb));
  136. close(fb->fd);
  137. return;
  138. }
  139. static int snap2jpg(const char * filename, int quality, FBInfo* fb)
  140. {
  141. int row_stride = 0;
  142. FILE * outfile = NULL;
  143. JSAMPROW row_pointer[1] = {0};
  144. struct jpeg_error_mgr jerr;
  145. struct jpeg_compress_struct cinfo;
  146. memset(&jerr, 0x00, sizeof(jerr));
  147. memset(&cinfo, 0x00, sizeof(cinfo));
  148. cinfo.err = jpeg_std_error(&jerr);
  149. jpeg_create_compress(&cinfo);
  150. if ((outfile = fopen(filename, "wb+")) == NULL)
  151. {
  152. fprintf(stderr, "can't open %s\n", filename);
  153. return -1;
  154. }
  155. jpeg_stdio_dest(&cinfo, outfile);
  156. cinfo.image_width = fb_width(fb);
  157. cinfo.image_height = fb_height(fb);
  158. cinfo.input_components = 3;
  159. cinfo.in_color_space = JCS_RGB;
  160. jpeg_set_defaults(&cinfo);
  161. jpeg_set_quality(&cinfo, quality, TRUE);
  162. jpeg_start_compress(&cinfo, TRUE);
  163. row_stride = fb_width(fb) * 2;
  164. JSAMPLE* image_buffer = malloc(3 * fb_width(fb));
  165. while (cinfo.next_scanline < cinfo.image_height)
  166. {
  167. int i = 0;
  168. int offset = 0;
  169. unsigned char* line = fb->bits + cinfo.next_scanline * fb_width(fb) * fb_bpp(fb);
  170. for(i = 0; i < fb_width(fb); i++, offset += 3, line += fb_bpp(fb))
  171. {
  172. fb->unpack(fb, line, image_buffer+offset, image_buffer + offset + 1, image_buffer + offset + 2);
  173. }
  174. row_pointer[0] = image_buffer;
  175. (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
  176. }
  177. jpeg_finish_compress(&cinfo);
  178. fclose(outfile);
  179. jpeg_destroy_compress(&cinfo);
  180. return 0;
  181. }
  182. //Ref: http://blog.chinaunix.net/space.php?uid=15059847&do=blog&cuid=2040565
  183. static int snap2png(const char * filename, int quality, FBInfo* fb)
  184. {
  185. FILE *outfile;
  186. if ((outfile = fopen(filename, "wb+")) == NULL)
  187. {
  188. fprintf(stderr, "can't open %s\n", filename);
  189. return -1;
  190. }
  191. /* prepare the standard PNG structures */
  192. png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
  193. png_infop info_ptr = png_create_info_struct(png_ptr);
  194. /* setjmp() must be called in every function that calls a PNG-reading libpng function */
  195. if (setjmp(png_jmpbuf(png_ptr)))
  196. {
  197. png_destroy_write_struct(&png_ptr, &info_ptr);
  198. fclose(outfile);
  199. return -1;
  200. }
  201. /* initialize the png structure */
  202. png_init_io(png_ptr, outfile);
  203. //
  204. int width = 0;
  205. int height = 0;
  206. int bit_depth = 8;
  207. int color_type = PNG_COLOR_TYPE_RGB;
  208. int interlace = 0;
  209. width = fb_width(fb);
  210. height = fb_height(fb);
  211. png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type,
  212. (!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7,
  213. PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  214. /* write the file header information */
  215. png_write_info(png_ptr, info_ptr);
  216. png_bytep row_pointers[height];
  217. png_byte* image_buffer = malloc(3 * width);
  218. int i = 0;
  219. int j = 0;
  220. unsigned char* line = NULL;
  221. for( ; i < height; i++ )
  222. {
  223. line = (char*)fb->bits + i * width * fb_bpp(fb);
  224. for(j = 0; j < width; j++, line += fb_bpp(fb))
  225. {
  226. int offset = j * 3;
  227. fb->unpack(fb, line, image_buffer+offset, image_buffer+offset+1, image_buffer+offset+2);
  228. }
  229. row_pointers[i] = image_buffer;
  230. png_write_rows(png_ptr, &row_pointers[i], 1);
  231. }
  232. png_destroy_write_struct(&png_ptr, &info_ptr);
  233. fclose(outfile);
  234. return 0;
  235. }
  236. int gsnap(int argc, char* argv[])
  237. {
  238. FBInfo fb;
  239. const char* filename = NULL;
  240. const char* fbfilename = NULL;
  241. if(argc != 3)
  242. {
  243. printf("\nUsage: %s [jpeg|png file] [framebuffer dev]\n", argv[0]);
  244. printf("Example: %s fb.jpg /dev/fb0\n", argv[0]);
  245. printf("-----------------------------------------\n");
  246. printf("Powered by broncho(www.broncho.cn)\n\n");
  247. return 0;
  248. }
  249. filename = argv[1];
  250. fbfilename = argv[2];
  251. memset(&fb, 0x00, sizeof(fb));
  252. if (fb_open(&fb, fbfilename) == 0)
  253. {
  254. if(strstr(filename, ".png") != NULL)
  255. {
  256. snap2png(filename, 100, &fb);
  257. }
  258. else
  259. {
  260. snap2jpg(filename, 100, &fb);
  261. }
  262. fb_close(&fb);
  263. }
  264. return 0;
  265. }