栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux LVGL Framebuffer截屏保存为PNG图片

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux LVGL Framebuffer截屏保存为PNG图片

framebuffer截屏保存为PNG图片

产品做说明书,或开发过程中有时的沟通,常有截屏的需求!一般的UI开发库中也有这个基本的功能,截屏功能!
其实比较简单,把frameBuffer中的内存拷出来,写到PNG图片即可!

调试时,把RGB的顺序搞反了,保存的图片,色彩总是不对,见下面代码的for代码,libpng中有一个接口设置RGB顺序了: png_set_bgr 。
在不同的平台获取的数据可能不同,需要根据实际情况调整! 这里UI也是32位的RGBA,framebuffer也是设置成为32的RGBA方式!

开发中如果色彩不对,可以在UI里设置一个区域的颜色的R,G,B值都写好,在下面的拷贝内存中这个位置的RGB值分别打印现来,应该就很快定位问题!

PUPANVR这个工程里,添加了 view/TViewScreenSnap.h里实现了这个功能!
代码位置: https://gitee.com/jhting/pupanvr/blob/develop/app/appmain/view/TViewScreenSnap.cpp
代码是在LVGL的UI中做的,在fbdev.c中改了一下几个函数!

	void fbdev_get_sizes(uint32_t *width, uint32_t *height, uint32_t *line_length);	
	char* fbdev_get_framebufferMapAddr();

上面只是改了一下 fbdev_get_sizes, 添加了 fbdev_get_framebufferMapAddr 获取打开的地址!这样不用再去open一个framebuffer设备了!

截屏代码实现如下:

	
bool TViewScreenSnap::screenSnap(const char* pngFileName)
{
    unsigned int width = 0;
    unsigned int height = 0;
    unsigned int line_length = 0;
    unsigned int bit_depth = 8;

    unsigned int i = 0;
    unsigned int k = 0;
    unsigned char *rawDataBuffer = NULL;

    FILE *fp = NULL;

    char* framebufferDevAddr = fbdev_get_framebufferMapAddr();
    if(!framebufferDevAddr)
    {
        return false;
    }

    fbdev_get_sizes(&width, &height, &line_length);

    if(width == 0 || height == 0 || line_length == 0)
    {
        return false;
    }

    png_structp png_ptr;
    png_infop info_ptr;

    fp = fopen(pngFileName, "wb");
    if(!fp)
    {
        printf("screenSnap open file %s failure!n", pngFileName);
        return false;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (png_ptr == NULL)
    {
        printf("png_create_write_struct failure!n");
        fclose(fp);
        return false;
    }

    rawDataBuffer = (unsigned char*)malloc(line_length);
    if(!rawDataBuffer)
    {
        fclose(fp);
        png_destroy_write_struct(&png_ptr,  NULL);
        return false;
    }

     
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
        fclose(fp);
        free(rawDataBuffer);
        png_destroy_write_struct(&png_ptr,  NULL);
        return false;
    }

       
   if (setjmp(png_jmpbuf(png_ptr)))
   {
      
      fclose(fp);
      free(rawDataBuffer);
      png_destroy_write_struct(&png_ptr, &info_ptr);
      return false;
   }

    //png_set_swap_alpha(png_ptr);

    png_init_io(png_ptr, fp);
  
    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGBA,
       PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    
    png_set_packing(png_ptr);

    //frame BGRA      ->   RGBA
    png_set_bgr(png_ptr);

    png_write_info(png_ptr, info_ptr);

    unsigned char* pRawRowData = (unsigned char*)framebufferDevAddr;
	for(k = 0; k < height; k++) 
    {
        #if 1
            memcpy(rawDataBuffer, framebufferDevAddr + k * line_length, line_length);
        #else
            pRawRowData = (unsigned char*)(framebufferDevAddr + k * line_length);
            for(i = 0; i < line_length; i = i + 4)
            {  
                //frame BGRA      ->   RGBA
                rawDataBuffer[i + 0] = pRawRowData[i + 2];     //R              
                rawDataBuffer[i + 1] = pRawRowData[i + 1];     //G
                rawDataBuffer[i + 2] = pRawRowData[i + 0];     //B
                rawDataBuffer[i + 3] = pRawRowData[i + 3];     //A
            }
        
        #endif
		png_write_row(png_ptr, rawDataBuffer);
	}

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);

    free(rawDataBuffer);
    fclose(fp);
    return true;
}

效果图!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/747879.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号