第11讲 streamconfigurationmap实战一 -凯发k8手机登录

本讲是android camera专题系列的第11讲,我们介绍android camera2 api专题的streamconfigurationmap实战之如何获取预览size和拍照jpeg size。

更多资源:

资源 描述
在线课程
知识星球 星球名称:深入浅出android camera
星球id: 17296815
wechat 极客笔记圈

geekcamera2启动时序图

geekcamera2启动时序图

用streamconfigurationmap来做什么

在创建camera capture session前,会先通过streamconfigurationmap获取

  • camera支持的预览size列表
  • camera支持的拍照size列表
  • camera支持的录像size列表

获取预览size

预览组件

  • surfaceholder / surfacetexture / imagereader

需要考虑的因素

  • 屏幕size、拍照size
  • 一般提供三种宽高比:全屏、1:1、4:3

实战

  • geekcamera2 如何选择预览size

获取preview size list核心代码

private void doinitsupportedpreviewsizes(camerafeatures camera_features,
                                         streamconfigurationmap configs) throws cameracontrollerexception{
    android.util.size [] camera_preview_sizes = configs.getoutputsizes(surfacetexture.class);
    camera_features.msupportedpreviewsizes = new arraylist<>();
    point display_size = new point();
    activity activity = (activity)context;
    {
        display display = activity.getwindowmanager().getdefaultdisplay();
        display.getrealsize(display_size);
        // getrealsize() is adjusted based on the current rotation, so should already be landscape format, but it
        // would be good to not assume open camera runs in landscape mode (if we ever ran in portrait mode,
        // we'd still want display_size.x > display_size.y as preview resolutions also have width > height)
        if( display_size.x < display_size.y ) {
            //noinspection suspiciousnamecombination
            display_size.set(display_size.y, display_size.x);
        }
        if( mydebug.log )
            log.i(tag, "display_size: "   display_size.x   " x "   display_size.y);
    }
    if( camera_preview_sizes == null ) {
        // camera_preview_sizes is null on samsung galaxy note 10  and s20 for camera id 4!
        log.e(tag, "no preview sizes returned by getoutputsizes");
        throw new cameracontrollerexception();
    }
    else {
        for(android.util.size camera_size : camera_preview_sizes) {
            if( mydebug.log )
                log.i(tag, "preview size: "   camera_size.getwidth()   " x "   camera_size.getheight());
            if( camera_size.getwidth() > display_size.x || camera_size.getheight() > display_size.y ) {
                // nexus 6 returns these, even though not supported?! (get green corruption lines if we allow these)
                // google camera filters anything larger than height 1080, with a todo saying to use device's measurements
                continue;
            }
            camera_features.msupportedpreviewsizes.add(new cameracontroller.size(camera_size.getwidth(), camera_size.getheight()));
        }
    }
}

根据picture size获取preview size核心代码

public cameracontroller.size getoptimalpreviewsize(list sizes) {
    if( mydebug.log )
        log.d(tag, "getoptimalpreviewsize()");
    final double aspect_tolerance = 0.05;
    if( sizes == null )
        return null;
    if( is_video && video_high_speed ) {
        videoprofile profile = getvideoprofile();
        if( mydebug.log )
            log.d(tag, "video size: "   profile.videoframewidth   " x "   profile.videoframeheight);
        // preview size must match video resolution for high speed, see doc for cameradevice.createconstrainedhighspeedcapturesession()
        return new cameracontroller.size(profile.videoframewidth, profile.videoframeheight);
    }
    cameracontroller.size optimalsize = null;
    double mindiff = double.max_value;
    point display_size = new point();
    activity activity = (activity)this.getcontext();
    {
        display display = activity.getwindowmanager().getdefaultdisplay();
        display.getsize(display_size);
        // getsize() is adjusted based on the current rotation, so should already be landscape format, but:
        // (a) it would be good to not assume open camera runs in landscape mode (if we ever ran in portrait mode,
        // we'd still want display_size.x > display_size.y as preview resolutions also have width > height,
        // (b) on some devices (e.g., nokia 8), when coming back from the settings when device is held in preview,
        // display size is returned in portrait format! (to reproduce, enable "maximise preview size"; or if that's
        // already enabled, change the setting off and on.)
        if( display_size.x < display_size.y ) {
            //noinspection suspiciousnamecombination
            display_size.set(display_size.y, display_size.x);
        }
        if( mydebug.log )
            log.d(tag, "display_size: "   display_size.x   " x "   display_size.y);
    }
    double targetratio = calculatetargetratioforpreview(display_size);
    int targetheight = math.min(display_size.y, display_size.x);
    if( targetheight <= 0 ) {
        targetheight = display_size.y;
    }
    // try to find the size which matches the aspect ratio, and is closest match to display height
    for(cameracontroller.size size : sizes) {
        if( mydebug.log )
            log.d(tag, "    supported preview size: "   size.width   ", "   size.height);
        double ratio = (double)size.width / size.height;
        if( math.abs(ratio - targetratio) > aspect_tolerance )
            continue;
        if( math.abs(size.height - targetheight) < mindiff ) {
            optimalsize = size;
            mindiff = math.abs(size.height - targetheight);
        }
    }
    if( optimalsize == null ) {
        // can't find match for aspect ratio, so find closest one
        if( mydebug.log )
            log.d(tag, "no preview size matches the aspect ratio");
        optimalsize = getclosestsize(sizes, targetratio, null);
    }
    if( mydebug.log ) {
        log.d(tag, "chose optimalsize: "   optimalsize.width   " x "   optimalsize.height);
        log.d(tag, "optimalsize ratio: "   ((double)optimalsize.width / optimalsize.height));
    }
    return optimalsize;
}

