转自:http://blog.csdn.net/lu_embedded/article/details/53934184

版权声明:开心源自分享,快乐源于生活 —— 分享技术,传递快乐。转载文章请注明出处,谢谢! http://blog.csdn.net/lu_embedded/article/details/53934184

  由于 Linux 系统的 FrameBuffer 机制,把屏幕上的每个点映射成一段线性内存空间,这样,程序就可以通过改变这段内存的值来改变屏幕上某一点的颜色。如果我们想把当前的显示内容保存起来,可能会想到如下命令:

# cat /dev/fb0 > fb_data.raw
  • 1

  反过来,可以将这些数据回显到 framebuffer 中:

# cat fb_data.raw > /dev/fb0
  • 1

  使用 clear 命令清除,可以恢复正常。
  但是,用这用方法保存起来的数据是原始数据,只有专用软件才能打开,并且大小固定(如:8MB)。基于这些原因,我们找到一个不错的工具——gsnap,这个工具可以将
framebuffer 的数据保存为图片(png或jpeg格式)。下面我们介绍一下移植过程。
  这里的移植很简单,因为源文件只有 gsnap.c,因此我们只需用相应平台的编译工具链进行编译链接即可。命令如下:

# $(CC) gsnap.c -ljpeg -lpng -o gsnap
  • 1

  显然,gsnap 需要用到 libjpeg 和 libpng 两个库。那么编译成功与否就跟这两个库有关了。如果你的目标平台还没有这些依赖库,那么就有必要下载相关源码进行编译安装,步骤遵循 configure、make、make install 三部曲。
  由于我的目标平台已经包含 libjpeg 和 libpng,于是我尝试用上述命令进行编译,提示缺少头文件,所以编译不成功。然后我将 libjpeg 和 libpng 源码包中的头文件抽取出来,添加到 /usr/include。发现仍然缺少头文件,如下:

  • libpng 方面——找不到 pnglibconf.h,经检查发现将 scripts/pnglibconf.h.prebuilt 另存为
    pnglibconf.h,并添加到 /usr/include 即可。
  • libjpeg 方面——找不到 jconfig.h,经检查发现将 jconfig.txt 另存为 jconfig.h,并添加到
    /usr/include 即可。

不用担心,如果你遵循三部曲来安装这些库,上面的 pnglibconf.h 和 jconfig.h 都会在编译的过程中生成。
  一旦编译成功,我们就可以运行 gsnap 来截取屏幕画面了。gsnap 的使用也很简单,格式为:

    gsnap <jpeg|png file> <framebuffer dev>
  • 1

  例如:

# ./gsnap test.png /dev/fb0
  • 1

  我这里用的是 i.mx6q 的 yocto 1.5.3 系统,截图 test.png 如下:



  以下是 gsnap.c 的源代码:

