Androidカスタムカメラ、手動フォーカス
7767 ワード
プロジェクトのまとめ:
プロジェクトの需要:カメラのページを作って、View形式で現れて、レイアウトのファイルの中に追加することができて、タッチフォーカスを実現します
問題(難点):1.ビューを作成するためにレイアウトファイルに追加できるので、このビューのサイズは固定されていません.そのためプレビュー解像度が定まらず、縦画面切り替え後にプレビュー画像が変形しやすくなります
2.手動フォーカスは、プレビュー領域の中心を原点とし、左上角(-1000,-1000)、右下角(1000,000)の座標系に定義されたフォーカスAreaを算出する必要がある.座標変換は問題です
コードdemoアップロードしました
カメラのインスタンスを取得して画面に表示する方法は、ネット上の多くの例で、説明しすぎません.コードは以下の通りです.
第1の問題解決方法は、表示領域の大きさを取得し、携帯電話カメラでサポートされているプレビュー解像度と比較して、表示領域のアスペクト比に最も近い最大携帯電話プレビュー解像度を取得し、取得プレビュー解像度値に基づいて、表示領域のアスペクトを変更することである.携帯電話のプレビュー解像度の最大値は、プレビューをより明確にするためです
第2の問題の解決方法は、画面上の点の座標に基づいて、表示領域の座標を算出する
プロジェクトの需要:カメラのページを作って、View形式で現れて、レイアウトのファイルの中に追加することができて、タッチフォーカスを実現します
問題(難点):1.ビューを作成するためにレイアウトファイルに追加できるので、このビューのサイズは固定されていません.そのためプレビュー解像度が定まらず、縦画面切り替え後にプレビュー画像が変形しやすくなります
2.手動フォーカスは、プレビュー領域の中心を原点とし、左上角(-1000,-1000)、右下角(1000,000)の座標系に定義されたフォーカスAreaを算出する必要がある.座標変換は問題です
コードdemoアップロードしました
カメラのインスタンスを取得して画面に表示する方法は、ネット上の多くの例で、説明しすぎません.コードは以下の通りです.
private Camera getCameraInstance() {
Camera c = null;
try {
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); // get cameras number
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { // , CAMERA_FACING_FRONT CAMERA_FACING_BACK
try {
c = Camera.open(camIdx);
} catch (RuntimeException e) {
}
}
}
if (c == null) {
c = Camera.open(0); // attempt to get a Camera instance
}
} catch (Exception e) {
// Toast.makeText(context, " !", Toast.LENGTH_SHORT);
}
return c;
}
第1の問題解決方法は、表示領域の大きさを取得し、携帯電話カメラでサポートされているプレビュー解像度と比較して、表示領域のアスペクト比に最も近い最大携帯電話プレビュー解像度を取得し、取得プレビュー解像度値に基づいて、表示領域のアスペクトを変更することである.携帯電話のプレビュー解像度の最大値は、プレビューをより明確にするためです
private void updateCameraParameters() {
if (camera != null) {
Camera.Parameters p = camera.getParameters();
long time = new Date().getTime();
p.setGpsTimestamp(time);
Size previewSize = findBestPreviewSize(p);
p.setPreviewSize(previewSize.width, previewSize.height);
// , ( ),
p.setPictureSize(previewSize.width, previewSize.height);
// Set the preview frame aspect ratio according to the picture size.
frameLayout.setAspectRatio((double) previewSize.width / previewSize.height);
if (context.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
camera.setDisplayOrientation(90);
p.setRotation(90);
}
camera.setParameters(p);
}
}
/**
* ( )
* @param parameters
* @return
*/
private Size findBestPreviewSize(Camera.Parameters parameters) {
//
String previewSizeValueString = null;
previewSizeValueString = parameters.get("preview-size-values");
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
if (previewSizeValueString == null) { // m9
return camera.new Size(getScreenWH().widthPixels, getScreenWH().heightPixels);
}
float bestX = 0;
float bestY = 0;
float tmpRadio = 0;
float viewRadio = 0;
if (viewWidth != 0 && viewHeight != 0) {
viewRadio = Math.min((float) viewWidth, (float) viewHeight) / Math.max((float) viewWidth, (float) viewHeight);
}
// System.out.println("CustomCameraView previewSizeValueString COMMA_PATTERN = "
// + previewSizeValueString);
String[] COMMA_PATTERN = previewSizeValueString.split(",");
for (String prewsizeString : COMMA_PATTERN) {
prewsizeString = prewsizeString.trim();
int dimPosition = prewsizeString.indexOf('x');
if (dimPosition == -1) {
continue;
}
float newX = 0;
float newY = 0;
try {
newX = Float.parseFloat(prewsizeString.substring(0, dimPosition));
newY = Float.parseFloat(prewsizeString.substring(dimPosition + 1));
} catch (NumberFormatException e) {
continue;
}
float radio = Math.min(newX, newY) / Math.max(newX, newY);
if (tmpRadio == 0) {
tmpRadio = radio;
bestX = newX;
bestY = newY;
} else if (tmpRadio != 0 && (Math.abs(radio - viewRadio)) < (Math.abs(tmpRadio - viewRadio))) {
tmpRadio = radio;
bestX = newX;
bestY = newY;
}
}
if (bestX > 0 && bestY > 0) {
// System.out.println("CustomCameraView previewSizeValueString bestX = " +
// bestX + ", bestY = " + bestY);
return camera.new Size((int) bestX, (int) bestY);
}
return null;
}
第2の問題の解決方法は、画面上の点の座標に基づいて、表示領域の座標を算出する
/**
*
* @param event
*/
public void focusOnTouch(MotionEvent event) {
int[] location = new int[2];
frameLayout.getLocationOnScreen(location);
Rect focusRect = calculateTapArea(view_focus.getWidth(), view_focus.getHeight(), 1f, event.getRawX(), event.getRawY(),
location[0], location[0] + frameLayout.getWidth(), location[1], location[1] + frameLayout.getHeight());
Rect meteringRect = calculateTapArea(view_focus.getWidth(), view_focus.getHeight(), 1.5f, event.getRawX(), event.getRawY(),
location[0], location[0] + frameLayout.getWidth(), location[1], location[1] + frameLayout.getHeight());
Camera.Parameters parameters = camera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// System.out.println("CustomCameraView getMaxNumFocusAreas = " +
// parameters.getMaxNumFocusAreas());
if (parameters.getMaxNumFocusAreas() > 0) {
List focusAreas = new ArrayList();
focusAreas.add(new Camera.Area(focusRect, 1000));
parameters.setFocusAreas(focusAreas);
}
// System.out.println("CustomCameraView getMaxNumMeteringAreas = " +
// parameters.getMaxNumMeteringAreas());
if (parameters.getMaxNumMeteringAreas() > 0) {
List meteringAreas = new ArrayList();
meteringAreas.add(new Camera.Area(meteringRect, 1000));
parameters.setMeteringAreas(meteringAreas);
}
try {
camera.setParameters(parameters);
} catch (Exception e) {
}
camera.autoFocus(this);
}
/**
*
* @param focusWidth
* @param focusHeight
* @param areaMultiple
* @param x
* @param y
* @param previewleft
* @param previewRight
* @param previewTop
* @param previewBottom
* @return Rect(left,top,right,bottom) : left、top、right、bottom 。 Rect
*/
public Rect calculateTapArea(int focusWidth, int focusHeight, float areaMultiple,
float x, float y, int previewleft, int previewRight, int previewTop, int previewBottom) {
int areaWidth = (int) (focusWidth * areaMultiple);
int areaHeight = (int) (focusHeight * areaMultiple);
int centerX = (previewleft + previewRight) / 2;
int centerY = (previewTop + previewBottom) / 2;
double unitx = ((double) previewRight - (double) previewleft) / 2000;
double unity = ((double) previewBottom - (double) previewTop) / 2000;
int left = clamp((int) (((x - areaWidth / 2) - centerX) / unitx), -1000, 1000);
int top = clamp((int) (((y - areaHeight / 2) - centerY) / unity), -1000, 1000);
int right = clamp((int) (left + areaWidth / unitx), -1000, 1000);
int bottom = clamp((int) (top + areaHeight / unity), -1000, 1000);
return new Rect(left, top, right, bottom);
}
public int clamp(int x, int min, int max) {
if (x > max)
return max;
if (x < min)
return min;
return x;
}
ソースアドレス:http://download.csdn.net/detail/minyou_1314/7854309あるいは私のリソースにダウンロードします