Android自定义相机缩放后卡顿

24

我有一个自定义相机,在一些设备上运行良好。它在三星Galaxy Gran Duos(三星GT i9082,Android 4.2.2)上运行良好,但是当我尝试拍摄之前放大的图像时,它会冻结,不会崩溃,唯一的退出方式是按下返回按钮。这只发生在三星Galaxy Gran Duos上。

我用来拍照的代码:

    Camera.PictureCallback photoCallback = new Camera.PictureCallback() {

    public void onPictureTaken(byte[] data, Camera camera) {

        try {

        } catch (Exception e) {
            if (flePicture== null){
                Log.d("camera", "Error creating media file, check storage permissions: " +
                        e.getMessage());
                return;
            }
        }

        try {
            FileOutputStream fos = new FileOutputStream(flePicture);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d("camera", "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d("camera", "Error accessing file: " + e.getMessage());
        } 
    }
};

放大所使用的代码:

private void zoomIn() {
    if (pblnInPreview) {
        Camera.Parameters parameters = camCamera.getParameters();

        if ((parameters.getZoom() + 1) < parameters.getMaxZoom()) {
            parameters.setZoom(parameters.getZoom() + 1);
            camCamera.setParameters(parameters);
        }
    }
}

日志记录:

04-07 17:21:14.386: E/BrcmCamera(130): processControlBuffer: Corrupt stream error raised by camera - sensor communication failure

在所有分辨率下拍照是否会出现错误?在受影响的设备上以较低的分辨率拍照是否可接受? - samgak
@samgak:是的,这在所有分辨率下都会发生。低分辨率没有问题,我已经在使用了!谢谢。 - Tiago GP
你在设置参数后尝试启动预览了吗? - Cynapsis
4个回答

1
我认为您需要使用camera.isZoomSupported()来确认您的相机是否支持变焦,如果支持,您需要使用camera.cancelAutoFocus()取消自动对焦以防止图像失真。 但是,这仅在您的设备实际支持变焦时才有效。如果不支持,则需要先捕获整个图像,然后使用Bitmap.createBitmap缩放所需部分。

0
这不是非常相关的答案。我知道。
但是我想说的是,三星4.2.2存在许多缺陷问题。 它有ClipboardManager崩溃、ActionBar AppCompat崩溃等问题。
只需使用简单的if语句对其进行过滤并挽救您的生命。
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1 && Build.MANUFACTURER.toUpperCase().contains("SAMSUNG")){
    // ignore
}else{
    // your logic on the go
}

这不是问题的目的。我们需要看到解决问题的方案,而不需要深入研究问题的根源。虽然今天已经有了这样的解决方法来防止错误发生,但对我们来说并不理想。 - Julio Borges
@JulioBorges // 你为什么不认为这个模型可能有缺陷的相机驱动程序或在固件中丢失了一些包?三星4.2.2确实存在问题。 - Youngjae
@Youngjae:三星有它的细节,你说的没错,但“if”子句只是避免问题。我之前在这里发布过...无论如何还是谢谢! - Tiago GP

0
你是否在拍完照后重新开始相机预览?
加入这行代码:camera.startPreview(); 试一下。
     Camera.PictureCallback photoCallback = new Camera.PictureCallback() {

    public void onPictureTaken(byte[] data, Camera camera) {
           camera.startPreview();
        try {

        } catch (Exception e) {
            if (flePicture== null){
                Log.d("camera", "Error creating media file, check storage permissions: " +
                        e.getMessage());
                return;
            }
        }

        try {
            FileOutputStream fos = new FileOutputStream(flePicture);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d("camera", "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d("camera", "Error accessing file: " + e.getMessage());
        } 
    }
};

首先感谢您!我尝试了那个方法,但是没有起作用。照片可以正常拍摄,但当我尝试应用缩放时,屏幕会冻结,没有图片被捕获,最大的问题是应用程序仍然在运行,LogCat中没有显示任何内容。 - Tiago GP

0

这是某种特定内核类型的问题。

尝试这种方法。

private static final String TAG = Test.class.getSimpleName();

private boolean isPreviewStarted;
private Camera camera;

Camera.PictureCallback photoCallback = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {

        // check if this needs to stop the preview
        if (deviceNeedsStopPreviewToShoot()) {
            stopPreview();
        }

        // save your image

        // restart preview if needed.
        startPreview();

    }
};

public void startPreview() {
    if (!isPreviewStarted && camera != null) {
        camera.startPreview();
        isPreviewStarted = true;
    }
}

public void stopPreview() {
    if (isPreviewStarted && camera != null) {
        camera.stopPreview();
        isPreviewStarted = false;
    }
}

public static boolean deviceNeedsStopPreviewToShoot() {
    String[] oldDevices = {"smdk4210", "aries"};
    boolean needs = Arrays.asList(oldDevices).contains(Build.BOARD);
    Log.e(TAG, "Device " + Build.BOARD + (needs ? " needs " : " doesn't need ") + "to stop preview");
    return needs;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接