Предварительный просмотр камеры HTC-One режет изображение
Я использую пользовательский предварительный просмотр камеры в своем приложении, он отлично работает практически на всех устройствах, для HTC-One я получаю плохое изображение, исходное фото не соответствует тому, что предварительный просмотр показывает вверху.
Это происходит только на этом устройстве, это код моей камеры предварительного просмотра и картинка о том, что происходит.
Заранее спасибо за любую помощь, кто-то может мне помочь.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private Context context;
private Camera.Size mPreviewSize;
private List<Camera.Size> mSupportedPreviewSizes;
public CameraPreview(Context context) {
super(context);
this.context = context;
mHolder = getHolder();
mHolder.addCallback(this);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for (Camera.Size str : mSupportedPreviewSizes) {
Log.e(TAG, str.width + "/" + str.height);
}
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if (mPreviewSize.height >= mPreviewSize.width) {
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
} else {
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
}
setMeasuredDimension(width, (int) (width * ratio));
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void setFlash(String flashMode) {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(flashMode);
mCamera.setParameters(params);
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
double ratio = (double) size.height / size.width;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
}
return optimalSize;
}
public void switchCamera(Camera camera) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
camera.setDisplayOrientation(90);
} else if (display.getRotation() == Surface.ROTATION_270) {
camera.setDisplayOrientation(180);
}
setCamera(camera);
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
}
1 ответ
Размер предварительного просмотра камеры и размер изображения - это два разных параметра, которые можно обновить с помощью API-интерфейсов setPictureSize () и setPreviewSize (). Но если пользователь не изменит эти размеры, он будет использовать значения по умолчанию.
В этом случае вы обновляете размер предварительного просмотра, вычисляя оптимальный размер предварительного просмотра на основе некоторого соотношения сторон. Но вы не обновляете размер изображения, поэтому он будет использовать размер изображения по умолчанию.
Если размер изображения и соотношение сторон для предварительного просмотра отличаются, определенно захваченное изображение будет отличаться от предварительного просмотра. Поэтому обновите размер изображения также, рассчитав оптимальный размер изображения с тем же соотношением сторон, что и размер предварительного просмотра.