就 Linux 上用 C语言 实现截图问题 解答过错(待续)

1.首先找到代码能实现截图:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <fcntl.h>
#include <malloc.h>
#include <linux/fb.h>
#include <jpeglib.h>
#include <jerror.h>
#include <errno.h>

extern int errno;

/*
	功能:		获取当前系统时间
	返回值:	指向时间字符串的开始位置
*/
static const char* getCurTime()					// 获取当前系统时间
{
	static char ret[30] = {0};
	time_t t;
	struct tm *tp;

	t = time(NULL);
	tp = localtime(&t);
	memset(ret, 0, sizeof(ret));
	sprintf(ret, "%02d%02d%02d_%02d%02d%02d", tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);
	
	return ret;
}

/*
	功能:		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;					// 目标缓冲区是RGB格式, 每个分量占1字节, 所以用uchar
	unsigned short int *pix565;				// 每像素信息占2字节, 所以用short类型

	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;
}

/*
	功能:			将ARGB1555格式的图片数据转换成RGB24的图片数据
	返回值:			0
	argb1555:[in]	源缓冲区地址, 指向存放argb1555数据的起始地址
	rgb24:	[out]	目标缓冲区地址, 指向存放rgb24数据的起始地址
	xres:			屏幕分辨率的宽度
	yres:			屏幕分辨率的高度
*/
int ARGB1555_to_RGB24(unsigned char *argb1555, unsigned char *rgb24, int xres, int yres)
{
	int i;
	int whole = xres * yres;
	unsigned char r, g, b;
	unsigned short int *pix1555;

	pix1555 = (unsigned short int *)argb1555;
	for(i = 0; i < whole; i++)
	{
	//	*pix1555 &= 0x7FFFFF;				// 透明分量置为0
		r = ((*pix1555) >> 10) & 0x1f;		// 取颜色分量: R
		*rgb24++ = (r << 3) | (r >> 2);
		g = ((*pix1555) >> 5) & 0x1f;		// 取分量: G
		*rgb24++ = (g << 3) | (g >> 2);
		b = (*pix1555) & 0x1f;				// 取分量: B
		*rgb24++ = (b << 3) | (b >> 2);
		pix1555++;
		
		if(rgb24[-3] == 0xFF && rgb24[-2] == 0 && rgb24[-1] == 0xFF)	// RGB = 0xFF00FF
			rgb24[-3] = 0;												// 修改RGB = 0x0000FF(将粉红色替换成蓝色)
	}
	return 0;
}

