Linux截图工具gsnap移植arm平台过程记录
Linux截图工具gsnap移植arm平台过程记录
最近工作中一款新产品开发接近尾声,需要写文档截图产品图形,找了一款开源的Linux截屏工具gsnap,将其移植到ARM产品中,这里记录一下移植过程。
gsnap
这个工具源代码就是一个C语言源文件: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;
}
gsnap需要两个依赖库libjpeg和libPng。而libPng还要依赖Zlib库。关于Zlib库的交叉编译请参考我这篇文档不再赘述zlib库的交叉编译记录
编译libjpeg库
从官网ijg.org下载源码
在Linux主机中解压后进入解压目录jpeg-9f。
运行autotools的配置命令进行配置后编译。
./configure --host=arm-linux-gnueabihf --prefix=/root/jpeg-9f/arm_install
make && make install
–host参数是指定编译器,我已经将我的ARM交叉编译工具链目录设置在了系统目录中,所以这里只需指定编译器前缀就行。
–prefix参数是指定编译后的安装目录,编译后make工具会将生成的编译文件和头文件目录拷贝到这个指定目录中。
编译libpng库
从SourceForge中下载源代码,我下载的是libpng-1.6.43.tar.gz
在Linux主机中解压后进入解压目录libpng-1.6.43。
注意,因为需要zlib库,故先配置一下几个编译变量。
export LDFLAGS="-L/root/zlib/arm_install/lib"
export CFLAGS="-I/root/zlib/arm_install/include"
export CPPFLAGS="-I/root/zlib/arm_install/include"
LDFLAGS是编译器搜索库文件路径变量。
CFLAGS是编译器C语言编译选项变量,这里是设置zlib库的头文件位置。
CPPFLAGS是编译器预处理器选项变量,这里是设置zlib库的头文件位置。
设置环境变量完毕后,运行配置命令进行配置后编译。
./configure --host=arm-linux-gnueabihf --prefix=/root/libpng-1.6.43/arm_install
make && make install
编译gsnap
几个库都准备好了,进入gsnap目录,将gsnap.c文件拷贝进来,进行编译。编译命令如下:
arm-linux-gnueabihf-gcc -o gsnap gsnap.c \
-L/root/jpeg-9f/arm_install/lib \
-L/root/libpng-1.6.43/arm_install/lib \
-L/root/zlib/arm_install/lib \
-I/root/jpeg-9f/arm_install/include \
-I/root/libpng-1.6.43/arm_install/include \
-I/root/zlib/arm_install/include \
-static -ljpeg -lpng -lz -lm
此命令是用静态链接方式,编译后不再需要几个库文件,单独使用编译后的gsnap文件即可。
将编译目标文件gsnap拷贝到arm板子中。
运行命令:
gsnap test.jpg /dev/fb0
这样就捕获了当前屏幕的截图文件test.jpg。
如果文章对您有用,请随手点个赞,谢谢!^_^
相关文章:

Linux截图工具gsnap移植arm平台过程记录
Linux截图工具gsnap移植arm平台过程记录 最近工作中一款新产品开发接近尾声,需要写文档截图产品图形,找了一款开源的Linux截屏工具gsnap,将其移植到ARM产品中,这里记录一下移植过程。 gsnap 这个工具源代码就是一个C语言源文件&a…...

密码学知识点02
#来自ウルトラマンレオ(雷欧) 1 常见加密方式 2 对称加密 采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。 常见加密算法: DES : Data…...

实现Pytest测试用例按顺序循环执行多次
要实现测试用例按顺序循环执行多次,可以使用 pytest 的自定义装饰器或插件。这里有两种方法可以实现这个需求: 方法一:使用 pytest-repeat 插件 pytest-repeat 插件允许你重复执行测试用例。你可以使用 --count 参数来指定每个测试用例的执…...

SVN工作原理和使用示例
SVN(Subversion)是另一种版本控制系统,用于管理项目文件及其变更历史。与Git不同,SVN是集中式版本控制系统,这意味着所有版本控制操作都集中在一个中央服务器上。以下是SVN的工作原理和基本使用示例。 目录 SVN 工作…...

云服务器部署Java+Vue前后端分离项目
1、申请一个云服务器 选择云服务器:阿里云、腾讯云、百度云、京东云、华为云等等,我使用的是阿里云服务器。 2、远程链接服务器 使用FinalShell工具或者其他远程工具,使用SSH链接,主机地址要填写阿里云服务的公网ip,如…...

