Предварительный просмотр камеры в порядке, но передняя камера производит очень темные фотографии - PullRequest
0 голосов
/ 03 декабря 2018

Я создал собственную камеру, используя API-интерфейс Camera 1, и по какой-то причине он создает очень темные снимки ( только на передней камере , задняя камера работает отлично).Предварительный просмотр камеры показывает камеру как следует, с правильной яркостью - только когда изображение захвачено и декодировано в растровое изображение, оно выглядит действительно темным.Я некоторое время лихорадочно гуглял и обнаружил, что об этой проблеме сообщалось довольно много раз, но не могу найти работающее решение.Я использую устройство Samsung J5.

CameraPreview:

class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

  private static final String CAMERA = "CAMERA";

  private static Camera mCamera;

  private final CameraActivity cameraActivity;
  private final SurfaceHolder mHolder;

  public CameraPreview(Camera camera, CameraActivity cameraActivity) {
    super(cameraActivity);
    this.cameraActivity = cameraActivity;
    mCamera = camera;
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  }

  public void setCameraDisplayOrientation(int cameraId) {
    Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    final int rotation = cameraActivity.getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;

    switch (rotation) {
      case Surface.ROTATION_0:
        degrees = 0;
        break;
      case Surface.ROTATION_90:
        degrees = 90;
        break;
      case Surface.ROTATION_180:
        degrees = 180;
        break;
      case Surface.ROTATION_270:
        degrees = 270;
        break;
    }

    int result;
    if (info.facing == cameraId) {
      result = (info.orientation + degrees) % 360;
      result = (360 - result) % 360;
    } else {
      result = (info.orientation - degrees + 360) % 360;
    }

    mCamera.setDisplayOrientation(result);
  }

  @Override
  public void surfaceCreated(SurfaceHolder holder) {
    try {
      mCamera.setPreviewDisplay(holder);
      mCamera.startPreview();
      cameraActivity.isSafeToTakePicture(true);
      Camera.Parameters params = mCamera.getParameters();
      // my attempt at preventing darkness 
      params.setExposureCompensation(params.getMaxExposureCompensation());
      if(params.isAutoExposureLockSupported()) {
        params.setAutoExposureLock(false);
      }

      mCamera.setParameters(params);
    } catch (IOException e) {
      Log.d(CAMERA, "An error occured when setting up the camera preview " + e.getMessage());
    }
  }

  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
    mCamera.stopPreview();
  }

  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
  }
}

На моем CameraPictureCallback (при получении изображения) я отправляю байты этому методу, который декодирует байты в растровое изображение, помещает его всвязывает и передает его следующему фрагменту:

 public void openFragmentWithBitmap(byte[] bytes) {
    final BitmapFactory.Options scalingOptions = new BitmapFactory.Options();
    final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, scalingOptions);
    final Bundle bundle = new Bundle();
    bundle.putParcelable(SELFIE, bitmap);

    mCamera.stopPreview();
    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    final Fragment startChainFragment = new StartChainFragment();
    startChainFragment.setArguments(bundle);
    ft.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
      .replace(R.id.rlPlaceholder, startChainFragment, StartChainFragment.TAG)
      .addToBackStack(null)
      .commit();
  }

Мне не хватает здесь трюка?В моем surfaceCreated () я установил максимальную компенсацию экспозиции, но это, похоже, не дает эффекта.Ценю любую помощь.

Редактировать: Оказывается, добавление задержки не имеет значения, поэтому вот результаты (предварительный просмотр камеры и фактическое снятое изображение):

CameraPreview: enter image description here

Захваченное изображение: enter image description here

Изображение захватывается с помощью вызова mCamera.takePicture(null, null, pictureCallback) при нажатии кнопки захвата (обратный вызов просто передает байты вышеупомянутомуметод). * * тысяча тридцать-одна

Ответы [ 2 ]

0 голосов
/ 22 декабря 2018

После всей крови, пота и слез я нашел решение этой проблемы.Я заметил, что предварительный просмотр и окончательное изображение не выглядят так, как будто они имеют одинаковое разрешение (вы можете видеть, что бутылка на изображении предварительного просмотра шире, чем на снятом изображении).Поэтому я попытался сделать их одинаковыми или максимально близкими.Я называю этот метод после startPreview() в surfaceCreated():

private void loadCameraParameters() {
    final Camera.Parameters camParams = mCamera.getParameters();

    final Camera.Size previewSize = getOptimalPreviewSize(camParams.getSupportedPreviewSizes(),  screenWidth, screenHeight);
    camParams.setPreviewSize(previewSize.width, previewSize.height);

    final Camera.Size pictureSize = getOptimalPreviewSize(camParams.getSupportedPictureSizes(), screenWidth, screenHeight);
    camParams.setPictureSize(pictureSize.width, pictureSize.height);

    mCamera.setParameters(camParams);
}

, где getOptimalPreviewSize():

private Camera.Size getOptimalPreviewSize(List<Size> sizes, int targetWidth, int targetHeight) {
    final double aspectTolerance = 0.05;
    final double targetRatio = (double) targetWidth/targetHeight;

    if (sizes == null) {
      return null;
    }

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    for (Camera.Size size : sizes) {
      final double ratio = (double) size.width / size.height;
      if (Math.abs(ratio - targetRatio) > aspectTolerance) continue;
      if (Math.abs(size.height - targetHeight) < minDiff) {
        optimalSize = size;
        minDiff = Math.abs(size.height - targetHeight);
      }
    }

    if (optimalSize == null) {
      minDiff = Double.MAX_VALUE;
      for (Camera.Size size : sizes) {
        if (Math.abs(size.height - targetHeight) < minDiff) {
          optimalSize = size;
          minDiff = Math.abs(size.height - targetHeight);
        }
      }
    }

    return optimalSize;
  }

Теперь моя картинка и предварительный просмотр идеально подходят для обеих моихустройства с одинаковой яркостью и разрешением .

0 голосов
/ 10 декабря 2018

Поскольку я работал с пользовательской камерой и столкнулся с множеством проблем, связанных с размерами экрана различных устройств и т. Д., Это единственное, что сработало для меня, поэтому я предлагаю следующую библиотеку, которая может помочь вам разобраться в проблеме.У него тоже есть много вариантов.

https://github.com/florent37/CameraFragment

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...