天天看點

第40講 Android Camera2 API Digital Zoom縮放實戰

本講是Android Camera專題系列的第40講,我們介紹Android Camera2 API專題的Digital Zoom縮放實戰,包括如下内容:

  1. 判斷是否支援Digital Zoom
  2. 配置Zoom的SeekBar
  3. 将Zoom值轉換為Crop Region并設定給底層

視訊線上觀看:

  •  極客筆記:極客筆記線上課程

加入知識星球與更多Camera同學交流

– 星球名稱:深入淺出Android Camera

– 星球ID: 17296815

判斷是否支援Digital Zoom

float max_zoom = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
camera_features.is_zoom_supported = max_zoom > 0.0f;
           

平滑的Zoom Steps計算方式

// set 20 steps per 2x factor
final int steps_per_2x_factor = 20;
//final double scale_factor = Math.pow(2.0, 1.0/(double)steps_per_2x_factor);
int n_steps =(int)( (steps_per_2x_factor * Math.log(max_zoom + 1.0e-11)) / Math.log(2.0));
final double scale_factor = Math.pow(max_zoom, 1.0/(double)n_steps);
if( MyDebug.LOG ) {
    Log.i(TAG, "[Zoom] n_steps: " + n_steps);
    Log.i(TAG, "[Zoom] scale_factor: " + scale_factor);
}
camera_features.zoom_ratios = new ArrayList<>();
camera_features.zoom_ratios.add(100);
double zoom = 1.0;
for(int i=0;i<n_steps-1;i++) {
    zoom *= scale_factor;
    camera_features.zoom_ratios.add((int)(zoom*100));
    Log.i(TAG, "[Zoom] zoom:" + zoom*100);
}
camera_features.zoom_ratios.add((int)(max_zoom*100));
camera_features.max_zoom = camera_features.zoom_ratios.size()-1;
this.zoom_ratios = camera_features.zoom_ratios;
           

配置Zoom的SeekBar

zoomSeekBar.setOnSeekBarChangeListener(null); // clear an existing listener - don't want to call the listener when setting up the progress bar to match the existing state
zoomSeekBar.setMax(preview.getMaxZoom());
zoomSeekBar.setProgress(preview.getMaxZoom()-preview.getCameraController().getZoom());
zoomSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if( MyDebug.LOG )
            Log.d(TAG, "zoom onProgressChanged: " + progress);
        // note we zoom even if !fromUser, as various other UI controls (multitouch, volume key zoom, -/+ zoomcontrol)
        // indirectly set zoom via this method, from setting the zoom slider
        preview.zoomTo(preview.getMaxZoom() - progress);
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
});
           

将Zoom值轉換為Crop Region并設定給底層

float zoom = zoom_ratios.get(value)/100.0f;
Rect sensor_rect = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
if (mPreviewBuilder.get(CaptureRequest.DISTORTION_CORRECTION_MODE) != null) {
    int distortionMode = mPreviewBuilder.get(CaptureRequest.DISTORTION_CORRECTION_MODE);
    if (mStaticMetadata.isDistortionCorrectionSupported() &&
            distortionMode == CaptureRequest.DISTORTION_CORRECTION_MODE_OFF) {
        sensor_rect = characteristics.get(CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
        Log.i(TAG, "[Zoom] distortionMode:" + distortionMode);
    }
}
int left = sensor_rect.width()/2;
int right = left;
int top = sensor_rect.height()/2;
int bottom = top;
int hwidth = (int)(sensor_rect.width() / (2.0*zoom));
int hheight = (int)(sensor_rect.height() / (2.0*zoom));
left -= hwidth;
right += hwidth;
top -= hheight;
bottom += hheight;