C++的7种设计模式原则
一、设计模式前言 设计模式(Design Patterns)的“模式”指的是一种在软件设计中经过验证的、解决特定问题的方案。它们不是具体的代码,而是解决常见设计问题的抽象方案或模板。设计模式提供了一种标准的方式来组织代码,以提高代码…...

24.8.5数据结构|栈
栈-弹夹 1、定义: 栈就是特殊的线性表,与之前的线性表的区别就是增加了约束,只允许在一端插入和删除,就这麽简单。 2、基本操作 栈的插入操作叫:入栈{进栈、压栈};栈的删除:出栈{退栈&#x…...

LeetCode算法题训练
力扣刷题训练 开始记录力扣的刷题之路 刷题思路来自灵茶山艾府 入门题单: 「新」动计划 编程入门编程基础 0 到 1 训练方法 A 滑动窗口(定长/不定长/多指针)二分算法(二分答案/最小化最大值/最大化最小值/第K小)…...

Python | Leetcode Python题解之第326题3的幂
题目: 题解: class Solution:def isPowerOfThree(self, n: int) -> bool:return n > 0 and 1162261467 % n 0...

手机CPU性能天梯图(2024年8月),含安兔兔/GB6/3DMark跑分
原文地址(高清无水印原图/持续更新/含榜单出处链接): 2024年8月手机处理器天梯图 2024年8月1日更新日志:由于近期并未有新处理器发布,故只做常规更新;移除鲁大师天梯图;补充其它天梯图数量。 -…...

通过实际的例子和代码演示,可以更好地理解 `optional` 的使用方式和应用场景
当然,让我们通过一些实际的例子来演示 std::optional 的使用方式和应用场景。 场景 1:函数返回值 假设我们有一个函数,它尝试从字符串中解析一个整数,但如果字符串不是一个有效的整数,我们希望返回一个错误状态。 #…...

Java 电商秒杀系统优化实战:实现进阶示例详解与 RabbitMQ 配置
上一篇博客介绍了使用消息队列、异步处理等技术构建 Java 电商秒杀系统的基本思路,本文将进一步优化代码实现,并提供更详细的代码示例和 RabbitMQ 配置,助您构建更健壮、高效的秒杀系统。 一、 代码优化 1. 接口限流 在 SeckillController…...

路径规划 | 基于狼群算法的无人机路径规划(Matlab)
目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 路径规划 | 基于狼群算法的无人机路径规划(Matlab) 狼是一种群居性动物,社会分工明确,通过承担各自的责任与团结协作,共同促进整个狼群的生存与发展。狼群算…...

13-python函数返回值和装包的后续提取数据方法——解包
1.1 参数解包 不定长参数简单来讲就是装包,把多个参数装到一个元组或者装到字典中,就叫做装包 Ctrld可以快速向下复制 传递实参时,也可以在序列类型的参数前添加星号,这样他会自动将序列中的元素依次作为参数传递 注意&#x…...

I. 对线
https://codeforces.com/gym/103186/problem/I 一开始感觉操作挺复杂的 但是写过Chino的数列 - 洛谷 发现可以通过矩阵来实现swap操作,就想能不能用线段树维护矩阵来写 有三排兵线,我们维护区间和,因此初始矩阵就有了 接下来分析每个操作的…...
Topsis法模型(评价类问题)
目录 本文章内容参考: 一. 概念 二. 特点和适用范围 三. 实现步骤 四. 代码实现 本文章内容参考: TOPSIS法模型讲解(附matlab和python代码) 【数学建模快速入门】数模加油站 江北_哔哩哔哩_bilibili 一. 概念 TOPSIS(Technique for O…...

HPA 与pod调度
HPA 自动更新工作负载资源(例如 Deployment 或者 StatefulSet), 目的是自动扩缩工作负载以满足需求。 绑定到deploy上,控制pod 依托于metrics-server HorizontalPodAutoscaler 水平pod自动扩缩:意味着对增加的负…...

jupyter下载
https://blog.csdn.net/qq_48372575/article/details/125630622 我下面是CPU运行的,GPU链接在上面 Anaconda下载 https://docs.anaconda.com/miniconda/miniconda-other-installer-links/ 参考链接: https://blog.csdn.net/qq_48372575/article/detai…...

蓝桥杯双周赛 第 16 场 小白入门赛 解题报告 | 珂学家 | 七夕娱乐场
前言 题解 因为这场七夕节,所以出的特别友好。 整体还是偏思维。 T6 额外提供组合数学解,还是蛮有趣的。 A. 喜鹊罢工 题型: 签到 365 可以有多少个 7 组成 365可以有多少个7组成 365可以有多少个7组成 向上取整即可 #include <iostream>usi…...

[C++] 深入理解面向对象编程特性 : 继承
文章目录 继承的概念与定义继承的定义定义格式不同继承方式与继承的基类中访问限定符间的影响C中的继承和访问控制总结父类的private成员在子类中的访问限制protected成员的使用场景成员访问方式总结继承方式的默认值实际应用中的继承方式 示例代码 OOP中类之间的关系“is a” …...

汇昌联信科技做拼多多电商怎么引流?
在互联网经济高速发展的今天,电商平台如雨后春笋般涌现,其中拼多多以其独特的社交电商模式迅速崛起。对于汇昌联信科技而言,如何在拼多多平台上有效引流,成为提升销量和品牌知名度的关键。本文将深入探讨汇昌联信科技在拼多多电商…...

公网ip和私网ip的区别
1.接入方式不同\n公网IP以公网连接Internet上的非保留地址,私网IP则是局域网上的IP,通过NAT才能够与公网进行通信。 2.特点不同\n公网IP由国际互联网络信息中心InterNIC负责,将IP地址分配给注册并向InterNIC提出申请的机构或组织。私网IP则是为节省可分…...

【开发踩坑】windows查看jvm gc信息
windows查看jvm gc信息 EZ 找出java进程PID 控制面板----搜索任务管理器---- 任务管理器----搜索 java----详细信息 这里PID是4856 cmd jstat gc面板 reference: jstat命令...

时间序列预测 | CEEMDAN+CNN+Transformer多变量时间序列预测(Python)
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 时间序列预测 | CEEMDANCNNTransformer多变量时间序列预测(Python) 时间序列预测 创新点 多尺度特征提取:CEEMDAN将复杂的时间序列分解成多个IMFs,使得CNN和Transforme…...

vue3--实现vue2插件JSONPathPicker的路径获取功能
背景 最近在进行vue2项目升级为vue3。 在项目中需要获取json某些字段的路径,vue2中使用JSONPathPicker ,但是该插件不支持vue3,vue3中也没有相应的模块有该功能。 实现目标: 原vue2中JSONPathPicker实现的功能: 查…...

SuccBI+低代码文档中心 — 可视化分析(仪表板)(上)
有关仪表板的设计器: 查询设置 由于仪表板的设计器是所见即所得的,可以将当前制作的内容和数据的查询结果实时展示在界面中,当引入到仪表板的模型数据量较大时,为了提高设计器界面的查询性能,提供了以下两种方法&…...

P3156 【深基15.例1】询问学号
昨天我发布了关于数据结构线性表的学习知识(【数据结构】顺序表-CSDN博客)。所谓“纸上得来终觉浅”,光看不练可不行,下面我们来看一下顺序表的习题。 题目链接 【深基15.例1】询问学号 - 洛谷 题目解读 题目描述了一个场景&…...

详解Xilinx FPGA高速串行收发器GTX/GTP(5)--详解8B10B编解码
目录 1、8B/10B编码是什么? 2、8B/10B编码的规则 3、两个例子 4、GTX的8B/10B编码 5、Verilog实现 文章总目录点这里:《FPGA接口与协议》专栏的说明与导航 1、8B/10B编码是什么? 简单来说,8B/10B编码就是将原本是8bits的数据,按照一定的规则扩展编码到10b…...

python 画多盘的写放大曲线方法
在服务器测试中我们经常会遇见客户要求画出每个SSD的WAF曲线,也就是写放大,通常的做法就是我们每隔10分钟记录一下每个SSD的host写入量和nand写入量,下面我们介绍一下python处理多盘的WAF的做法 如图所示 假设这是一个记录多盘的写入量信息的…...

计算机网络TCP/UDP知识点
这是一些在学习过程中关于计算机网络八股文的一些知识点记录: TCP/UDP TCP怎么保证可靠性 1.序列号,确认应答,超时重传 数据到达接收方,接收方需要发出一个确认应答,表示已经收到该数据段,并且确认序号…...