1、本程序使用到jpeg库,请读者自行安装
2、废话少说,上源码。
#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>
#define FBDEV ( "/dev/fb0" )
#define FBTMPDEV ( "/tmp/fb0" )
/* RGB565转RGB888函数
*@rgb565: 指向存放rgb565数据的起始地址
*@rgb24:指向存放rgb24数据的起始地址
*@width:屏幕(分辨率)的宽度
*@height:屏幕(分辨率)的高度
*/
int RGB565_to_RGB888( unsigned char* rgb565, unsigned char* rgb24, int width, int height )
{
int i = 0;
int whole = width * height;
unsigned char r, g, b;
unsigned short int* pix565 = NULL;
if ( NULL == rgb565 || NULL == rgb24 || width < 0 || height < 0 )
{
return -1;
}
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 0;
}
/* jpeg压缩函数
*@filename:jpg文件名
*@rgb:指向存放rgb24数据的起始地址
*@width:屏幕(分辨率)的宽度
*@height:屏幕(分辨率)的高度
*@quality: jpeg压缩质量
*/
int Jpeg_Compress(const char* filename, unsigned char* rgb, int width, int height, int quality )
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* outfile = NULL;
JSAMPROW row_pointer[ 1 ];
int row_stride = 0;
if ( NULL == filename || NULL == rgb || width < 0 || height < 0 || quality < 0 )
{
return -2;
}
cinfo.err = jpeg_std_error( &jerr );
jpeg_create_compress( &cinfo );
//输出文件
outfile = fopen( filename, "wb" );
if ( outfile == NULL )
{
return -1;
}
jpeg_stdio_dest( &cinfo, outfile );
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
//输入数据格式为RGB
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults( &cinfo );
//压缩质量
jpeg_set_quality( &cinfo, quality, TRUE );
jpeg_start_compress( &cinfo, TRUE );
row_stride = width * 3;
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 0;
}
/* 截图函数
*@filename:jpg文件名
*/
int Cut_ScreenFun( const char* filename )
{
int fd = -1;
int fdOne = -1;
struct fb_var_screeninfo fb_var_info;
unsigned char* trgb = NULL;
unsigned char* rgb = NULL;
int buffer_size = 0;
int return_value = 0;
if ( NULL == filename )
{
return_value = -1;
return return_value;
}
system("cat /dev/fb0 > /tmp/fb0");
fdOne = open( FBTMPDEV, O_RDONLY );
if ( fdOne < 0 )
{
printf( "can not open tmp dev\n" );
return_value = -2;
goto open_tmp;
}
//打开framebuffer设备
fd = open( FBDEV, O_RDONLY );
if ( fd < 0 )
{
printf( "can not open dev\n" );
return_value = -2;
goto open_tmp;
}
//获取LCD的可变参数
ioctl( fd, FBIOGET_VSCREENINFO, &fb_var_info );
//一帧大小
buffer_size = ( ( fb_var_info.xres * fb_var_info.yres * fb_var_info.bits_per_pixel ) >> 3 );
trgb = ( unsigned char* )malloc( buffer_size );
if ( NULL == trgb )
{
return_value = -3;
goto here;
}
rgb = ( unsigned char* )malloc( fb_var_info.xres * fb_var_info.yres * 3 );
if ( NULL == rgb )
{
return_value = -4;
goto here;
}
//获取一帧数据
if ( read ( fdOne, trgb, buffer_size ) < 0 )
{
printf( "read failed!\n" );
return_value = -5;
goto read_fail;
}
//格式转换
if ( RGB565_to_RGB888( trgb, rgb, fb_var_info.xres, fb_var_info.yres ) < 0 )
{
printf( "call RGB565_to_RGB888 failed!\n" );
return_value = -6;
goto read_fail;
}
//jpeg压缩
if ( Jpeg_Compress( filename, rgb, fb_var_info.xres, fb_var_info.yres, 80 ) < 0 )
{
printf( "compress failed!\n" );
return_value = -7;
goto read_fail;
}
read_fail:
free( rgb );
here:
free( trgb );
close( fd );
close( fdOne );
open_tmp:
unlink( FBTMPDEV );
return return_value;
}
int main( void )
{
Cut_ScreenFun( "./gn1108.jpg" );
system( "chmod a+x gn1108.jpg" );
return 0;
}