Android 三星 Galaxy S4 自定义相机预览失真

Posted

技术标签:

【中文标题】Android 三星 Galaxy S4 自定义相机预览失真【英文标题】:Android Samsung Galaxy S4 Custom Camera Preview Distorted 【发布时间】:2015-11-22 19:51:25 【问题描述】:

我在使用 target sdk 22 构建的应用中使用自定义相机。我已经通过我的应用在许多设备上测试了相机,包括三星 S5、三星 Note 4 和华为升华伴侣 7,图像预览很好。

但是当我在三星 Galaxy S4 (android 5.0.1) 中通过我的应用程序打开相机时,我的相机预览会失真。以下是预览图:

我在 *** 上看到过很多帖子,但它们都是关于捕获图像之后的,而我的问题是在捕获图片之前。

以下是我用于预览的代码:

    surfaceChanged 方法

         public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
            try 
             holder.addCallback(this);
                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
                Camera.Parameters parameters = camera.getParameters();
                try 
                List<Camera.Size> supportedSizes = null;
                supportedSizes = Compatibility.getSupportedPreviewSizes(parameters);
    
                //preview form factor
                float ff = (float)w/h;
                Log.d("", "Screen res: w:"+ w + " h:" + h + " aspect ratio:" + ff);
    
                //holder for the best form factor and size
                float bff = 0;
                int bestw = 0;
                int besth = 0;
                Iterator<Camera.Size> itr = supportedSizes.iterator();
    
                while(itr.hasNext()) 
                    Camera.Size element = itr.next();
                    //current form factor
                    float cff = (float)element.width/element.height;
    
                    Log.d("Camera", "Candidate camera element: w:"+ element.width + " h:" + element.height + " aspect ratio:" + cff);
                    int currentRes = element.width*element.height;
                    //ff = Asp ratio of current Screen
                    // cff =  Asp ratio of current Size from Size list
                    // bff =  Asp ratio of current best aspect ratio selected
                    if ((Math.abs(ff-cff) <= Math.abs(ff-bff) ) ) 
                          bff=cff;
                          bestw = element.width;
                          besth = element.height;
                         
                 
    
                Log.d("Camera", "Chosen camera element: w:"+ bestw + " h:" + besth + " aspect ratio:" + bff);
                if ((bestw == 0) || (besth == 0))
                    Log.d("Camera", "Using default camera parameters!");
                    bestw = 480;
                    besth = 320;
                    Log.d("Camera","Using default camera parameters! aspect ratio "+480/320);
                
                parameters.setPreviewSize(bestw, besth);
    
                //Handling camera angle
                switch(this.getWindowManager().getDefaultDisplay().getRotation())
                case 0:
                    camera.setDisplayOrientation(90);
                    break;
                case 1:
                    camera.setDisplayOrientation(0);
                    break;
                case 2:
                case 3:
                    camera.setDisplayOrientation(180);
                    break;
                
    
             catch (Exception ex) 
                parameters.setPreviewSize(480 , 320);
            
    
            camera.setParameters(parameters);
            camera.startPreview();
         catch (Exception ex) 
            ex.printStackTrace();
        
    
    

    Compatibility.getSupportedPreviewSizes(parameters) 方法

     @SuppressWarnings("unchecked")
     public static List<Camera.Size> getSupportedPreviewSizes(Camera.Parameters params) 
    List<Camera.Size> retList = null;
    
    try 
        Object retObj = mParameters_getSupportedPreviewSizes.invoke(params);
        if (retObj != null) 
            retList = (List<Camera.Size>)retObj;
        
    
    catch (InvocationTargetException ite) 
        /* unpack original exception when possible */
        Throwable cause = ite.getCause();
        if (cause instanceof RuntimeException) 
            throw (RuntimeException) cause;
         else if (cause instanceof Error) 
            throw (Error) cause;
         else 
            /* unexpected checked exception; wrap and re-throw */
            throw new RuntimeException(ite);
        
     catch (IllegalAccessException ie) 
        //System.err.println("unexpected " + ie);
    
    return retList;
    
    

我将不胜感激。

提前致谢。

【问题讨论】:

你选择了哪种预览尺寸? 预览尺寸为 480 x 320 你的意思是,它回退到 480x320,因为没有一个支持的尺寸不够好?问题是,据我所知,S4 不支持此分辨率。使用不受支持的分辨率的结果是不可预测的。 是的,回退到480 * 320。那么解决办法是什么? 没有支持的预览大小符合您的标准。但是使用不受支持的尺寸是不行的。所以,你应该放宽你的标准,并检查solutions,当屏幕和相机尺寸不完全适合时修复纵横比。 【参考方案1】:

在三星 Note IV 上,我意识到您不应该使用 setPreviewSize(),即使您从 getSupportedPreviewSizes() 获得的尺寸应该是合法且可用的。

这是三星低级相机软件中的一个尴尬错误。不酷,三星!它只能在某些设备上重现。

然而,仍然拍摄是无可挑剔的。 所以,这是我的代码:

    Camera.Parameters parameters = camera.getParameters();

    boolean currentPreviewSettingsAreValid = parameters != null;
    currentPreviewSettingsAreValid = currentPreviewSettingsAreValid && parameters.getPreviewSize() != null;
    currentPreviewSettingsAreValid = currentPreviewSettingsAreValid && parameters.getPreviewSize().width > 0 && parameters.getPreviewSize().height > 0;

    if (parameters != null && !currentPreviewSettingsAreValid) 
        Camera.Size bestSize = getBestSizeOfSupported(parameters.getSupportedPreviewSizes(), width, height);

        if (bestSize != null) 
            parameters.setPreviewSize(bestSize.width, bestSize.height);
        
    

希望对大家有帮助

【讨论】:

你能把这个相机代码再开源一点吗?

以上是关于Android 三星 Galaxy S4 自定义相机预览失真的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 远程调试三星 Galaxy s4

三星 Galaxy S4 上的 dash.js

Android Galaxy S4 -- 在锁定屏幕上可见的活动

Eclipse Kepler 不允许在三星 Galaxy S4 上进行调试

尝试使用媒体查询定位 Moto G 和三星 Galaxy S4

Samsung Galaxy Camera Android API - 自定义相机应用程序