问题
I'm new in Android Camera2 API. I just move my all project to the new Camera2 API. I have used the Camera2Basic example as a starting point.
I'm now trying handle zoom by adding this:
public boolean onTouchEvent(MotionEvent event) {
try {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraId);
float maxZoom = (characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM))*10;
Rect m = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
int action = event.getAction();
float current_finger_spacing;
if (event.getPointerCount() > 1) {
// Multi touch logic
current_finger_spacing = getFingerSpacing(event);
if(finger_spacing != 0){
if(current_finger_spacing > finger_spacing && maxZoom > zoom_level){
zoom_level++;
}
else if (current_finger_spacing < finger_spacing && zoom_level > 1){
zoom_level--;
}
int minW = (int) (m.width() / maxZoom);
int minH = (int) (m.height() / maxZoom);
int difW = m.width() - minW;
int difH = m.height() - minH;
int cropW = difW /100 *(int)zoom_level;
int cropH = difH /100 *(int)zoom_level;
cropW -= cropW & 3;
cropH -= cropH & 3;
Rect zoom = new Rect(cropW, cropH, m.width() - cropW, m.height() - cropH);
mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom);
}
finger_spacing = current_finger_spacing;
}
else{
if (action == MotionEvent.ACTION_UP) {
//single touch logic
}
}
try {
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback,
null);
}
catch (CameraAccessException e) {
e.printStackTrace();
}
catch (NullPointerException ex)
{
ex.printStackTrace();
}
}
catch (CameraAccessException e)
{
throw new RuntimeException("can not access camera.", e);
}
return true;
}
And this:
private float getFingerSpacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
But after I captured, the picture result is without the zoom. How can I make it happen? Thanks all.
Update
Need to add captureBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom);
to captureStillPicture()
method.
回答1:
Need to add captureBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom);
to the captureStillPicture()
method.
回答2:
You've only set the SCALER_CROP_REGION
on the CaptureRequestBuilder
for the recurring preview camera output. You just need to add the same crop region property to the CaptureRequestBuilder
that uses the ImageSaver
's JPEG Surface
as the output, and you should be all set.
回答3:
Global:
companion object {
private const val ZOOM_GESTURE_SENSITIVITY = .0005f
private const val MAX_ZOOM_FACTOR = 3f
}
private var fingerDistance: Float? = null
private var zoom = 1f
Listener:
textureView.setOnTouchListener({ _, event ->
if (event.action != MotionEvent.ACTION_MOVE || event.pointerCount <= 1) {
fingerDistance = null
return@setOnTouchListener true
}
val newFingerDistance = with(event) {
val x = getX(0) - getX(1)
val y = getY(0) - getY(1)
sqrt(x * x + y * y) * resources.displayMetrics.density
}
if (fingerDistance != null) {
val manager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val characteristics = manager.getCameraCharacteristics(cameraId)
val maxZoom = min(MAX_ZOOM_FACTOR, characteristics.get(
CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM))
val zoomChange = (newFingerDistance - fingerDistance!!) * ZOOM_GESTURE_SENSITIVITY
zoom = min(maxZoom, max(1f, zoom + zoomChange))
val sensorSize = characteristics.get(
CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)!!
val cropW = (sensorSize.width() * (1 - 1 / zoom) / 2).toInt()
val cropH = (sensorSize.width() * (1 - 1 / zoom) / 2).toInt()
val zoomRect = Rect(cropW, cropH,
sensorSize.width() - cropW,
sensorSize.height() - cropH)
previewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect)
}
fingerDistance = newFingerDistance
try {
captureSession
?.setRepeatingRequest(previewRequestBuilder.build(), captureCallback, null)
} catch (e: Exception) {
e.printStackTrace()
}
true
})
回答4:
Just set SCALER.CROP.REGION
to the captureBuilder
. You can do it in this way:
yourCapturebuilder.(CaptureRequest.SCALER_CROP_REGION, newZoom);
In other way, if you want to keep the Zoom in a preference. I suggest you do something like this: Save the Rect in a preference as a String and later on recover it to use it, or call it every time you open the camera:
Preferences.edit().putString(CameraSettings.KEY_ZOOM,newZoom.toString());
Later call this method to set the zoom dynamically:
public boolean setZoomValue(CaptureRequest.Builder builder) {
Log.i(TAG,"zoom preference value " + mPreferences.getString(CameraSettings.KEY_ZOOM,null));
String rawZoomValue = mPreferences.getString(CameraSettings.KEY_ZOOM, null);
if (rawZoomValue == null)
return false;
rawZoomValue = rawZoomValue.replaceAll("[Rect() ]", "");
String[] rectZoomList = rawZoomValue.split(",|\\-|\\)|\\(");
Rect zoomValue = new Rect( Integer.parseInt(rectZoomList[0]), Integer.parseInt(rectZoomList[1]), Integer.parseInt(rectZoomList[2]),Integer.parseInt(rectZoomList[3]));
builder.set(CaptureRequest.SCALER_CROP_REGION, zoomValue);
Log.i(TAG, "Zoom applied: " + zoomValue);
return true;
}
来源:https://stackoverflow.com/questions/35968315/android-camera2-handle-zoom