Подтвердить что ты не робот

Экран камеры/предварительный просмотр в полноэкранном режиме не поддерживает соотношение сторон - изображение искажено, растягивается, чтобы поместиться на экране

Я разработал небольшое приложение для отображения предварительного просмотра камеры в полноэкранном режиме. Я использую Camera API для этого.

Это макет действия:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <!-- This is the container for the camera preview screen -->
    <FrameLayout android:id="@+id/camera_preview"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"/>
</LinearLayout>

Когда устройство находится в портретном режиме, дисплей масштабируется по вертикали, чтобы соответствовать высоте экрана устройства, поэтому соотношение сторон не совпадает с форматом изображения на встроенной камере. Это 2 изображения, которые лучше объясняют, что я говорю:

enter image description hereenter image description here

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

Мне нужен предварительный просмотр камеры в полноэкранном режиме, независимо от размера предварительного просмотра, указанного getSupportedPreviewSizes() mehod и без искажений. Есть ли способ сделать это? Есть ли способ поддерживать правильное соотношение сторон при просмотре камеры во весь экран? Я ожидал, что это будет сделано автоматически ОС - обрезание изображения в соответствии с запрошенным разрешением при сохранении пропорций, но этого не происходит.

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

Я разместил здесь: https://www.dropbox.com/s/3d52xt8kazynsae/CameraFullScreen.7z?v=0mcn весь проект, который я сделал.

Любая идея/решение для меня важнее. Большое спасибо.

=============================================== =========================

Обновление из-за ответа ss1271:

Я немного проанализирую резолюции, которые вы писали выше для Samsung Galaxy Ace II.

I. Разрешение экрана: 480x800 - соотношение сторон 3: 5 = 0,6

II. getSupportedPreviewSizes. Я почти уверен, что эти значения взяты из задней камеры. Ниже приведено соотношение сторон для этих разрешений:

   2560x1920   - 0,75

   2560x1536   - 0,60

   2048x1536   - 0,75

   2048x1232   - 0,60

   960x720     - 0,75

   640x480     - 0,75

Итак, ваш метод вернет Size, соответствующий 2560x1536 или 2048x1232 - они имеют такое же соотношение сторон, что и разрешение экрана, и использование этих значений не будет искажать изображение. Проблема для меня в том, что я не могу использовать столь большие разрешения, так как я беру 6 кадров в секунду, и их нужно сохранять с меньшим разрешением.

Ниже приводятся некоторые результаты от устройства Samsung S2:

I. Разрешение экрана: 480 x 800 - соотношение сторон 3: 5 = 0,6

II. Камера заднего вида
а). getSupportedPreviewSizes:

800 / 480   - 480/800 = 0,60
800 / 450   - 450/800 = 0,56
720 / 480   - 0,66 
640 / 480   - 0,75
352 / 288   - 0,81
320 / 240   - 0,75
176 / 144   - 0,81

б). Встроенные разрешения камеры:

3264 / 2448  - 0,75  - not full screen
3264 / 1968  - 0,60  - FULL SCREEN (since has the same aspect ratio as device screen)
2048 / 1536  - 0,75  - not full screen
2048 / 1232  - 0,60  - FULL SCREEN (same aspect ratio as device screen)
800 / 480    - 0,60  - FULL SCREEN (same aspect ratio as device screen)
640 / 480    - 0, 75 - not full screen

III. Передняя камера
а). getSupportedPreviewSizes:

640 / 480   - 0,75
352 / 288   - 0,81
320 / 240   - 0,75
176 / 144   - 0,81

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

Для S2, камеры заднего вида, мне интересно, почему метод getSupportedPreviewSizes() не возвращает те же разрешения, что и у Native camera, или те, что отображаются на собственной камере, - это размеры изображения? Мне интересно, почему у меня нет таких возможностей, как 3264/1968, 2048/1232, данный методом getSupportedPreviewSizes()? : enter image description here

4b9b3361

Ответ 1

Вкратце, вы можете сделать предварительный просмотр камеры в полноэкранном режиме, однако вам нужно будет найти подходящие размеры среди поддерживаемых размеров предварительного просмотра самостоятельно, только если пользовательский предварительный просмотр камеры - это то, что вы хотите.

По вашему вопросу, согласно Android Developers - Camera

Если вы хотите установить определенный размер для предварительного просмотра камеры, установите это в методе surfaceChanged(), как указано в комментариях выше. когда установите размер предварительного просмотра, должен использовать значения из getSupportedPreviewSizes(). Не устанавливайте произвольные значения в setPreviewSize() метод.

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

Например, Samsung Galaxy Ace II имеет экран разрешения 480x800, читая Size, возвращенный с getSupportedPreviewSizes(), его камера поддерживает:

2560x1920

2560x1536

2048x1536

2048x1232

960x720

640х480

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

Реализация поиска правильного размера предварительного просмотра не является чем-то сложным. Общим методом для этого было бы что-то вроде этого:

    /**
     * Calculate the optimal size of camera preview
     * @param sizes
     * @param w
     * @param h
     * @return
     */
    private Size getOptimalSize(List<Size> sizes, int w, int h) {

        final double ASPECT_TOLERANCE = 0.2;        
        double targetRatio = (double) w / h;         
        if (sizes == null)             
            return null;          
        Size optimalSize = null;         
        double minDiff = Double.MAX_VALUE;          
        int targetHeight = h;          
        // Try to find an size match aspect ratio and size         
        for (Size size : sizes) 
        {             
//          Log.d("CameraActivity", "Checking size " + size.width + "w " + size.height + "h");            
            double ratio = (double) size.width / size.height;            
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)                
                continue;             
            if (Math.abs(size.height - targetHeight) < minDiff) 
            {                 
                optimalSize = size;                 
                minDiff = Math.abs(size.height - targetHeight);             
            }         
        }          
        // Cannot find the one match the aspect ratio, ignore the requirement     

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

        SharedPreferences previewSizePref;
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            previewSizePref = getSharedPreferences("PREVIEW_PREF",MODE_PRIVATE);
        } else {
            previewSizePref = getSharedPreferences("FRONT_PREVIEW_PREF",MODE_PRIVATE);
        }

        SharedPreferences.Editor prefEditor = previewSizePref.edit();
        prefEditor.putInt("width", optimalSize.width);
        prefEditor.putInt("height", optimalSize.height);

        prefEditor.commit();

//      Log.d("CameraActivity", "Using size: " + optimalSize.width + "w " + optimalSize.height + "h");            
        return optimalSize;     
    }

И вы также можете сделать аналогичный поиск подходящих размеров камеры (размер выходного изображения).

Примечание. Я нашел исходную версию вышеуказанного кода из Интернета, и я сделал некоторые изменения/оптимизации для своей собственной цели.

Пожалуйста, дайте мне знать, если это сработает для вас.

Ответ 2

Я столкнулся с той же проблемой в Camera2 API, я использовал размер и формат просмотра формата для решения проблемы. Вы также можете сделать то же самое с вашим API-интерфейсом камеры.