/*
	功能:	jpeg压缩函数
	返回值:	0: 成功, -1: 失败
	rgb:	指向存放rgb24数据的起始地址
	width:	屏幕(分辨率)的宽度
	height:	屏幕(分辨率)的高度
*/
int jpeg_compress(unsigned char *rgb, int width, int height)
{
	char outfile[100] = {0};
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	FILE * pf = NULL;
	JSAMPROW row_pointer[1];
	int row_stride;

	sprintf(outfile, "snap_%s.jpg", getCurTime());
	if ((pf = fopen(outfile, "wb")) == NULL)
	{
		printf("Can not create output file, please check!\n");
		return -1;
	}
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	
	jpeg_stdio_dest(&cinfo, pf);

	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;				// 1-灰度图,3-彩色图
	// 输入数据格式为RGB
	cinfo.in_color_space = JCS_RGB;			// JCS_GRAYSCALE-灰度图,JCS_RGB-彩色图

	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, 80, TRUE);		// 设置压缩质量:80
	jpeg_start_compress(&cinfo, TRUE);		// 开始压缩过程
	row_stride = width * 3;					// row_stride: 每一行的字节数

	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(pf);
	jpeg_destroy_compress(&cinfo);			// 释放资源

	return 0;
}

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;
	const char *dev = "/dev/fb0";

	// 打开framebuffer设备
	fd = open(dev, O_RDONLY);
	if(fd < 0)
	{
		printf("fd=%d, error=[%d: %s]\n", fd, errno, strerror(errno));
		return -1;
	}

	// 获取LCD的可变参数
	ioctl(fd, FBIOGET_VSCREENINFO, &fb_var_info);
	// 一个像素多少位
	printf("bits_per_pixel: %d\n", fb_var_info.bits_per_pixel);
	printf("分辨率: %d x %d\n", fb_var_info.xres, fb_var_info.yres);
	printf("颜色分量值: (A, R, G, B) = (%d, %d, %d, %d)bits\n", fb_var_info.transp.length, fb_var_info.red.length, fb_var_info.green.length, fb_var_info.blue.length);
	printf("颜色分量偏移: (A, R, G, B) = (%d, %d, %d, %d)\n", fb_var_info.transp.offset, fb_var_info.red.offset, fb_var_info.green.offset, fb_var_info.blue.offset);
	// 获取LCD的固定参数
	ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix_info);
	// 一帧大小
	printf("smem_len: %#X\n", fb_fix_info.smem_len);
	// 一行大小
	printf("line_length: %#X\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("read failed!\n");
		goto read_fail;
	}

	//	RGB565_to_RGB24(trgb, rgb, fb_var_info.xres, fb_var_info.yres);			// 将RGB565转换成RGB24格式
	ARGB1555_to_RGB24(trgb, rgb, fb_var_info.xres, fb_var_info.yres);		// 将ARGB1555转换成RGB24格式
	if(jpeg_compress(rgb, fb_var_info.xres, fb_var_info.yres) < 0)			// jpeg压缩失败
		printf("Jpeg compress failed!\n");

read_fail:
	free(rgb);
here:
	free(trgb);
	close(fd);

	return 0;
}

运行结果是 黑的 多:

2.为什么是 黑的 ?

查资料,说是:

利用framebuffer做出的这个截图工具,fb0里的内容截图出来的是字符界面,并不是Linux上的GUI界面。

使用C语言来做Linux的截图,标准C没有可用于此目的的库函数。标准C也不知道屏幕,不能用于特定于系统的调用;Linux核心是CLI,核心库里没有图形功能,Linux里用的gnome截图命令是用的GTK工具包,是属于第三方工具。

 

原文链接:Linux上如何不用第三方库实现截图!!(C/C++)-编程语言-CSDN问答

3.实现:

flameshot ----QT  

gnome ---- GTK

用 system()调用截图程序运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
//1.创建文件file1,写入字符串“abcdefghijklmn”; //2.创建文件file2,写入字符串“ABCDEFGHIJKLMN”; //3.读取file1中的内容,写入file2,使file2中的字符串内容为“abcdefghijklmn ABCDEFGHIJKLMN” 创建新文件,该文件具有用户读写权限。 //2.采用dup/dup2/fcntl复制一个新的文件描述符,通过新文件描述符向文件写入“class_name”字符串; //3.通过原有的文件描述符读取文件中的内容,并且打印显示; 1.输入文件名称,能够判断文件类型,判断实际用户对该文件具有哪些存取权限; ?2.要求打印出文件类型信息,inode节点编号,链接数目,用户id,组id,文件大小信息; ?3.修改文件的权限为当前用户读写,组内用户读写,组外用户无权限 新建文件,设置文件权限屏蔽字为0; 2.建立该文件的硬链接文件,打印硬链接文件的inode节点号和文件大小; ? 3.建立该文件的软链接文件,打印软链接文件的inode节点号和文件大小;打印软链接文件中的内容; 4.打印源文件的inode节点号,文件大小和链接数目; ? 5.调用unlink对源文件进行操作,打印源文件链接数目; .新建/home/user目录; 2.把当前工作路径移至/home/user目录; 3.打印当前工作路径; ?编写程序完成以下功能: ?1.递归遍历/home目录,打印出所有文件和子目录名称及节点号。 ?2.判断文件类型,如果是子目录,继续进行递归遍历,直到遍历完所有子目录为止
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值