相机焦距

发布于 2024-11-15 21:44:10 字数 10116 浏览 3 评论 0原文

我正在尝试从 Android 相机读取焦距(照片中拍摄对象的距离)。即使 HTC Desire 正确自动对焦,我的所有焦距始终为 0。这是整个应用程序,仅适用于 v2.3.3 及更高版本。

ImageCapture.java

package test.test;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;

import android.app.Activity;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

//THIS CLASS READS THE FOCUS DISTANCES
class ImageFocusCallback implements AutoFocusCallback {
    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        //READ FOCUS DISTANCES HERE
        Camera.Parameters parameters = camera.getParameters();
        float[] distances = new float[3];
        if (success) {
            // Only available with Android 9 (2.3)
            // Focus Mode is always reported as auto but
            // distances do not appear to be updating
            // always: 0.1, 1.2, Infinity, (on my device it's 0,0,0)
            Log.d("Focus Mode: ", parameters.getFocusMode());
            parameters.getFocusDistances(distances);
            Log.d("focus distance near", Float.toString(distances[0]));
            Log.d("focus distance optimum", Float.toString(distances[1]));
            Log.d("focus distance far", Float.toString(distances[2]));
        }
    }
}

public class ImageCapture extends Activity implements SurfaceHolder.Callback {
    //CALL AUTO FOCUS HERE
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            ImageFocusCallback autoFocusCallBack = new ImageFocusCallback();
            //AUTOFOCUS IS CALLED HERE
            camera.autoFocus(autoFocusCallBack);
            return true;
        }
        return false;
    }

    //REST OF THE CODE
    private Camera           camera;
    private boolean          isPreviewRunning = false;
    private SimpleDateFormat timeStampFormat  = new SimpleDateFormat("yyyyMMddHHmmssSS");

    private SurfaceView      surfaceView;
    private SurfaceHolder    surfaceHolder;
    private Uri              target           = Media.EXTERNAL_CONTENT_URI;


    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        Log.e(getClass().getSimpleName(), "onCreate");
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        setContentView(R.layout.main);
        surfaceView = (SurfaceView) findViewById(R.id.surface);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

    @Override
    public boolean onCreateOptionsMenu(android.view.Menu menu) {
        MenuItem item = menu.add(0, 0, 0, "goto gallery");
        item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                Intent intent = new Intent(Intent.ACTION_VIEW, target);
                startActivity(intent);
                return true;
            }
        });
        return true;
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }

    Camera.PictureCallback mPictureCallbackRaw  = new Camera.PictureCallback() {
                                                    @Override
                                                    public void onPictureTaken(byte[] data, Camera c) {
                                                        Log.e(getClass().getSimpleName(), "PICTURE CALLBACK RAW: " + data);
                                                        camera.startPreview();
                                                    }
                                                };

    Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
                                                    @Override
                                                    public void onPictureTaken(byte[] data, Camera c) {
                                                        Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
                                                    }
                                                };

    Camera.ShutterCallback mShutterCallback     = new Camera.ShutterCallback() {
                                                    @Override
                                                    public void onShutter() {
                                                        Log.e(getClass().getSimpleName(), "SHUTTER CALLBACK");
                                                    }
                                                };




    // ImageCaptureCallback iccb = null;
    // if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    // try {
    // String filename = timeStampFormat.format(new Date());
    // ContentValues values = new ContentValues();
    // values.put(Media.TITLE, filename);
    // values.put(Media.DESCRIPTION, "Image capture by camera");
    // Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI,
    // values);
    // // String filename = timeStampFormat.format(new Date());
    // iccb = new
    // ImageCaptureCallback(getContentResolver().openOutputStream(uri));
    // } catch (Exception ex) {
    // ex.printStackTrace();
    // Log.e(getClass().getSimpleName(), ex.getMessage(), ex);
    // }
    // }
    // if (keyCode == KeyEvent.KEYCODE_BACK) {
    // return super.onKeyDown(keyCode, event);
    // }
    //
    // if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    // camera.takePicture(mShutterCallback, mPictureCallbackRaw, iccb);
    // return true;
    // }
    //
    // return false;
    // }

    @Override
    protected void onResume() {
        Log.e(getClass().getSimpleName(), "onResume");
        super.onResume();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onStop() {
        Log.e(getClass().getSimpleName(), "onStop");
        super.onStop();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.e(getClass().getSimpleName(), "surfaceCreated");
        camera = Camera.open();
        Camera.Parameters parameters = camera.getParameters();
        float[] distances = new float[3];
        Log.d("Focus Mode: ", parameters.getFocusMode());
        parameters.getFocusDistances(distances);
        Log.d("focus distance 0", Float.toString(distances[0]));
        Log.d("focus distance 1", Float.toString(distances[1]));
        Log.d("focus distance 2", Float.toString(distances[2]));
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Log.e(getClass().getSimpleName(), "surfaceChanged");
        if (isPreviewRunning) {
            camera.stopPreview();
        }
        Camera.Parameters p = camera.getParameters();
        p.setPreviewSize(w, h);
        camera.setParameters(p);
        try {
            camera.setPreviewDisplay(holder);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        camera.startPreview();
        isPreviewRunning = true;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.e(getClass().getSimpleName(), "surfaceDestroyed");
        camera.stopPreview();
        isPreviewRunning = false;
        camera.release();
    }

}



class ImageCaptureCallback implements PictureCallback {

    private OutputStream filoutputStream;

    public ImageCaptureCallback(OutputStream filoutputStream) {
        this.filoutputStream = filoutputStream;
    }

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        try {
            Log.v(getClass().getSimpleName(), "onPictureTaken=" + data + " length = " + data.length);
            filoutputStream.write(data);
            filoutputStream.flush();
            filoutputStream.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}
}

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical">
    <SurfaceView android:id="@+id/surface" 
    android:layout_width="fill_parent"
        android:layout_height="10dip" 
        android:layout_weight="1">
    </SurfaceView>
</LinearLayout>  

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="test.test"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
 <uses-feature android:name="android.hardware.camera.autofocus" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ImageCapture"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

难道是设备驱动程序有bug?在Android源Camera.java中调用native_autoFocus()和native_getParameters()来读取距离。有谁知道哪里可以获取本机调用的源代码?

I'm trying to read the focus distance (distance of subject in a photo) from an Android camera. I keep getting 0 for all focus distances on my HTC Desire even when it correctly autofocuses. Here's the whole app, only works on v2.3.3 and above.

ImageCapture.java

package test.test;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;

import android.app.Activity;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

//THIS CLASS READS THE FOCUS DISTANCES
class ImageFocusCallback implements AutoFocusCallback {
    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        //READ FOCUS DISTANCES HERE
        Camera.Parameters parameters = camera.getParameters();
        float[] distances = new float[3];
        if (success) {
            // Only available with Android 9 (2.3)
            // Focus Mode is always reported as auto but
            // distances do not appear to be updating
            // always: 0.1, 1.2, Infinity, (on my device it's 0,0,0)
            Log.d("Focus Mode: ", parameters.getFocusMode());
            parameters.getFocusDistances(distances);
            Log.d("focus distance near", Float.toString(distances[0]));
            Log.d("focus distance optimum", Float.toString(distances[1]));
            Log.d("focus distance far", Float.toString(distances[2]));
        }
    }
}

