Это решение является одним из способов обхода ситуации. Некоторый код устарел и не рекомендуется для использования в корпоративных проектах, но если вам нужно просто показать предварительный просмотр камеры без сжатия, этого достаточно.
Если вам нужно обработать изображение перед предварительным просмотром, вы должны посмотреть SurfaceTexture
public class CameraPreview
extends SurfaceView
implements SurfaceHolder.Callback, Camera.PreviewCallback {
public static final String TAG = CameraPreview.class.getSimpleName();
private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;
private static final double ASPECT_RATIO = 3.0 / 4.0;
private Camera mCamera;
private SurfaceHolder mHolder;
private boolean mIsLive;
private boolean mIsPreviewing;
public CameraPreview(Context context) {
super(context);
init(context);
}
public CameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int) (width / ASPECT_RATIO + 0.5);
setMeasuredDimension(width, height);
}
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
//L.g().d(TAG, "onVisibilityChanged: visibility=" + visibility);
if (mIsLive) {
if (visibility == VISIBLE && !mIsPreviewing) {
startCameraPreview();
} else {
stopCameraPreview();
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
startCamera();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopCamera();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
//L.g().d(TAG, "surfaceChanged: format=" + format + ", width=" + w + ", height=" + h);
if (mHolder.getSurface() == null || mCamera == null) return;
mHolder = holder;
try {
mCamera.stopPreview();
} catch (Exception ignored) {}
try {
mCamera.setPreviewDisplay(mHolder);
if (mIsLive && mIsPreviewing) mCamera.startPreview();
} catch (Exception ignored) {}
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
//work with camera preview
if (mIsPreviewing) camera.setOneShotPreviewCallback(this);
}
private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_SIZE_MAX_WIDTH);
}
private Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPictureSizes(), PICTURE_SIZE_MAX_WIDTH);
}
/**
* This code I found in this repository
* https://github.com/boxme/SquareCamera/blob/master/squarecamera/src/main/java/com/desmond/squarecamera/CameraFragment.java#L368
*/
private Camera.Size determineBestSize(List<Camera.Size> sizes, int widthThreshold) {
Camera.Size bestSize = null;
Camera.Size size;
int numOfSizes = sizes.size();
for (int i = 0; i < numOfSizes; i++) {
size = sizes.get(i);
boolean isDesireRatio = (size.width / 4) == (size.height / 3);
boolean isBetterSize = (bestSize == null) || size.width > bestSize.width;
if (isDesireRatio && isBetterSize) {
bestSize = size;
}
}
if (bestSize == null) {
return sizes.get(sizes.size() - 1);
}
return bestSize;
}
private void init(Context context) {
mHolder = getHolder();
mHolder.addCallback(this);
}
public void startCamera() {
if (!mIsLive) {
//L.g().d(TAG, "startCamera");
mIsPreviewing = false;
mCamera = Camera.open();
if (mCamera != null) {
try {
Camera.Parameters param = mCamera.getParameters();
Camera.Size bestPreviewSize = determineBestPreviewSize(param);
Camera.Size bestPictureSize = determineBestPictureSize(param);
param.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
param.setPictureSize(bestPictureSize.width, bestPictureSize.height);
mCamera.setParameters(param);
} catch (RuntimeException ignored) {}
try {
mCamera.setDisplayOrientation(90);
mCamera.setPreviewCallback(this);
mCamera.setPreviewDisplay(mHolder);
mIsLive = true;
} catch (Exception ignored) {}
}
//else L.g().d(TAG, "startCamera: error launching the camera");
}
}
public void stopCamera() {
if (mCamera != null && mIsLive) {
//L.g().d(TAG, "stopCamera");
mCamera.stopPreview();
mCamera.release();
mCamera = null;
mIsPreviewing = false;
mIsLive = false;
}
}
public void startCameraPreview() {
if (mCamera != null && mIsLive && !mIsPreviewing) {
//L.g().d(TAG, "startCameraPreview");
mCamera.setPreviewCallback(this);
mCamera.startPreview();
mIsPreviewing = true;
}
}
public void stopCameraPreview() {
if (mCamera != null && mIsLive && mIsPreviewing) {
//L.g().d("stopCameraPreview");
mCamera.stopPreview();
mIsPreviewing = false;
}
}
}