获取拍照size

拍照组件

  • imagereader(jpeg)

需要考虑的点

  • support size list要考虑gethighresolutionoutputsizes
  • 拍照使用哪种format(jpeg,yuv_420_888,raw等)

  • 宽高比与预览size保持一致

实战

  • geekcamera2 如何选择拍照size

获取jpeg size list核心代码

private void doinitsupportedjpegsizes(camerafeatures camera_features,
                                      streamconfigurationmap configs) throws cameracontrollerexception {
    android.util.size [] camera_picture_sizes = configs.getoutputsizes(imageformat.jpeg);
    camera_features.msupportedpicturesizes = new arraylist<>();
    if( android.os.build.version.sdk_int >= android.os.build.version_codes.m ) {
        android.util.size [] camera_picture_sizes_hires = configs.gethighresolutionoutputsizes(imageformat.jpeg);
        if( camera_picture_sizes_hires != null ) {
            for(android.util.size camera_size_hr : camera_picture_sizes_hires) {
                if( mydebug.log )
                    log.i(tag, "high resolution picture size: "   camera_size_hr.getwidth()   " x "   camera_size_hr.getheight());
                // check not already listed? if it's listed in both, we'll add it later on when scanning camera_picture_sizes
                // (and we don't want to set supports_burst to false for such a resolution).
                boolean found = false;
                for(android.util.size sz : camera_picture_sizes) {
                    if( sz.equals(camera_size_hr) ) {
                        found = true;
                        break;
                    }
                }
                if( !found ) {
                    if( mydebug.log )
                        log.i(tag, "doinitsupportedjpegsizes high resolution [non-burst] picture size: "   camera_size_hr.getwidth()   " x "   camera_size_hr.getheight());
                    cameracontroller.size size = new cameracontroller.size(camera_size_hr.getwidth(),
                                                            camera_size_hr.getheight());
                    size.supports_burst = false;
                    camera_features.msupportedpicturesizes.add(size);
                }
            }
        }
    }
    if( camera_picture_sizes == null ) {
        // camera_picture_sizes is null on samsung galaxy note 10  and s20 for camera id 4!
        log.e(tag, "no picture sizes returned by getoutputsizes");
        throw new cameracontrollerexception();
    }
    else {
        for(android.util.size camera_size : camera_picture_sizes) {
            if( mydebug.log )
                log.i(tag, "doinitsupportedjpegsizes picture size: "   camera_size.getwidth()   " x "   camera_size.getheight());
            camera_features.msupportedpicturesizes.add(new cameracontroller.size(camera_size.getwidth(),
                                                        camera_size.getheight()));
        }
    }
    // sizes are usually already sorted from high to low, but sort just in case
    // note some devices do have sizes in a not fully sorted order (e.g., nokia 8)
    collections.sort(camera_features.msupportedpicturesizes, new cameracontroller.sizesorter());
    // test high resolution modes not supporting burst:
    //camera_features.picture_sizes.get(0).supports_burst = false;
}

camera课程

python教程

java教程

web教程

数据库教程

图形图像教程

办公软件教程

linux教程

计算机教程

大数据教程

开发工具教程

android camera2 api

网站地图