PageRenderTime 547ms CodeModel.GetById 362ms app.highlight 63ms RepoModel.GetById 118ms app.codeStats 1ms

/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/*
 26 * History:
 27 * ================================================================
 28 * 2009-08-20 Li XianJing <xianjimli@hotmail.com> created
 29 * 2011-02-28 Li XianJing <xianjimli@hotmail.com> suppport RGB888 framebuffer.
 30 * 2011-04-09 Li XianJing <xianjimli@hotmail.com> merge figofuture's png output.
 31 * 	ref: http://blog.chinaunix.net/space.php?uid=15059847&do=blog&cuid=2040565
 32 * 2011-08-03 Jiao JinXing <jiaojinxing1987@gmail.com> port to sylixos
 33 */
 34
 35#include <png.h>
 36#include <fcntl.h>
 37#include <stdio.h>
 38#include <stdlib.h>
 39#include <unistd.h>
 40#include <string.h>
 41#include <jpeglib.h>
 42#include <sys/mman.h>
 43#include <sys/stat.h>
 44#include <sys/types.h>
 45
 46struct _FBInfo;
 47typedef struct _FBInfo FBInfo;
 48typedef int (*UnpackPixel)(FBInfo* fb, unsigned char* pixel, 
 49	unsigned char* r, unsigned char* g, unsigned char* b);
 50
 51struct _FBInfo
 52{
 53	int fd;
 54	UnpackPixel unpack;
 55	unsigned char *bits;
 56    LW_GM_VARINFO vi;
 57    LW_GM_SCRINFO fi;
 58};
 59
 60#define fb_width(fb)  ((fb)->vi.GMVI_ulXRes)
 61#define fb_height(fb) ((fb)->vi.GMVI_ulYRes)
 62#define fb_bpp(fb)    ((fb)->vi.GMVI_ulBitsPerPixel >> 3)
 63#define fb_size(fb)   ((fb)->vi.GMVI_ulXRes * (fb)->vi.GMVI_ulYRes * fb_bpp(fb))
 64
 65static int fb_unpack_rgb565(FBInfo* fb, unsigned char* pixel, 
 66	unsigned char* r, unsigned char* g, unsigned char* b)
 67{
 68	unsigned short color = *(unsigned short*)pixel;
 69
 70	*r = ((color >> 11) & 0xff) << 3;
 71	*g = ((color >> 5) & 0xff)  << 2;
 72	*b = (color & 0xff )<< 3;
 73
 74	return 0;
 75}
 76
 77static int fb_unpack_rgb24(FBInfo* fb, unsigned char* pixel, 
 78	unsigned char* r, unsigned char* g, unsigned char* b)
 79{
 80	*r = pixel[0];
 81	*g = pixel[1];
 82	*b = pixel[2];
 83
 84	return 0;
 85}
 86
 87static int fb_unpack_argb32(FBInfo* fb, unsigned char* pixel, 
 88	unsigned char* r, unsigned char* g, unsigned char* b)
 89{
 90	*r = pixel[1];
 91	*g = pixel[2];
 92	*b = pixel[3];
 93
 94	return 0;
 95}
 96
 97static int fb_unpack_none(FBInfo* fb, unsigned char* pixel, 
 98	unsigned char* r, unsigned char* g, unsigned char* b)
 99{
100	*r = *g = *b = 0;
101
102	return 0;
103}
104
105static void set_pixel_unpacker(FBInfo* fb)
106{
107	if(fb_bpp(fb) == 2)
108	{
109		fb->unpack = fb_unpack_rgb565;
110	}
111	else if(fb_bpp(fb) == 3)
112	{
113		fb->unpack = fb_unpack_rgb24;
114	}
115	else if(fb_bpp(fb) == 4)
116	{
117		fb->unpack = fb_unpack_argb32;
118	}
119	else
120	{
121		fb->unpack = fb_unpack_none;
122		printf("%s: not supported format.\n", __func__);
123	}
124
125	return;
126}
127
128static int fb_open(FBInfo* fb, const char* fbfilename)
129{
130	fb->fd = open(fbfilename, O_RDWR);
131
132	if (fb->fd < 0)
133	{
134		fprintf(stderr, "can't open %s\n", fbfilename);
135
136		return -1;
137	}
138
139	if (ioctl(fb->fd, LW_GM_GET_SCRINFO, &fb->fi) < 0)
140		goto fail;
141
142	if (ioctl(fb->fd, LW_GM_GET_VARINFO, &fb->vi) < 0)
143		goto fail;
144
145    fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0);
146
147	if (fb->bits == MAP_FAILED)
148		goto fail;
149
150	set_pixel_unpacker(fb);
151
152	return 0;
153
154fail:
155	printf("%s is not a framebuffer.\n", fbfilename);
156	close(fb->fd);
157
158	return -1;
159}
160
161static void fb_close(FBInfo* fb)
162{
163    munmap(fb->bits, fb_size(fb));
164
165	close(fb->fd);
166
167	return;
168}
169
170static int snap2jpg(const char * filename, int quality, FBInfo* fb)
171{
172	int row_stride = 0; 
173	FILE * outfile = NULL;
174	JSAMPROW row_pointer[1] = {0};
175	struct jpeg_error_mgr jerr;
176	struct jpeg_compress_struct cinfo;
177
178	memset(&jerr, 0x00, sizeof(jerr));
179	memset(&cinfo, 0x00, sizeof(cinfo));
180
181	cinfo.err = jpeg_std_error(&jerr);
182	jpeg_create_compress(&cinfo);
183
184	if ((outfile = fopen(filename, "wb+")) == NULL) 
185	{
186		fprintf(stderr, "can't open %s\n", filename);
187
188		return -1;
189	}
190
191	jpeg_stdio_dest(&cinfo, outfile);
192	cinfo.image_width = fb_width(fb);
193	cinfo.image_height = fb_height(fb);
194	cinfo.input_components = 3;
195	cinfo.in_color_space = JCS_RGB;
196	jpeg_set_defaults(&cinfo);
197	jpeg_set_quality(&cinfo, quality, TRUE);
198	jpeg_start_compress(&cinfo, TRUE);
199
200	row_stride = fb_width(fb) * 2;
201	JSAMPLE* image_buffer = malloc(3 * fb_width(fb));
202
203	while (cinfo.next_scanline < cinfo.image_height) 
204	{
205		int i = 0;
206		int offset = 0;
207		unsigned char* line = fb->bits + cinfo.next_scanline * fb_width(fb) * fb_bpp(fb);
208
209		for(i = 0; i < fb_width(fb); i++, offset += 3, line += fb_bpp(fb))
210		{
211			fb->unpack(fb, line, image_buffer+offset, image_buffer + offset + 1, image_buffer + offset + 2);
212		}
213
214		row_pointer[0] = image_buffer;
215		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
216	}
217
218	jpeg_finish_compress(&cinfo);
219	fclose(outfile);
220
221	jpeg_destroy_compress(&cinfo);
222
223	return 0;
224}
225
226//Ref: http://blog.chinaunix.net/space.php?uid=15059847&do=blog&cuid=2040565
227static int snap2png(const char * filename, int quality, FBInfo* fb)
228{
229	FILE *outfile;
230	if ((outfile = fopen(filename, "wb+")) == NULL)
231	{
232		fprintf(stderr, "can't open %s\n", filename);
233		return -1;
234	}
235
236	/* prepare the standard PNG structures */
237	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
238	
239	png_infop info_ptr = png_create_info_struct(png_ptr);
240
241	/* setjmp() must be called in every function that calls a PNG-reading libpng function */
242	if (setjmp(png_jmpbuf(png_ptr)))
243	{
244		png_destroy_write_struct(&png_ptr, &info_ptr);
245		fclose(outfile);
246		return -1;
247	}
248
249	/* initialize the png structure */
250	png_init_io(png_ptr, outfile);
251
252	//
253	int width = 0;
254	int height = 0;
255	int bit_depth = 8;
256	int color_type = PNG_COLOR_TYPE_RGB;
257	int interlace = 0;
258	width = fb_width(fb);
259	height = fb_height(fb);
260
261	png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type,
262					(!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7,
263					PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
264
265	/* write the file header information */
266	png_write_info(png_ptr, info_ptr);
267
268	png_bytep row_pointers[height];
269	png_byte* image_buffer = malloc(3 * width);
270
271	int i = 0;
272	int j = 0;
273	unsigned char* line = NULL;
274	for( ; i < height; i++ )
275	{
276		line = (char*)fb->bits + i * width * fb_bpp(fb);
277		for(j = 0; j < width; j++, line += fb_bpp(fb))
278		{
279			int offset = j * 3;
280			fb->unpack(fb, line, image_buffer+offset, image_buffer+offset+1, image_buffer+offset+2);
281		}
282		row_pointers[i] = image_buffer;
283		png_write_rows(png_ptr, &row_pointers[i], 1);
284	}
285	
286	png_destroy_write_struct(&png_ptr, &info_ptr);
287
288	fclose(outfile);
289
290	return 0;
291
292}
293
294int gsnap(int argc, char* argv[])
295{
296	FBInfo fb;
297	const char* filename   = NULL;
298	const char* fbfilename = NULL;
299
300	if(argc != 3)
301	{
302		printf("\nUsage: %s [jpeg|png file] [framebuffer dev]\n", argv[0]);
303		printf("Example: %s fb.jpg /dev/fb0\n", argv[0]);
304		printf("-----------------------------------------\n");
305		printf("Powered by broncho(www.broncho.cn)\n\n");
306
307		return 0;
308	}
309
310	filename   = argv[1];
311	fbfilename = argv[2];
312
313	memset(&fb, 0x00, sizeof(fb));
314	if (fb_open(&fb, fbfilename) == 0)
315	{
316		if(strstr(filename, ".png") != NULL)
317		{
318			snap2png(filename, 100, &fb);
319		}
320		else
321		{
322			snap2jpg(filename, 100, &fb);
323		}
324		fb_close(&fb);
325	}
326
327	return 0;
328}
329