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

一、概述

        最近看到网上有人问怎么用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;
        //输入数据格式为RGB
        cinfo.in_color_space = JCS_RGB;

        jpeg_set_defaults(&cinfo);
        //压缩质量为80
        jpeg_set_quality(&cinfo, 80, 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 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("reaf 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;
}

效果:

相关:https://ask.csdn.net/questions/7623601?spm=1001.2014.3001.5505


转自:Linux下C语言实现LCD屏幕截图 - lknlfy - 博客园 (cnblogs.com)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值