Как реализовать предварительный просмотр

При добавлении предварительного просмотра в приложение используйте PreviewView – это View, который можно обрезать, масштабировать и поворачивать для правильного отображения.

Когда камера становится активной, изображение с нее передается на поверхность внутри PreviewView.

Как использовать PreviewView

Чтобы реализовать предварительный просмотр для CameraX с помощью PreviewView, выполните следующие действия:

  1. При необходимости настройте CameraXConfig.Provider.
  2. Добавьте PreviewView в макет.
  3. Запросите ProcessCameraProvider.
  4. При создании View проверьте ProcessCameraProvider.
  5. Выберите камеру и привяжите жизненный цикл и варианты использования.

У PreviewView есть некоторые ограничения. При использовании PreviewView вы не можете:

  • Создайте SurfaceTexture, чтобы задать TextureView и Preview.SurfaceProvider.
  • Получите SurfaceTexture из TextureView и задайте его в Preview.SurfaceProvider.
  • Получите Surface из SurfaceView и установите его в Preview.SurfaceProvider.

Если произойдет что-то из перечисленного, Preview прекратит передачу кадров на PreviewView.

Добавьте PreviewView в макет

Ниже показан пример PreviewView в макете:

<FrameLayout
    android:id="@+id/container">
        <androidx.camera.view.PreviewView
            android:id="@+id/previewView" />
</FrameLayout>

Запрос CameraProvider

В следующем примере кода показано, как запросить CameraProvider:

Kotlin

import androidx.camera.lifecycle.ProcessCameraProvider
import com.google.common.util.concurrent.ListenableFuture

class MainActivity : AppCompatActivity() {
    private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider>
    override fun onCreate(savedInstanceState: Bundle?) {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
    }
}

Java

import androidx.camera.lifecycle.ProcessCameraProvider
import com.google.common.util.concurrent.ListenableFuture

public class MainActivity extends AppCompatActivity {
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
    }
}

Проверьте доступность CameraProvider

После запроса CameraProvider убедитесь, что инициализация прошла успешно, когда представление создано. Ниже показано, как это сделать.

Kotlin

cameraProviderFuture.addListener(Runnable {
    val cameraProvider = cameraProviderFuture.get()
    bindPreview(cameraProvider)
}, ContextCompat.getMainExecutor(this))

Java

cameraProviderFuture.addListener(() -> {
    try {
        ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
        bindPreview(cameraProvider);
    } catch (ExecutionException | InterruptedException e) {
        // No errors need to be handled for this Future.
        // This should never be reached.
    }
}, ContextCompat.getMainExecutor(this));

Пример использования функции bindPreview приведен в следующем разделе.

Выберите камеру и привяжите жизненный цикл и способы использования

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

  1. Создайте Preview.
  2. Выберите нужный вариант камеры LensFacing.
  3. Привяжите выбранную камеру и все варианты использования к жизненному циклу.
  4. Подключите Preview к PreviewView.

Пример кода:

Kotlin

fun bindPreview(cameraProvider : ProcessCameraProvider) {
    var preview : Preview = Preview.Builder()
            .build()

    var cameraSelector : CameraSelector = CameraSelector.Builder()
          .requireLensFacing(CameraSelector.LENS_FACING_BACK)
          .build()

    preview.setSurfaceProvider(previewView.getSurfaceProvider())

    var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
}

Java

void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
    Preview preview = new Preview.Builder()
            .build();

    CameraSelector cameraSelector = new CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build();

    preview.setSurfaceProvider(previewView.getSurfaceProvider());

    Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview);
}

Обратите внимание, что bindToLifecycle() возвращает объект Camera. Подробнее о настройках камеры, таких как масштаб и экспозиция…

Вы завершили реализацию предварительного просмотра с камеры. Создайте приложение и убедитесь, что предварительный просмотр работает правильно.

Дополнительные элементы управления для PreviewView

CameraX PreviewView предоставляет дополнительные API для настройки таких свойств, как:

Режим реализации

PreviewView может использовать один из следующих режимов для рендеринга потока предварительного просмотра в целевом объекте View:

  • PERFORMANCE – режим по умолчанию. PreviewView использует SurfaceView для показа видеопотока, но в некоторых случаях переключается на TextureView. SurfaceView имеет выделенную поверхность для рисования, которая с большей вероятностью будет реализована с аппаратным оверлеем с помощью внутреннего аппаратного композитора, особенно если поверх видео предварительного просмотра нет других элементов пользовательского интерфейса (например, кнопок). При отрисовке с аппаратным оверлеем кадры видео не проходят через графический процессор, что может снизить энергопотребление и задержку.

  • COMPATIBLE. В этом режиме PreviewView использует TextureView, у которого, в отличие от SurfaceView, нет выделенной поверхности для рисования. В результате видео отображается со смешиванием. На этом этапе приложение может выполнять дополнительную обработку, например масштабировать и поворачивать видео без ограничений.

