Android P 缩短screencap时间

前情提要

在Android P 系统上使用screencap截一张图片需要3s,为了加快截图时间,决定修改screencap保存的图片格式

方法:修改screencap保存的图片格式为JPEG

screencap源码路径:/frameworks/base/cmds/screencap/screencap.cpp
源码中screencap只能保存成png格式 或者在stdout中打印出来


int main(int argc, char** argv)
{
    ...
    // 保存成png格式
    if (png) {
        const SkImageInfo info =
            SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d));
        SkPixmap pixmap(info, base, s * bytesPerPixel(f));
        struct FDWStream final : public SkWStream {
          size_t fBytesWritten = 0;
          int fFd;
          FDWStream(int f) : fFd(f) {}
          size_t bytesWritten() const override { return fBytesWritten; }
          bool write(const void* buffer, size_t size) override {
            fBytesWritten += size;
            return size == 0 || ::write(fFd, buffer, size) > 0;
          }
        } fdStream(fd);
        (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100);
        if (fn != NULL) {
            notifyMediaScanner(fn);
        }
    } else { // 在stdout打印出来
        uint32_t c = dataSpaceToInt(d);
        write(fd, &w, 4);
        write(fd, &h, 4);
        write(fd, &f, 4);
        write(fd, &c, 4);
        size_t Bpp = bytesPerPixel(f);
        for (size_t y=0 ; y<h ; y++) {
            write(fd, base, w*Bpp);
            base = (void *)((char *)base + s*Bpp);
        }
    }
    close(fd);
    if (mapbase != MAP_FAILED) {
        munmap((void *)mapbase, mapsize);
    }

    // b/36066697: Avoid running static destructors.
    _exit(0);
  }

增加图片保存格式为JPEG


int main(int argc, char** argv)
{
    
    const char* pname = argv[0];
    bool png = false;
    bool jpg = false; // 增加JPG格式
    int32_t displayId = DEFAULT_DISPLAY_ID;
    int c;
    while ((c = getopt(argc, argv, "pjhd:")) != -1) {
        switch (c) {
            case 'p':
                png = true;
                break;
            case 'j':
                jpg = true;
                break;
            case 'd':
                displayId = atoi(optarg);
                break;
            case '?':
            case 'h':
                usage(pname);
                return 1;
        }
    }
   ...
    // 保存成png格式
    if (png) {
    ... 
     } else if(jpg) { // 增加JPEG格式
        const SkImageInfo info =
             SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d));
         SkPixmap pixmap(info, base, s * bytesPerPixel(f));
         struct FDWStream final : public SkWStream {
           size_t fBytesWritten = 0;
           int fFd;
           FDWStream(int f) : fFd(f) {}
           size_t bytesWritten() const override { return fBytesWritten; }
           bool write(const void* buffer, size_t size) override {
             fBytesWritten += size;
             return size == 0 || ::write(fFd, buffer, size) > 0;
           }
         } fdStream(fd);
         // 和上面png代码基本相同,不同点就在SkEncodedImageFormat::kJPEG
         (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kJPEG, 100);
         if (fn != NULL) {
             notifyMediaScanner(fn);
         }
     }
  • 编译: make screencap -j4
  • 拷贝编译出来的out/target/product/XXX/system/bin/screencap到设备的system/bin/screencap
  • 使用: $adb shell screencap -j sdcard/screen.jpg

解析

screencap 使用skia库来绘图
官网地址: https://skia.org/user/api/SkPixmap_Reference

其他方法

降低设备分辨率和像素密度可以加速截图

具体步骤:
查看设备分辨率
$ adb shell wm size
修改设备分辨率
$ adb shell wm size 1920dpx1080dp
重置分辨率
$ adb shell wm size reset

查看到像素密度是160

$ adb shell wm density
Physical density: 160

如果分辨率相应缩小1倍后,像素密度应该同样缩小一倍,为80

$ adb shell wm density 80
# wm -h
Window manager (window) commands:
  help
      Print this help text.
  size [reset|WxH|WdpxHdp]
    Return or override display size.
    width and height in pixels unless suffixed with 'dp'.
  density [reset|DENSITY]
    Return or override display density.
  overscan [reset|LEFT,TOP,RIGHT,BOTTOM]
    Set overscan area for display.
  scaling [off|auto]
    Set display scaling mode.
  dismiss-keyguard
    Dismiss the keyguard, prompting user for auth if necessary.
  tracing (start | stop)
    Start or stop window tracing.

也可以把属性写死在/system/build.prop

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章