public class ImageCapture extends Activity implements SurfaceHolder.Callback {
    //CALL AUTO FOCUS HERE
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            ImageFocusCallback autoFocusCallBack = new ImageFocusCallback();
            //AUTOFOCUS IS CALLED HERE
            camera.autoFocus(autoFocusCallBack);
            return true;
        }
        return false;
    }

    //REST OF THE CODE
    private Camera           camera;
    private boolean          isPreviewRunning = false;
    private SimpleDateFormat timeStampFormat  = new SimpleDateFormat("yyyyMMddHHmmssSS");

    private SurfaceView      surfaceView;
    private SurfaceHolder    surfaceHolder;
    private Uri              target           = Media.EXTERNAL_CONTENT_URI;


    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        Log.e(getClass().getSimpleName(), "onCreate");
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        setContentView(R.layout.main);
        surfaceView = (SurfaceView) findViewById(R.id.surface);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

    @Override
    public boolean onCreateOptionsMenu(android.view.Menu menu) {
        MenuItem item = menu.add(0, 0, 0, "goto gallery");
        item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                Intent intent = new Intent(Intent.ACTION_VIEW, target);
                startActivity(intent);
                return true;
            }
        });
        return true;
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }

    Camera.PictureCallback mPictureCallbackRaw  = new Camera.PictureCallback() {
                                                    @Override
                                                    public void onPictureTaken(byte[] data, Camera c) {
                                                        Log.e(getClass().getSimpleName(), "PICTURE CALLBACK RAW: " + data);
                                                        camera.startPreview();
                                                    }
                                                };

    Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
                                                    @Override
                                                    public void onPictureTaken(byte[] data, Camera c) {
                                                        Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
                                                    }
                                                };

    Camera.ShutterCallback mShutterCallback     = new Camera.ShutterCallback() {
                                                    @Override
                                                    public void onShutter() {
                                                        Log.e(getClass().getSimpleName(), "SHUTTER CALLBACK");
                                                    }
                                                };




    // ImageCaptureCallback iccb = null;
    // if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    // try {
    // String filename = timeStampFormat.format(new Date());
    // ContentValues values = new ContentValues();
    // values.put(Media.TITLE, filename);
    // values.put(Media.DESCRIPTION, "Image capture by camera");
    // Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI,
    // values);
    // // String filename = timeStampFormat.format(new Date());
    // iccb = new
    // ImageCaptureCallback(getContentResolver().openOutputStream(uri));
    // } catch (Exception ex) {
    // ex.printStackTrace();
    // Log.e(getClass().getSimpleName(), ex.getMessage(), ex);
    // }
    // }
    // if (keyCode == KeyEvent.KEYCODE_BACK) {
    // return super.onKeyDown(keyCode, event);
    // }
    //
    // if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    // camera.takePicture(mShutterCallback, mPictureCallbackRaw, iccb);
    // return true;
    // }
    //
    // return false;
    // }

    @Override
    protected void onResume() {
        Log.e(getClass().getSimpleName(), "onResume");
        super.onResume();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onStop() {
        Log.e(getClass().getSimpleName(), "onStop");
        super.onStop();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.e(getClass().getSimpleName(), "surfaceCreated");
        camera = Camera.open();
        Camera.Parameters parameters = camera.getParameters();
        float[] distances = new float[3];
        Log.d("Focus Mode: ", parameters.getFocusMode());
        parameters.getFocusDistances(distances);
        Log.d("focus distance 0", Float.toString(distances[0]));
        Log.d("focus distance 1", Float.toString(distances[1]));
        Log.d("focus distance 2", Float.toString(distances[2]));
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Log.e(getClass().getSimpleName(), "surfaceChanged");
        if (isPreviewRunning) {
            camera.stopPreview();
        }
        Camera.Parameters p = camera.getParameters();
        p.setPreviewSize(w, h);
        camera.setParameters(p);
        try {
            camera.setPreviewDisplay(holder);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        camera.startPreview();
        isPreviewRunning = true;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.e(getClass().getSimpleName(), "surfaceDestroyed");
        camera.stopPreview();
        isPreviewRunning = false;
        camera.release();
    }

}



class ImageCaptureCallback implements PictureCallback {

    private OutputStream filoutputStream;

    public ImageCaptureCallback(OutputStream filoutputStream) {
        this.filoutputStream = filoutputStream;
    }

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        try {
            Log.v(getClass().getSimpleName(), "onPictureTaken=" + data + " length = " + data.length);
            filoutputStream.write(data);
            filoutputStream.flush();
            filoutputStream.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}
}

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical">
    <SurfaceView android:id="@+id/surface" 
    android:layout_width="fill_parent"
        android:layout_height="10dip" 
        android:layout_weight="1">
    </SurfaceView>
</LinearLayout>  

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="test.test"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
 <uses-feature android:name="android.hardware.camera.autofocus" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ImageCapture"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

Could it be that that there is a bug in the device driver? In the Android source Camera.java call native_autoFocus() and native_getParameters() to read the distances. Does anyone know where to get the source for the native calls?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ι不睡觉的鱼゛ 2024-11-22 21:44:10

在 Froyo 中,frameworks/base/core/jni/android_hardware_Camera.cpp 通过调用 android_hardware_Camera_autoFocus() 来实现 native_autoFocus(),这似乎在运行时绑定到设备/供应商特定的代码。

不幸的是,“如果相机不支持自动对焦并且调用了 autoFocus,则将立即调用 onAutoFocus,并将成功的假值设置为 true。”是记录的行为

我很好奇您使用的哪些功能需要 2.3.3、API 级别 10。

In Froyo, frameworks/base/core/jni/android_hardware_Camera.cpp implements native_autoFocus() by calling android_hardware_Camera_autoFocus(), which appears to bind at runtime to the device/vendor specific code.

Unfortunately, "If the camera does not support auto-focus and autoFocus is called, onAutoFocus will be called immediately with a fake value of success set to true." is a documented behavior.

I'm curious which of the functions you use requires 2.3.3, API level 10.

找个人就嫁了吧 2024-11-22 21:44:10

可能是相机驱动程序中的一个错误,只有再次设置手机才能修复此问题,是的,我知道这真的很糟糕,但我也遇到了完全相同的问题。

但我选择为我的设备使用自定义 ROM。 Atm 我使用 Android Revolution HD 6.1.1
http://forum.xda-developers.com/showthread.php?t=840040

对于你的第二个问题,你可以从你下载的ROM包中取出相机应用程序的源文件。也许如果你改变它,它就会起作用。

此致

Probably its a bug in the camera driver you can only fix this if you set up you phone again, yes I know it really shitty, but I had exact the same problem too.

But i choosed to use a custom rom for my device. Atm im using Android Revolution HD 6.1.1
http://forum.xda-developers.com/showthread.php?t=840040

For your secound Question you can take out the source file for the camera app from the package you download with the rom. Probably if you change it, it will work.

Best Regards

一直在等你来 2024-11-22 21:44:10

我不知道你可以在哪里获得本机调用的来源。但是如果 getFocusDistances(float[]) 方法中的所有焦距都为 0,您可以阅读 此问题。在那里你可以看到这个错误不是设备的错误而是Android SDK的错误。

I don't know where you can get the source for the native calls. But what about getting 0 for all the focus distances in getFocusDistances(float[]) method, you can read this issue. There you can read that this error is not the error of the device but of the Android SDK.

べ繥欢鉨o。 2024-11-22 21:44:10

这是错误 14341 - “无论实际焦距如何,Camera.Parameters.getFocusDistances() 返回的距离在 Nexus S 上都不会改变”。

首次报告于 2011 年 1 月 26 日,最后一次报告于 2014 年 3 月 18 日。因此,该 Bug 是在您遇到该错误之前不久报告的,并且至今尚未修复。这是专门针对您的设备进行报告的。

报告中的各种评论声称此错误影响“Nexus S”、“HTC Sensation”、“Galaxy S Plus”、“Galaxy S II”、“HTC Desire HD”、“Galaxy Nexus”、 “Xperia Mini ST15i”、“Nexus 5”、“Galaxy R”和“Galaxy Note II”;有一条评论声称它在“Galaxy Nexus”上完美运行。

参考:https://code.google.com/p/android/issues /detail?id=14341

这是您正在寻找的源代码吗: https://android.googlesource.com/platform/frameworks/base/+/froyo-release/core/jni/android_hardware_Camera.cpp

This is Bug 14341 - "Distances returned by Camera.Parameters.getFocusDistances() do not change on Nexus S regardless of actual focus distance".

First reported Jan 26, 2011 with the last report on Mar 18, 2014. Thus, the Bug was reported shortly before you ran into it and has not been fixed to this day. It is specifically reported against your Device.

Various comments in the report claim this Bug affects the "Nexus S", "HTC Sensation", "Galaxy S Plus", "Galaxy S II", "HTC Desire HD", "Galaxy Nexus", "Xperia Mini ST15i", "Nexus 5", "Galaxy R", and the "Galaxy Note II"; with one Comment claiming it works perfectly on the "Galaxy Nexus".

Reference: https://code.google.com/p/android/issues/detail?id=14341 .

Is this the Source Code you were looking for: https://android.googlesource.com/platform/frameworks/base/+/froyo-release/core/jni/android_hardware_Camera.cpp

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文