/*
* File: gsnap.c
* Author: Li XianJing <xianjimli@hotmail.com>
* Brief: snap the linux mobile device screen.
*
* Copyright (c) 2009 Li XianJing <xianjimli@hotmail.com>
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ /*
* History:
* ================================================================
* 2009-08-20 Li XianJing <xianjimli@hotmail.com> created
* 2011-02-28 Li XianJing <xianjimli@hotmail.com> suppport RGB888 framebuffer.
* 2011-04-09 Li XianJing <xianjimli@hotmail.com> merge figofuture's png output.
* ref: http://blog.chinaunix.net/space.php?uid=15059847&do=blog&cuid=2040565
*
*/ #include <png.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <jpeglib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fb.h>
#include <linux/kd.h> struct _FBInfo;
typedef struct _FBInfo FBInfo;
typedef int (*UnpackPixel)(FBInfo* fb, unsigned char* pixel,
unsigned char* r, unsigned char* g, unsigned char* b); struct _FBInfo
{
int fd;
UnpackPixel unpack;
unsigned char *bits;
struct fb_fix_screeninfo fi;
struct fb_var_screeninfo vi;
}; #define fb_width(fb) ((fb)->vi.xres)
#define fb_height(fb) ((fb)->vi.yres)
#define fb_bpp(fb) ((fb)->vi.bits_per_pixel>>3)
#define fb_size(fb) ((fb)->vi.xres * (fb)->vi.yres * fb_bpp(fb)) static int fb_unpack_rgb565(FBInfo* fb, unsigned char* pixel,
unsigned char* r, unsigned char* g, unsigned char* b)
{
unsigned short color = *(unsigned short*)pixel; *r = ((color >> 11) & 0xff) << 3;
*g = ((color >> 5) & 0xff) << 2;
*b = (color & 0xff )<< 3; return 0;
} static int fb_unpack_rgb24(FBInfo* fb, unsigned char* pixel,
unsigned char* r, unsigned char* g, unsigned char* b)
{
*r = pixel[fb->vi.red.offset>>3];
*g = pixel[fb->vi.green.offset>>3];
*b = pixel[fb->vi.blue.offset>>3]; return 0;
} static int fb_unpack_argb32(FBInfo* fb, unsigned char* pixel,
unsigned char* r, unsigned char* g, unsigned char* b)
{
*r = pixel[fb->vi.red.offset>>3];
*g = pixel[fb->vi.green.offset>>3];
*b = pixel[fb->vi.blue.offset>>3]; return 0;
} static int fb_unpack_none(FBInfo* fb, unsigned char* pixel,
unsigned char* r, unsigned char* g, unsigned char* b)
{
*r = *g = *b = 0; return 0;
} static void set_pixel_unpacker(FBInfo* fb)
{
if(fb_bpp(fb) == 2)
{
fb->unpack = fb_unpack_rgb565;
}
else if(fb_bpp(fb) == 3)
{
fb->unpack = fb_unpack_rgb24;
}
else if(fb_bpp(fb) == 4)
{
fb->unpack = fb_unpack_argb32;
}
else
{
fb->unpack = fb_unpack_none;
printf("%s: not supported format.\n", __func__);
} return;
} static int fb_open(FBInfo* fb, const char* fbfilename)
{
fb->fd = open(fbfilename, O_RDWR); if (fb->fd < 0)
{
fprintf(stderr, "can't open %s\n", fbfilename); return -1;
} if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0)
goto fail; if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0)
goto fail; fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0); if (fb->bits == MAP_FAILED)
goto fail; printf("---------------framebuffer---------------\n");
printf("%s: \n width : %8d\n height: %8d\n bpp : %8d\n r(%2d, %2d)\n g(%2d, %2d)\n b(%2d, %2d)\n",
fbfilename, fb_width(fb), fb_height(fb), fb_bpp(fb),
fb->vi.red.offset, fb->vi.red.length,
fb->vi.green.offset, fb->vi.green.length,
fb->vi.blue.offset, fb->vi.blue.length);
printf("-----------------------------------------\n"); set_pixel_unpacker(fb); return 0; fail:
printf("%s is not a framebuffer.\n", fbfilename);
close(fb->fd); return -1;
} static void fb_close(FBInfo* fb)
{
munmap(fb->bits, fb_size(fb));
close(fb->fd); return;
} static int snap2jpg(const char * filename, int quality, FBInfo* fb)
{
int row_stride = 0;
FILE * outfile = NULL;
JSAMPROW row_pointer[1] = {0};
struct jpeg_error_mgr jerr;
struct jpeg_compress_struct cinfo; memset(&jerr, 0x00, sizeof(jerr));
memset(&cinfo, 0x00, sizeof(cinfo)); cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo); if ((outfile = fopen(filename, "wb+")) == NULL)
{
fprintf(stderr, "can't open %s\n", filename); return -1;
} jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = fb_width(fb);
cinfo.image_height = fb_height(fb);
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE); row_stride = fb_width(fb) * 2;
JSAMPLE* image_buffer = malloc(3 * fb_width(fb)); while (cinfo.next_scanline < cinfo.image_height)
{
int i = 0;
int offset = 0;
unsigned char* line = fb->bits + cinfo.next_scanline * fb_width(fb) * fb_bpp(fb); for(i = 0; i < fb_width(fb); i++, offset += 3, line += fb_bpp(fb))
{
fb->unpack(fb, line, image_buffer+offset, image_buffer + offset + 1, image_buffer + offset + 2);
} row_pointer[0] = image_buffer;
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
} jpeg_finish_compress(&cinfo);
fclose(outfile); jpeg_destroy_compress(&cinfo); return 0;
} //Ref: http://blog.chinaunix.net/space.php?uid=15059847&do=blog&cuid=2040565
static int snap2png(const char * filename, int quality, FBInfo* fb)
{
FILE *outfile;
if ((outfile = fopen(filename, "wb+")) == NULL)
{
fprintf(stderr, "can't open %s\n", filename);
return -1;
} /* prepare the standard PNG structures */
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0); png_infop info_ptr = png_create_info_struct(png_ptr); /* setjmp() must be called in every function that calls a PNG-reading libpng function */
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(outfile);
return -1;
} /* initialize the png structure */
png_init_io(png_ptr, outfile); //
int width = 0;
int height = 0;
int bit_depth = 8;
int color_type = PNG_COLOR_TYPE_RGB;
int interlace = 0;
width = fb_width(fb);
height = fb_height(fb); png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type,
(!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* write the file header information */
png_write_info(png_ptr, info_ptr); png_bytep row_pointers[height];
png_byte* image_buffer = malloc(3 * width); int i = 0;
int j = 0;
unsigned char* line = NULL;
for( ; i < height; i++ )
{
line = (char*)fb->bits + i * width * fb_bpp(fb);
for(j = 0; j < width; j++, line += fb_bpp(fb))
{
int offset = j * 3;
fb->unpack(fb, line, image_buffer+offset, image_buffer+offset+1, image_buffer+offset+2);
}
row_pointers[i] = image_buffer;
png_write_rows(png_ptr, &row_pointers[i], 1);
} png_destroy_write_struct(&png_ptr, &info_ptr); fclose(outfile); return 0; } int main(int argc, char* argv[])
{
FBInfo fb;
const char* filename = NULL;
const char* fbfilename = NULL; if(argc != 3)
{
printf("\nUsage: %s [jpeg|png file] [framebuffer dev]\n", argv[0]);
printf("Example: %s fb.jpg /dev/fb0\n", argv[0]);
printf("-----------------------------------------\n");
printf("Powered by broncho(www.broncho.cn)\n\n"); return 0;
} filename = argv[1];
fbfilename = argv[2]; memset(&fb, 0x00, sizeof(fb));
if (fb_open(&fb, fbfilename) == 0)
{
if(strstr(filename, ".png") != NULL)
{
snap2png(filename, 100, &fb);
}
else
{
snap2jpg(filename, 100, &fb);
}
fb_close(&fb);
} return 0;
}

