Android相机预览人像比例

Posted

技术标签:

【中文标题】Android相机预览人像比例【英文标题】:Android camera preview portrait scale 【发布时间】:2013-01-11 19:18:28 【问题描述】:

请帮助正确配置 android 相机(在 HTC Desire 2.3.3 上测试),以便在旋转(纵向)模式下从相机预览。 预览必须占不到一半的屏幕,宽度必须等于设备宽度,并且比例必须根据相机纵横比动态设置。 我当前的代码:

public class CameraSurface extends SurfaceView implements SurfaceHolder.Callback 
…
public void surfaceCreated(SurfaceHolder holder) 
try 
    if (camera != null) 
                try 
                    camera.stopPreview();
                 catch (Exception ignore) 
                
                try 
                    camera.release();
                 catch (Exception ignore) 
                
                camera = null;
            

            camera = Camera.open();             
            camera.setPreviewDisplay(holder);
         catch (Exception ex) 
            try 
                if (camera != null) 
                    try 
                        camera.stopPreview();
                     catch (Exception ignore) 
                    
                    try 
                        camera.release();
                     catch (Exception ignore) 
                    
                    camera = null;
                
             catch (Exception ignore)     
            
        
    

    public void surfaceDestroyed(SurfaceHolder holder) 
        try 
            if (camera != null) 
                try 
                    camera.stopPreview();
                 catch (Exception ignore) 
                
                try 
                    camera.release();
                 catch (Exception ignore) 
                
                camera = null;
            
         catch (Exception ex) 
            ex.printStackTrace();
        
    


    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
        try 
            Camera.Parameters parameters = camera.getParameters();
            float bff = 0;
            try 
                List<Camera.Size> supportedSizes = null;

                //maximize supported resizes, TODO remove as hardcode
                w*=1.5;
                h*=1.5;

                // On older devices (<1.6) the following will fail
                // the camera will work nevertheless
                supportedSizes = Compatibility.getSupportedPreviewSizes(parameters);

                // preview form factor
                float ff = (float) w / h;
                Log.d("TAG", "Screen res: w:" + w + " h:" + h
                        + " aspect ratio:" + ff);

                // holder for the best form factor and size                 
                int bestw = 0;
                int besth = 0;
                Iterator<Camera.Size> itr = supportedSizes.iterator();

                // we look for the best preview size, it has to be the closest
                // to the
                // screen form factor

                while (itr.hasNext()) 
                    Camera.Size element = itr.next();
                    // current form factor
                    float cff = (float) element.width / element.height;
                    // check if the current element is a candidate to replace
                    // the best match so far
                    // current form factor should be closer to the bff
                    // preview width should be less than screen width
                    // preview width should be more than current bestw
                    // this combination will ensure that the highest resolution
                    // will win
                    Log.d("TAG", "Candidate camera element: w:"
                            + element.width + " h:" + element.height
                            + " aspect ratio:" + cff);
                    if ((ff - cff <= ff - bff) && (element.width <= w)
                            && (element.width >= bestw)) 
                        bff = cff;
                        bestw = element.width;
                        besth = element.height;
                    
                
                Log.d("TAG", "Chosen camera element: w:" + bestw + " h:"
                        + besth + " aspect ratio:" + bff);
                // Some Samsung phones will end up with bestw and besth = 0
                // because their minimum preview size is bigger then the screen
                // size.
                // In this case, we use the default values: 480x320
                if ((bestw == 0) || (besth == 0)) 
                    Log.d("Mixare", "Using default camera parameters!");
                    bestw = 480;
                    besth = 320;
                               
                parameters.setPreviewSize(bestw,besth);
             catch (Exception ex) 
                parameters.setPreviewSize(480,320);

                bff=1.5f;
            
            makeResizeForCameraAspect(bff);                     
            camera.setDisplayOrientation(90);//only Android 2.2 and later
            camera.setParameters(parameters);               
            camera.startPreview();
         catch (Exception ex) 
            Log.e(TAG,"",ex);
        
    

    private void makeResizeForCameraAspect(float cameraAspectRatio)
        LayoutParams layoutParams=this.getLayoutParams();
        int matchParentWidth=this.getWidth();           
        int newHeight=(int)(matchParentWidth/cameraAspectRatio);
        if(newHeight!=layoutParams.height)
            layoutParams.height=newHeight;
            layoutParams.width=matchParentWidth;    
            this.setLayoutParams(layoutParams);
            this.invalidate();
        
    

活动布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical" >  
    <org.mixare.CameraSurface
        android:id="@+id/camera_surface"
        android:layout_
        android:layout_
        android:layout_alignParentTop="true"

         />
    <!--CameraSurface layout_height will be changed during it's loading process -->
</RelativeLayout>

AndroidManifest 配置为纵向:

  <activity android:label="@string/app_name" android:name=".MixView" 
    android:screenOrientation="portrait"  
    android:launchMode="singleTop" >

实际图片:

- 设备旋转纵向

- 设备旋转景观

在相同的主题中找到:Android - Camera preview is sideways、Android camera rotate,但我的代码得到了相同的结果

在这里您可能会看到图像的错误比例。 如何以适当的比例显示旋转和缩放的相机预览?

部分代码取自 Mixare 开源项目,http://www.mixare.org/

【问题讨论】:

嗨,你好像遇到了和我一样的问题:***.com/questions/16727836/…。你设法解决了这个问题吗?谢谢朋友。 不幸的是我还没有找到任何合适的解决方案,所以只是让应用程序处于横向模式。 【参考方案1】:

我知道我来不及回答这个问题,但是可以通过将相机的显示方向设置为 90 度来解决这个问题,即在 SurfaceCreated 类的 SurfaceCreated 方法中的 camera.open() 之后添加以下行

camera.setDisplayOrientation(90);

希望这可以帮助其他遇到同样问题的人。

【讨论】:

以上是关于Android相机预览人像比例的主要内容,如果未能解决你的问题,请参考以下文章

如何在surfaceview中将Android相机更改为人像?

Android 自定义相机 Camera 预览变形拉伸问题

Android相机以人像模式保存图片

Android | 教你如何使用HwCameraKit接入相机人像模式

相机预览人像设置参数失败

在 iOS OpenCV 相机中将相机预览旋转到人像