从原始帧缓冲数据获取jpg图像

WSS*_*WSS 3 java android framebuffer

我能够得到android framebuffer.But我不知道如何将这些原始字节转换为jpg图像文件.如果我尝试使用java bufferedImage.setpixel方法在我的笔记本电脑上绘制图像.我得到不正确的彩色图像

Process sh = Runtime.getRuntime().exec("su", null,null);    
OutputStream  os = sh.getOutputStream();
os.write("/system/bin/cat /dev/graphics/fb0 > /sdcard/img.raw".getBytes());
os.flush();          
os.close();
sh.waitFor();`
Run Code Online (Sandbox Code Playgroud)

JSc*_*Ced 6

在android上,帧缓冲区中有2个或更多缓冲的图像.因此,当您复制上面的fb0文件时,其中至少有2个屏幕图像.您可以通过执行以下操作来拆分它们:

dd if=/sdcard/img.raw bs=<width_of_your_screen> \
   count=<height_of_your_screen> of=/sdcard/img-1.raw
dd if=/sdcard/img.raw bs=<width_of_your_screen> \
   count=<times height_of_your_screen> skip=<previous count> of=/sdcard/img-2.raw
Run Code Online (Sandbox Code Playgroud)

因此,例如,如果您的设备是480x320,并且像素编码为4个字节,则可以通过以下方式提取2个连续帧:

dd if=/sdcard/img.raw bs=1920 count=320 of=/sdcard/img-1.raw
dd if=/sdcard/img.raw bs=1920 count=320 skip=320 of=/sdcard/img-2.raw
Run Code Online (Sandbox Code Playgroud)

如果fb0帧缓冲区中有3个图像:

dd if=/sdcard/img.raw bs=1920 count=320 skip=640 of=/sdcard/img-3.raw
Run Code Online (Sandbox Code Playgroud)

哪里:

  • dd 是一个linux实用程序,用于复制和转换带有参数的原始文件:

    • if 用于'输入文件'
    • of 用于'输出文件'
    • bs是'块大小'.在示例480x4 = 1920(480像素高,每像素4个字节)
    • count是计算要读取if和写入的"块大小"的数量of(即这里我们读取/写入宽度大小)
    • skip对于第二张图片是要跳过的'块大小'的nb(即跳过count第一张图像的nb )

您可以通过将块大小设置为480x320x4 = 614400和count = 1来使用更简单的命令,但是如果您需要动态支持不同的屏幕大小,我发现拆分bs和计数在我的示例中更容易使用参数进行编程.

另请注意,如果从设备shell运行上述操作,则设备可能没有该dd命令.如果您安装了busybox,则可以替换ddbusybox dd

图像根据RGB32,BGR32,...像素格式的设备进行编码.你需要对它们进行重新编码才能获得JPG或PNG ...有些例子可以在Stackoverflow上使用ffmpeg找到.一个简单的例子是(对于RGB32设备,屏幕为640x320的屏幕):

ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 480x320 -i img-1.raw -f image2 -vcodec mjpeg img-1.jpg
Run Code Online (Sandbox Code Playgroud)

如果你使用ffmpeg,还有stackoverflow上的帖子指出如何为android构建它(即/sf/answers/677686201/)