您的位置:首页 > 编程语言 > C语言/C++

安卓ADB工具系列——快速截屏并直接保存在windows上

2018-02-15 15:27 204 查看
前言

本文旨在windows操作系统下,利用ADB工具,直接将截图存放到电脑磁盘中,降低手机负担,提高截图效率。

ADB截图命令在下面这篇文章中有介绍

http://blog.csdn.net/wirelessqa/article/details/29187339

截图命令分为两种,第一种是先截图保存到安卓手机的SD卡中,然后再上传到电脑上,最后再删除SD卡中的截图。第二种是直接将截图保存到电脑上。

由于第一种方法需要对手机进行写-读-写操作,对电脑进行写操作,而第二种方法只需要对电脑写操作,大大减少了对手机的操作,对需要频繁截屏的场景十分奏效。

ADB直接截图并保存到电脑的命令是

adb shell screencap -p >screenshot.png


上述指令将截图数据重定向到当前文件夹下名为screenshot的png文件。然而,在windows操作系统下,回车符是\r\n,在Linux操作系统下,回车符是\n。安卓系统是基于Linux内核开发而来的,所以在安卓系统中回车符也是\n,这样就会出现一个问题,在安卓系统中截图得到的二进制数据流中,如果出现\n,Windows会将\n解析成\r\n,所以截图命令得到的png文件不能正常打开。要使得在Windows系统中能对截图得到的png文件进行操作,需要将png文件中数据部分的\r\n转换成\n,这样就能够得到正确的文件。

png文件结构在下面这篇文章中有介绍

http://blog.csdn.net/bisword/article/details/2777121

对于一个png文件来说,其文件头由固定8个字节来描述的,其十六进制数为:89 50 4E 47 0D 0A 1A 0A,其中0D代表\r,0A代表\n。上面说过Windows会将\n转化成\r\n,为了验证上面的介绍,这里使用Notepad++,利用HEX-Editor插件以十六进制显示重定向后的文件screenshot.png,其结果如下图所示。



可以看出,png的文件头中的0A在Windows中确实被解析成了0D0A,我们接下来需要做的便是将所有的0D0A替换成0A。假设原文件是a.png,需要得到的正确文件是b.png。替换的思路是:

创建一个大小为N字节的缓冲区1和大小为N个字节的缓冲区2,缓冲区1用于缓存读取的文件数据流,缓冲区2用于缓存写入的文件数据流。

从文件a.png读取N个字符并存入缓冲区1,从缓冲区的第0个位置开始到第N-2个位置,逐个判断当前字符和下一个字符是否是\r\n,如果不是,则将当前字符存入缓冲区2中,否则不进行任何操作。完成后将缓冲区2中的数据写入到b.png中。由于缓冲区1中第N-1个字符后面没有有效的字符,不能进行判断,所将第N-1个字符存放到临时变量1中留到下一步中判断。

再从文件读取N个字符并存入缓冲区1,先判断临时变量1和缓冲区1的第0个字符是否是\r\n,如果不是,则将临时变量1追加写入到b.png中,否则不进行任何操作。然后和步骤2类似,从缓冲区1的第0个字符开始到第N-2个字符,逐个判断当前字符和下一个字符是\r\n,如果不是则将当前字符存入缓冲区2中,否则不进行任何操作。完成后将缓冲区2中的数据写入到b.png中。

循环执行步骤2,直到读取到文件结尾EOF。

由于最后一步中缓冲区中最后一个字符没有用到,所以将上一步中的最后一个字符追加写入到b.png中。

关闭文件a.png和文件b.png。

注意:如果最后一次读取到的字符数目不是N,则以实际读取到的字符数目M为准,从第0个字符到第M-2个字符开始遍历。

上述算法的C语言实现如下,其中变量srcPngPath和destPngPath分别代表原文件和待写入的目的文件的路径。

int convertPng(const char* srcPngPath, const char* destPngPath)
{
//原文件和目的文件指针
FILE *fp1, *fp2;
int i, count;
//实际读取的字符数目
int num;
//png文件头的等效表示
long long head = 0x0a1a0a0d474e5089;
//读取和写入文件缓冲区,临时变量
char text[1024], text2[1024], tmpchar;

if (!(fp1 = fopen(srcPngPath, "rb")))
{
return -1;//原文件打开失败
}
fp2 = fopen(destPngPath, "wb");

fread(text, sizeof(char), 1024, fp1);
count = 0;
for (i = 0; i < 1023; i++)
{
if (!(text[i] == '\r' && text[i + 1] == '\n'))
text2[count++] = text[i];
}
fwrite(text2, sizeof(char), count, fp2);
tmpchar = text[1023];

while (num = fread(text, sizeof(char), 1024, fp1))
{
count = 0;
if (!(tmpchar == '\r' && text[0] == '\n'))
fputc(tmpchar, fp2);

for (i = 0; i < num - 1; i++)
{
if (!(text[i] == '\r' && text[i + 1] == '\n'))
text2[count++] = text[i];
}
fwrite(text2, sizeof(char), count, fp2);
tmpchar = text[num - 1];
}
fputc(text[num - 1], fp2);

fclose(fp1);
fclose(fp2);

return 0;
}


在我的2.8GHz主频的电脑上转换一个大小为12.1KB的png文件耗时约为1ms。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ADB C语言 png