Изображение камеры Android искажено - SurfaceHolder -

У меня странная проблема с камерой-SurfaceHolder.

Я хочу показать изображение камеры в моей деятельности. На моем GalaxyS1 все работает очень хорошо (CyanogenMod - Android 4.4) На моем S3 (также CyanogenMod - Android 4.4), с другой стороны, это выглядит странно.

Пейзажное изображение без строки заголовка хорошо, но когда я показываю строку заголовка или превращаю ее в портретный режим, оно выглядит искаженным:

--- РЕДАКТИРОВАТЬ ---

Спасибо Алекс Кон за вашу помощь. Похоже, ты прав. Предварительный просмотр для режима portraid теперь работает хорошо. Но все же это выглядит искаженным на пейзажном виде. Я проверил масштаб предварительного просмотра, и он выглядит хорошо. Насколько я вижу, я также правильно установил размер предварительного просмотра. Так что с ним не так?

Вот текущий код:

    private static final String TAG = CameraView.class.getSimpleName();

      private SurfaceHolder surfaceHolder;
      private Camera camera;
      private List<Size> mSupportedPreviewSizes;
      private Size mPreviewSize;

      public CameraView(Activity activity) {
        super(activity);
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        camera = Camera.open();
        mSupportedPreviewSizes = camera.getParameters()
                .getSupportedPreviewSizes();
        setCameraDisplayOrientation(activity, 0, camera);
      }

      @Override
      public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Camera.Parameters parameters = camera.getParameters();
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        camera.setParameters(parameters);
        camera.startPreview();
      }

      @Override
      public void surfaceCreated(SurfaceHolder holder) {
       try {
         camera.setPreviewDisplay(holder);
       } catch (IOException exception) {
             camera.release();
             camera = null;
       }
      }

     @Override
       public void surfaceDestroyed(SurfaceHolder arg0) {
       camera.stopPreview();
       camera.release();
       camera = null;
     }

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
                setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
    }
  }

  private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w,
                int h) {...}

  public static void setCameraDisplayOrientation(Activity activity,
                int cameraId, Camera camera) {...}

--- РЕДАКТИРОВАТЬ ---

Я зарегистрировал значения для onMeasure и Измененная поверхность. Кажется, они в порядке:

Портрет:

ПОВЕРХНОСТЬ ИЗМЕНЕНА: Witdh:720 Высота:1134

Измерение: ширина: 720 высота:1134

Пейзаж:

ПОВЕРХНОСТЬ ИЗМЕНЕНА: Witdh:1280 Высота:590

Измерение: ширина: 1280 высота:590

Предпросмотр Размер: Ширина: 704 Высота:576

Я получаю следующие возможные размеры предварительного просмотра.

В массиве 8 элементов:

960 х 720, 1280 х 720, 1184 х 666, 960 х 640,704 х 576, 640 х 480, 352 х 288, 320 х 240

Надеюсь, кто-нибудь может помочь!

Спасибо, Тобиас

1 ответ

Решение

Источником вашей проблемы является следующая строка:

parameters.setPreviewSize(w, h);

в surfaceChanged() метод. Вы не можете установить размер предварительного просмотра на произвольные значения в Android. Вы должны использовать только пары (w, h), возвращаемые Parameters.getSupportedPreviewSizes (). В противном случае вы нажмете, что кажется успешным, это допустимая форма неопределенной ситуации поведения. На самом деле, многие устройства просто вызывают RuntimeException на camera.setParameters(parameters), но ваши платформы разработки решили вести себя по-другому.

Не требуется, чтобы размер предварительного просмотра был таким же, как у поверхности, используемой для его отображения, например, можно использовать предварительный просмотр 320x240 на поверхности 640x480. Но если ваш предварительный просмотр и поверхность имеют разные пропорции, изображение будет выглядеть растянутым (см. ). Небольшие искажения могут быть допустимыми, например, при использовании предварительного просмотра 1280x720 при 800x400 пикселей, но при превышении определенного порога у вас нет другого выбора, кроме как использовать только часть экрана, оставляя поля выше и ниже предварительного просмотра.

Вы можете найти то, что придумало сообщество разработчиков: использовать getOptimalPreviewSize() для заданной ширины высота (это только один пример).

Другие вопросы по тегам