您的位置:首页 > 运维架构 > Linux

Linux下C语言实现LCD屏幕截图

2013-01-08 14:29 169 查看
From: http://blog.chinaunix.net/uid-24789420-id-3191806.html
一、概述

最近看到网上有人问怎么用C语言实现屏幕截图,刚好自己也在研究Linux驱动,于是花了半天时间把Linux的FrameBuffer驱动看懂了个七八,接着就动手写了个LCD屏幕截图的应用程序。

一些说明:

1. 板子LCD的分辨率为480x272,像素格式为RGB565。

2. 程序首先获取LCD的一些参数 ,然后将获取到的一帧数据转换为RGB24格式,最后用jpeglib库压缩为jpg格式的图片。

  3. 在嵌入式Linux的板子上测试通过。

二、实现
程序中有注释,不多说,直接上程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
#include <linux/fb.h>
#include <jpeglib.h>
#include <jerror.h>

/*RGB565转RGB24函数
*@rgb565: 指向存放rgb565数据的起始地址
*@rgb24:指向存放rgb24数据的起始地址
*@width:屏幕(分辨率)的宽度
*@height:屏幕(分辨率)的高度
*/
int RGB565_to_RGB24(unsigned char *rgb565, unsigned char *rgb24, int width, int height)
{
int i;
int whole = width*height;
unsigned char r, g, b;
unsigned short int *pix565;

pix565 = (unsigned short int *)rgb565;

for(i = 0;i < whole;i++)
{
r = ((*pix565)>>11)&0x1f;
*rgb24 = (r<<3) | (r>>2);
rgb24++;
g = ((*pix565)>>5)&0x3f;
*rgb24 = (g<<2) | (g>>4);
rgb24++;
b = (*pix565)&0x1f;
*rgb24 = (b<<3) | (b>>2);
rgb24++;
pix565++;

}
return 1;
}

/*jpeg压缩函数
*@rgb:指向存放rgb24数据的起始地址
*@width:屏幕(分辨率)的宽度
*@height:屏幕(分辨率)的高度
*/
int jpeg_compress(unsigned char *rgb, int width, int height)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * outfile;
JSAMPROW row_pointer[1];
int row_stride;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
// 输出文件名为:out.jpg
if ((outfile = fopen("out.jpg", "wb")) == NULL)
{
printf("can not open out.jpg\n");
return -1;
}
jpeg_stdio_dest(&cinfo, outfile);

cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;				// 1-灰度图,3-彩色图
// 输入数据格式为RGB
cinfo.in_color_space = JCS_RGB;			// JCS_GRAYSCALE-灰度图,JCS_RGB-彩色图

jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 80, TRUE);		// 设置压缩质量:80
jpeg_start_compress(&cinfo, TRUE);		// 开始压缩过程
row_stride = width * 3;					// row_stride: 每一行的字节数

while (cinfo.next_scanline < cinfo.image_height)
{
row_pointer[0] = &rgb[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}

jpeg_finish_compress(&cinfo);			// 完成压缩过程
fclose(outfile);

jpeg_destroy_compress(&cinfo);			// 释放资源

return 1;
}

int main()
{
int fd;
struct fb_var_screeninfo fb_var_info;
struct fb_fix_screeninfo fb_fix_info;
unsigned char *trgb;
unsigned char *rgb;
int buffer_size;

// 打开framebuffer设备
fd = open("/dev/fb0", O_RDONLY);
if(fd < 0)
{
printf("can not open dev\n");
exit(1);
}

// 获取LCD的可变参数
ioctl(fd, FBIOGET_VSCREENINFO, &fb_var_info);
// 一个像素多少位
printf("bits_per_pixel: %d\n", fb_var_info.bits_per_pixel);
// x分辨率
printf("xres: %d\n", fb_var_info.xres);
// y分辨率
printf("yres: %d\n", fb_var_info.yres);
// r分量长度(bit)
printf("red_length: %d\n", fb_var_info.red.length);
// g分量长度(bit)
printf("green_length: %d\n", fb_var_info.green.length);
// b分量长度(bit)
printf("blue_length: %d\n", fb_var_info.blue.length);
// t(透明度)分量长度(bit)
printf("transp_length: %d\n", fb_var_info.transp.length);
// r分量偏移
printf("red_offset: %d\n", fb_var_info.red.offset);
// g分量偏移
printf("green_offset: %d\n", fb_var_info.green.offset);
// b分量偏移
printf("blue_offset: %d\n", fb_var_info.blue.offset);
// t分量偏移
printf("transp_offset: %d\n", fb_var_info.transp.offset);

// 获取LCD的固定参数
ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix_info);
// 一帧大小
printf("smem_len: %d\n", fb_fix_info.smem_len);
// 一行大小
printf("line_length: %d\n", fb_fix_info.line_length);
// 一帧大小
buffer_size = (fb_var_info.xres * fb_var_info.yres * fb_var_info.bits_per_pixel / 8);

trgb = (unsigned char *)malloc(buffer_size);
if(trgb == NULL)
exit(0);
rgb = (unsigned char *)malloc(fb_var_info.xres * fb_var_info.yres * 3);
if(rgb == NULL)
{
goto here;
}
if(read(fd, trgb, buffer_size) < 0)		// 获取一帧数据
{
printf("read failed!\n");
goto read_fail;
}
// 格式转换
RGB565_to_RGB24(trgb, rgb, fb_var_info.xres, fb_var_info.yres);
// jpeg压缩
if(jpeg_compress(rgb, fb_var_info.xres, fb_var_info.yres) < 0)
printf("compress failed!\n");

read_fail:
free(rgb);
here:
free(trgb);

close(fd);

return 0;
}


注意:编译时加上"-ljpeg"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: