相机焦距
我正在尝试从 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 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.
可能是相机驱动程序中的一个错误,只有再次设置手机才能修复此问题,是的,我知道这真的很糟糕,但我也遇到了完全相同的问题。
但我选择为我的设备使用自定义 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
我不知道你可以在哪里获得本机调用的来源。但是如果 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.
这是错误 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