嵌入式Linux截图工具gsnap移植与分析【转】的更多相关文章

  1. 截图工具gsnap

    嵌入式linux截图工具的基本原理就是通过读取Framebuffer,把LCD上显示的内容转换成图片格式文件(jpeg.bmp.png). gsnap.bin 1.jpg  /dev/fb0 gsna ...

  2. 基于s5pv210嵌入式linux系统sqlite3数据库移植

    基于s5pv210嵌入式linux系统sqlite3数据库移植 1.下载源码 http://www.sqlite.org/download.html 最新源码为3080100 2.解压 tar xvf ...

  3. linux截图工具scrot

    SCROT截图工具 安装命令 sudo apt-get install scrot 截图命令使用说明: 1.抓取整个桌面:    scrot   ~/Pictures/pic1.jpg2.抓取窗口:  ...

  4. 【转载】Linux截图工具

    如果linux安装了gnome,那么系统自带了一款截屏软件 gnome-screenshot,使用起来很方便,功能齐备,支持命令行.简单介绍如下. 功能 对屏幕,窗口,或自定义的区域进行截图. 选项 ...

  5. Linux dd工具磁盘读写测试分析

    话说,Linux 自带的dd工具测试硬盘读写速度只能提供一个大概的测试结果,而且是连续IO 而不是随机IO ,理论上文件规模越大,测试结果越准确.理论上bs越大,所测得性能越高. 上句来自网上,是不是 ...

  6. Linux文本工具-cat-cut-paste;文本分析-sort-wc-uniq

    1.1 查看文本文件内容  cat 1.1.1 cat可以查看文本内容 cat [OPTION]... [FILE]... 常见选项 -E: 显示行结束符$ -A: 显示所有控制符 -n: 对显示出的 ...

  7. linux 截图工具 shutter

    ubuntu 安装shutter sudo apt install shutter libgoo-canvas-perl libgoo-canvas-perl是提供对截图编辑功能,例如,添加画框,文字 ...

  8. linux截图工具

    推荐:deepin-scrot 满足功能: 能够自定义快捷键(Ctrl+Alt+A) 小巧快速自定义选择区域进行截图 有简单的绘图功能 可以快速的保存到剪切版(双击图片) P.S.:双重截图

  9. 构建嵌入式Linux交叉编译工具链

    开源交叉编译工具链制作方法汇总: 1) 使用crosstool/crosstool-ng生成 2) 使用buildroot生成 ARM交叉编译工具链说明: 1) arm-linux-gcc是一个集合命 ...

