将相机预览适配到比显示器大的 SurfaceView [英] Fitting a camera preview to a SurfaceView larger than the display

查看:25
本文介绍了将相机预览适配到比显示器大的 SurfaceView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Android 应用程序,无论 getSupportedPreviewSizes() 给出的预览大小如何,它都需要全屏显示相机预览而不失真.我希望这会在高度或宽度上裁剪预览,但这与我无关.我之所以这样做是因为某些安卓相机(例如三星 Galaxy SII 前置摄像头)不会返回与显示器具有相同纵横比的任何预览,因此需要进行拉伸和剪裁.

I have an Android application that needs to fullscreen a camera preview regardless of the preview size given by getSupportedPreviewSizes() without distortion. I expect this to crop the preview by some amount in either the height or width, but this does not concern me. The reason I seek to do this is because certain android cameras (e.g. Samsung Galaxy SII front facing camera) do not return any previews with the same aspect ratio as the display, and therefore need to be stretched and clipped.

是否可以将相机预览完全扩展到大于显示尺寸的视图? 通过简单地设置表面视图的布局参数,可以将 SurfaceView 扩展到大于返回的预览像素尺寸match_parent,但这会导致某些方向的失真,并且只有在预览填满显示之前才有可能.这似乎表明在显示器外预览是不可能的,并且硬件(或操作系统)限制了这种行为.

Is it possible to fully grow the camera preview to a view larger than the display size? It is possible to grow the SurfaceView larger than the preview pixel dimensions returned by simply setting the surface view's layout params to match_parent, but this results in distortion in some direction and only is possible up until the preview fills the display. This seems to indicate that previewing outside of the display is impossible, and the hardware (or OS) limits such behavior.

还有另一个关于该主题的问题,但该问题声称无法创建大于屏幕尺寸的 SurfaceView,这是错误的,正如我在日志中发现的那样.然而,实际情况似乎是相机预览无法增长到巨大 SurfaceView 的全尺寸.

There is another question on the topic, but that question claims it is not possible to create a SurfaceView greater than the screen dimensions, which is false, as I have found with logging. However, what seems to be the case is that camera preview however cannot grow to the full size of an enormous SurfaceView.

我的尝试:

我有一个相对布局,其中有一个 FrameLayout,并在其中创建了一个 SurfaceView.整个相对布局的宽度设置为 635dp,大约是设备屏幕尺寸的两倍.FrameLayout 与此大小匹配,SurfaceView 也是如此(稍后以编程方式添加)

I have a relative layout, within it a FrameLayout, and within that I create a SurfaceView. The width of the entire relative layout is set below at 635dp, which is ~double the device's screen size. The FrameLayout matches this sizing and so does the SurfaceView (added programmatically later)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/camera_activity_layout"
    android:layout_width="635dp"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

</RelativeLayout>

以下是获取和设置预览尺寸的代码.在这里,我想让相机预览扩展以填充整个 FrameLayout(屏幕宽度的两倍).视图完全正常显示和破坏,所以我删除了与这个特定问题无关的代码,因为它分散了对基本问题的注意力,我试图轻松简单地将视图扩大到大于显示的大小.

The following is the code that gets and sets preview size. Here I want to make the camera preview expand to fill the entire FrameLayout (double the screen width). The view shows up and destructs totally normally so I am removing code not related to this particular question because it distracts from the essential question, and my attempt to easily and simply grow the view to some larger-than-display size.

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    ...

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Camera.Parameters parameters = mCamera.getParameters();
        final DisplayMetrics dm = this.getResources().getDisplayMetrics();
            //getBestPreviewSize returns the best preview size, don't worry
            //but some devices do not return one for all camera matching the aspect ratio
        cameraSize = getBestPreviewSize(parameters, dm.heightPixels, dm.widthPixels);

        if (cameraSize!=null) {
            parameters.setPreviewSize(cameraSize.width, cameraSize.height);
            mCamera.setParameters(parameters);
        }

        FrameLayout.LayoutParams frameParams = (FrameLayout.LayoutParams) this.getLayoutParams();

        frameParams.width = 800; //For argument's sake making this ~double the width of the display. Same result occurs if I use MATCH_PARENT
        frameParams.height = LayoutParams.MATCH_PARENT;
        this.setLayoutParams(frameParams);

        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

            Log.d("surfChange","W/H of CamPreview (child) is "+this.getWidth()+"/"+this.getHeight()+" while parent is ");
            Log.d("surfChange","W/H of holder (child) is "+mHolder.getSurfaceFrame().width()+"/"+mHolder.getSurfaceFrame().height()+" while parent is ");
        } catch (Exception e){
        }
    }
};

我担心在这项工作中取得成功的唯一方法是以某种方式渲染到 openGL 表面,但是这 显然 全彩色可能太慢了.如果只能简单地拉伸和剪切相机预览,那也很痛苦.

I am concerned that the only way to succeed in this endeavor is to somehow render to an openGL surface, but this apparently might be too slow in full color. It is also a pain if the camera preview can simply be stretched and clipped.

预先感谢对解决方案的任何尝试.

Thanks in advance to any attempts at the solution.

推荐答案

好的,我知道这是一个很晚的答案,但它是可能的.下面是来自 Android SDK 示例的代码.要查看实现此操作的其余代码,请下载 android sdk 示例并转到 Samples/android-10(我使用过的一个,可以尝试任何您想要的目标)/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java

Ok, I know this is very late as an answer but it is possible. Below is code from the Android SDK sample. To see the rest of the code to implement this download the android sdk samples and go to Samples/android-10(one I used, could try whichever you want to target)/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java

class PreviewSurface extends ViewGroup implements SurfaceHolder.Callback {
...
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    if (changed && getChildCount() > 0) {
        final View child = getChildAt(0);

        final int width = r - l;
        final int height = b - t;

        int previewWidth = width;
        int previewHeight = height;
        if (mPreviewSize != null) {
            previewWidth = mPreviewSize.width;
            previewHeight = mPreviewSize.height;
        }

        // Center the child SurfaceView within the parent.
        if (width * previewHeight > height * previewWidth) {
            final int scaledChildWidth = previewWidth * height / previewHeight;
            child.layout((width - scaledChildWidth) / 2, 0,
                    (width + scaledChildWidth) / 2, height);
        } else {
            final int scaledChildHeight = previewHeight * width / previewWidth;
            child.layout(0, (height - scaledChildHeight) / 2,
                    width, (height + scaledChildHeight) / 2);
        }
    }
}
}

此代码旨在使预览适合最小维度(不会弄乱纵横比)并居中以在另一个维度上显示黑条.但是,如果您将 > 翻转为 < 而不是您将实现您想要的.例如:

this code is intended to fit the preview to the smallest dimension (that doesn't mess up the aspcect ratio) and center to have black bars on the other dimension. But if you flip the > to be < instead you will achieve what you want. Ex:

if (width * previewHeight < height * previewWidth) {...

这篇关于将相机预览适配到比显示器大的 SurfaceView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