Используйте PreviewView.setImplementationMode(), чтобы выбрать режим реализации, подходящий для вашего приложения. Если режим PERFORMANCE по умолчанию не подходит для вашего приложения, в примере кода ниже показано, как задать режим COMPATIBLE:

Kotlin

// viewFinder is a PreviewView instance
viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE

Тип шкалы

Если разрешение видео в предварительном просмотре отличается от размеров целевого PreviewView, видеоконтент нужно подогнать под размер экрана, обрезав его или добавив черные полосы (сохранив исходное соотношение сторон). Для этого в PreviewView предусмотрены следующие ScaleTypes:

  • FIT_CENTER, FIT_START и FIT_END для кашетирования. Видеоконтент масштабируется (увеличивается или уменьшается) до максимально возможного размера, который может быть показан в целевом объекте PreviewView. Однако, хотя полный кадр видео виден, часть экрана может оставаться пустой. В зависимости от выбранного типа масштабирования кадр видео выравнивается по центру, началу или концу целевого представления.

  • FILL_CENTER, FILL_START, FILL_END для кадрирования. Если соотношение сторон видео не равно PreviewView, то оно будет показано не полностью, но заполнит весь экран PreviewView.

По умолчанию CameraX использует тип масштабирования FILL_CENTER. Используйте PreviewView.setScaleType(), чтобы задать тип масштабирования, наиболее подходящий для вашего приложения. В следующем примере кода задается тип масштабирования FIT_CENTER:

Kotlin

// viewFinder is a PreviewView instance
viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER

Процесс показа видео состоит из следующих этапов:

  1. Чтобы изменить масштаб видео:
    • Для типов масштабирования FIT_* масштабируйте видео с помощью min(dst.width/src.width, dst.height/src.height).
    • Для типов масштабирования FILL_* масштабируйте видео с помощью max(dst.width/src.width, dst.height/src.height).
  2. Выровняйте масштабированное видео по целевому элементу PreviewView:
    • Для FIT_CENTER/FILL_CENTER выровняйте по центру масштабированное видео и целевую страницу PreviewView.
    • Для FIT_START/FILL_START выровняйте масштабированное видео и целевой элемент PreviewView по верхнему левому углу.
    • Для FIT_END/FILL_END выровняйте масштабированное видео и целевой элемент PreviewView по правому нижнему углу каждого из них.

Например, вот исходное видео размером 640 x 480 и целевое видео размером 1920 x 1080: PreviewView

Изображение, на котором сравниваются видео размером 640 x 480 и предварительный просмотр размером 1920 x 1080 пикселей

На изображении ниже показан процесс масштабирования FIT_START / FIT_CENTER / FIT_END.

Изображение, показывающее процесс масштабирования FIT_START, FIT_CENTER и FIT_END

Вот как это работает:

  1. Масштабируйте кадр видео (сохраняя исходное соотношение сторон) с помощью min(1920/640, 1080/480) = 2.25, чтобы получить промежуточный кадр видео размером 1440 x 1080.
  2. Выровняйте кадр видео 1440 x 1080 по кадру 1920 x 1080 PreviewView.
    • Для FIT_CENTER выровняйте кадр видео по центру окна PreviewView. Первые и последние 240 пикселей столбцов PreviewView пустые.
    • Для FIT_START выровняйте кадр видео по началу (левому верхнему углу) окна PreviewView. Последние 480 столбцов пикселей в PreviewView пустые.
    • Для FIT_END выровняйте кадр видео по концу (правому нижнему углу) окна PreviewView. Первые 480 пикселей столбцов PreviewView пусты.

На изображении ниже показан процесс масштабирования FILL_START / FILL_CENTER / FILL_END.

Изображение, показывающее процесс масштабирования FILL_START, FILL_CENTER и FILL_END

Вот как это работает:

  1. Масштабируйте кадр видео с помощью max(1920/640, 1080/480) = 3, чтобы получить промежуточный кадр видео размером 1920 x 1440 (что больше размера PreviewView).
  2. Кадрируйте кадр видео 1920 x 1440, чтобы он помещался в окно PreviewView 1920 x 1080.
    • Для FILL_CENTER вырежьте область 1920 x 1080 из центра масштабированного видео 1920 x 1440. Верхние и нижние 180 строк видео не видны.
    • Для FILL_START обрежьте видео 1920 x 1440 до 1920 x 1080, начиная с начала. Нижние 360 строк видео не видны.
    • Для FILL_END обрежьте видео с разрешением 1920 x 1440 до 1920 x 1080 с конца. Верхние 360 строк видео не видны.

Дополнительные ресурсы

Чтобы узнать больше о CameraX, ознакомьтесь со следующими дополнительными ресурсами.

Практическая работа

  • Начало работы с CameraX
  • Пример кода

  • Примеры приложений CameraX