Установка предварительного просмотра камеры на SurfaceView больше, чем на дисплее
У меня есть приложение для Android, которое должно полноэкранно просматривать предварительный просмотр камеры независимо от размера предварительного просмотра, указанного getSupportedPreviewSizes()
без искажений. Я ожидаю, что это обрезает предварительный просмотр на некоторую величину как по высоте, так и по ширине, но это меня не касается. Причина, по которой я пытаюсь это сделать, состоит в том, что некоторые камеры Android (например, камера переднего обзора Samsung Galaxy SII) не возвращают никаких предварительных изображений с тем же соотношением сторон, что и дисплей, и поэтому их необходимо растягивать и обрезать.
Возможно ли полностью увеличить предварительный просмотр камеры до большего размера дисплея? Можно увеличить SurfaceView больше, чем размеры пикселов предварительного просмотра, возвращенные простым настройкой параметров макета поверхности to match_parent, но это приводит к искажению в некотором направлении и только возможно до тех пор, пока предварительный просмотр не заполнит дисплей. Это, по-видимому, указывает на невозможность предварительного просмотра вне дисплея, а аппаратное обеспечение (или ОС) ограничивает такое поведение.
Существует еще один вопрос по этой теме, но этот вопрос утверждает, что невозможно создать SurfaceView больше размеров экрана, что является ложным, как я нашел с протоколированием. Однако, похоже, что просмотр камеры, однако, не может увеличиться до полного размера огромного SurfaceView.
Моя попытка:
У меня есть относительный макет, внутри него - FrameLayout, и внутри этого я создаю SurfaceView. Ширина всей относительной компоновки установлена ниже на 635dp, что вдвое превышает размер экрана устройства. FrameLayout соответствует этому размеру, и SurfaceView также добавляется программно позже
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/camera_activity_layout"
android:layout_width="635dp"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</RelativeLayout>
Ниже приведен код, который получает и устанавливает размер предварительного просмотра. Здесь я хочу, чтобы предварительный просмотр камеры расширялся, чтобы заполнить весь FrameLayout (в два раза ширину экрана). В представлении отображаются и полностью уничтожаются, поэтому я удаляю код, не относящийся к этому конкретному вопросу, потому что он отвлекает от основного вопроса и мою попытку легко и просто увеличить представление до некоторого размера большего размера.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
...
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
final DisplayMetrics dm = this.getResources().getDisplayMetrics();
//getBestPreviewSize returns the best preview size, don't worry
//but some devices do not return one for all camera matching the aspect ratio
cameraSize = getBestPreviewSize(parameters, dm.heightPixels, dm.widthPixels);
if (cameraSize!=null) {
parameters.setPreviewSize(cameraSize.width, cameraSize.height);
mCamera.setParameters(parameters);
}
FrameLayout.LayoutParams frameParams = (FrameLayout.LayoutParams) this.getLayoutParams();
frameParams.width = 800; //For argument sake making this ~double the width of the display. Same result occurs if I use MATCH_PARENT
frameParams.height = LayoutParams.MATCH_PARENT;
this.setLayoutParams(frameParams);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
Log.d("surfChange","W/H of CamPreview (child) is "+this.getWidth()+"/"+this.getHeight()+" while parent is ");
Log.d("surfChange","W/H of holder (child) is "+mHolder.getSurfaceFrame().width()+"/"+mHolder.getSurfaceFrame().height()+" while parent is ");
} catch (Exception e){
}
}
};
Я обеспокоен тем, что единственный способ добиться успеха в этом начинании - это как-то сделать поверхность openGL, но этот очевидно, может быть слишком медленным в полном цвете. Это также боль, если предварительный просмотр камеры можно просто растянуть и обрезать.
Заранее благодарим за любые попытки решения.
Ответы
Ответ 1
Хорошо, я знаю, что это очень поздно, как ответ, но это возможно. Ниже приведен код из образца Android SDK. Чтобы увидеть остальную часть кода для реализации этой загрузки, образцы sdk android и перейдите к Samples/android-10(one I used, could try whichever you want to target)/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
class PreviewSurface extends ViewGroup implements SurfaceHolder.Callback {
...
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
// Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
}
этот код предназначен для предварительного просмотра до наименьшего размера (что не испортит соотношение aspcect) и центра, чтобы иметь черные полосы в другом измерении. Но если вы перевернете >
, чтобы быть <
, вы достигнете того, чего хотите. Пример:
if (width * previewHeight < height * previewWidth) {...