随机推荐

  1. 【Java并发编程】之六:Runnable和Thread实现多线程的区别

    Java中实现多线程有两种方法:继承Thread类.实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下 ...

  2. DAY6-Python学习笔记

    前记: 坚持写学习笔记今天是第六天了,今天事情有点多想起来还没写赶快补起来,学习Python已经快一个星期了,大部分的知识点已经跟着廖雪峰老师的教程了解了一下,由于自学能力不强还有很多知识点掌握不牢固 ...

  3. 基于element-ui的后台系统表格、dialog、筛选、自定义按钮、分页的一次性封装

    方便基础业务开发封装的一套组件,基于vue2.5.x和element-ui,可以通过配置自动生成表格展示,表格新增.编辑功能.分页.筛选项.自定义显示表格数据等功能. 先上演示图片 --------- ...

  4. XOR and Favorite Number CodeForces - 617E(前缀异或+莫队)

    题意原文地址:https://blog.csdn.net/chenzhenyu123456/article/details/50574169 题意:有n个数和m次查询,每次查询区间[l, r]问满足a ...

  5. 【BZOJ2724】蒲公英(分块)

    [BZOJ2724]蒲公英(分块) 题面 洛谷 谴责权限题的行为 题解 分块什么的都不会,根本就没写过几次. 复杂度根本不会分析,吓得我赶快来练练. 这题要求的是区间众数,显然没有什么很好的主席树之类 ...

  6. C++中三种传递参数方法的效率分析

    众所周知,在C++中有三种参数传递的方式: 按值传递(pass by value) #include <iostream> using namespace std; void swap(i ...

  7. 解题:HEOI 2016 求和

    题面 我们需要知道这样一个东西(大概叫 斯特林公式?) $S(i,j)=\frac{1}{j!}\sum\limits_{k=0}^{j}(-1)^k C_j^k(j-k)^i$ 那么就是推啊 $=\ ...

  8. 用Anaconda安装本地python包

    Anaconda确实带来了很多方便,但是之前也过多的依赖了conda自带的一键下载python包的功能.这不,这几天突然要用FastFM这个包,无奈conda里没有,于是只能从github下载下来,实 ...

  9. Java锁及AbstractQueuedSynchronizer源码分析

    一,Lock 二,关于锁的几个概念 三,ReentrantLock类图 四,几个重要的类 五,公平锁获取 5.1 lock 5.2 acquire 5.3 tryAcquire 5.3.1 hasQu ...

  10. 算法进阶之Leetcode刷题记录

    目录 引言 题目 1.两数之和 题目 解题笔记 7.反转整数 题目 解题笔记 9.回文数 题目 解题笔记 13.罗马数字转整数 题目 解题笔记 14.最长公共前缀 题目 解题笔记 20.有效的括号 题 ...