/ / Ist es möglich, die Kameravorschau zu beschneiden? - Android, Android-Kamera

Kann man eine Kameravorschau zuschneiden? - Android, Android-Kamera

Ich habe keine Möglichkeit gefunden, die Kamera-Vorschau zuzuschneiden und dann in SurfaceView anzuzeigen.

Android - Ist es möglich, die Kameravorschau zuzuschneiden?

Antworten:

6 für die Antwort № 1

Nicht direkt. Die Kamera-API lässt jetzt Offsets zu und drückt das Bild in die Oberfläche Halter. Sie können dies jedoch umgehen, indem Sie Overlays (andere Ansichten) darüber platzieren.


14 für die Antwort № 2

Sie können dies ohne Overlay-Ansichten tun (was nicht in allen Situationen funktioniert).

Fügen Sie der Unterklasse ViewGroup das SurfaceView als einziges untergeordnetes Element hinzu.

  1. Geben Sie in onMeasure die gewünschten zugeschnittenen Abmessungen an.
  2. Layouten Sie in onLayout die SurfaceView mit den nicht zugeschnittenen Dimensionen.

Grundsätzlich gilt,

public class CroppedCameraPreview extends ViewGroup {
private SurfaceView cameraPreview;
public CroppedCameraPreview( Context context ) {
super( context );
// i"d probably create and add the SurfaceView here, but it doesn"t matter
}
@Override
protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec ) {
setMeasuredDimension( croppedWidth, croppedHeight );
}
@Override
protected void onLayout( boolean changed, int l, int t, int r, int b ) {
if ( cameraPreview != null ) {
cameraPreview.layout( 0, 0, actualPreviewWidth, actualPreviewHeight );
}
}
}

7 für die Antwort № 3

Sie könnten die Kamera-Vorschau setzen (SurfaceView)in einem LinearLayout, das sich in einer ScrollView befindet. Wenn die Kameraausgabe größer als das von Ihnen festgelegte LinearLayout ist, können Sie programmgesteuert einen Bildlauf durchführen und den Benutzerscroll deaktivieren. Auf diese Weise können Sie das Beschneiden von Kameras auf einfache Weise emulieren:

<ScrollView
android:id="@+id/scrollView"
android:layout_width="640dip"
android:layout_height="282dip"
android:scrollbars="none"
android:fillViewport="true">

<LinearLayout
android:id="@+id/linearLayoutBeautyContent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/surfaceViewBeautyCamera"/>
</LinearLayout>
</ScrollView>

0 für die Antwort № 4

Der Code zum programmgesteuerten Scrollen des Bildes sieht etwa so aus:

public void setCameraOrientationOnOpen()
{
mCamera.stopPreview();
int rotation = getRotation();
Camera.Parameters currentCameraParameters = mCamera.getParameters();
List<Camera.Size> previewSizes = currentCameraParameters.getSupportedPreviewSizes();

mOptimalCameraSize = getOptimaPreviewCameraSize(previewSizes, (double)9/16);
currentCameraParameters.setPreviewSize(mOptimalCameraSize.width, mOptimalCameraSize.height);
mCamera.setParameters(currentCameraParameters);
float ratio = 100;
int ratio1 = (mSurfaceView.getLayoutParams().height * 100) / mOptimalCameraSize.width; //height
int ratio2 = (mSurfaceView.getLayoutParams().width * 100) / mOptimalCameraSize.height; //width
ratio = Math.max(ratio1, ratio2);
mSurfaceView.getLayoutParams().height = (int) ((mOptimalCameraSize.width * ratio) / 100);
mSurfaceView.getLayoutParams().width = (int) ((mOptimalCameraSize.height * ratio) / 100);
if(ratio > 100)
{
int offset = (mSurfaceView.getLayoutParams().height - mBoxHeight)/2;
mScrollView.scrollTo(0, offset); //center the image
}
mCamera.setDisplayOrientation(rotation);
mOptimalCameraSize = mCamera.getParameters().getPreviewSize();
}

Ich berechne die beste Vorschaugröße von der KameraWenden Sie für das Inhaltsfeld meiner Kamera (Verhältnis 16: 9) das berechnete Verhältnis auf das Bild an, um das gleiche Verhältnis beizubehalten, und berechnen Sie schließlich die erforderliche Bildlauffolge (das Bild würde sich in der Mitte befinden).


0 für die Antwort № 5

Erstellen Sie ein zentriertes Rahmenlayout, in dem die Kameravorschau gespeichert und mit Ansichten zum Zuschneiden überlagert wird. Wenn Sie Ihre Ansicht erstellen, dehnen Sie dynamisch eine transparente Ansicht, die ebenfalls zentriert ist.

XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000" >

<FrameLayout
android:id="@+id/camera_preview_frame"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerVertical="true" />

<View
android:id="@+id/transparent_window"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:layout_centerVertical="true"
android:background="@android:color/transparent" />

<View
android:id="@+id/black_top_box"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@id/transparent_window"
android:background="#000"/>

<View
android:id="@+id/black_bottom_box"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/transparent_window"
android:background="#000"/>
</RelativeLayout>

Dann können Sie in der OnCreate () -Methode Ihrer Aktivitätsklasse die transparente Ansicht wie folgt strecken.

CameraActivity.java

final View transView = findViewById(R.id.transparent_window);

transView.post(new Runnable() {

@Override
public void run() {
RelativeLayout.LayoutParams params;
params = (RelativeLayout.LayoutParams) transView.getLayoutParams();
params.height = transView.getWidth();
transView.setLayoutParams(params);
transView.postInvalidate();
}
});

Das ist ein Bildschirmfoto von meinem Telefon aus. Der graue Fleck in der Mitte ist der Blick der Kamera auf den Boden durch die transparente Ansicht


0 für die Antwort № 6

Hier ist eine Lösung für Orientierung = Landschaft, um @drees "hervorragende Antwort zu vervollständigen.

Fügen Sie einfach den layout-land-Ordner in den res-Ordner ein, duplizieren Sie Ihre gesamte Layout-XML und ändern Sie den Layout-Teil des @drees-Codes wie folgt:

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/background_dark" >

<FrameLayout
android:id="@+id/frameSurface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="@android:color/background_light"/>

<View
android:id="@+id/transparent_window"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerInParent="true"
android:background="@android:color/transparent" />

<View
android:id="@+id/black_top_box"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toLeftOf="@id/transparent_window"
android:background="@android:color/background_dark"/>

<View
android:id="@+id/black_bottom_box"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/transparent_window"
android:background="@android:color/background_dark"/>
</RelativeLayout>

0 für die Antwort № 7

Diese Lösung ist eine der Umgehungsmöglichkeiten für Ihre Situation. Ein Teil des Codes ist veraltet und nicht empfohlen zur Verwendung in Unternehmensprojekten, aber wenn Sie nur eine Kameravorschau anzeigen müssen, ohne sie zusammenzudrücken, reicht dies aus.
Wenn Sie ein Bild vor der Vorschau bearbeiten müssen, sollten Sie nachsehen Oberflächentextur

public class CameraPreview
extends SurfaceView
implements SurfaceHolder.Callback, Camera.PreviewCallback {

public static final String TAG = CameraPreview.class.getSimpleName();

private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;
private static final double ASPECT_RATIO = 3.0 / 4.0;

private Camera mCamera;
private SurfaceHolder mHolder;
private boolean mIsLive;
private boolean mIsPreviewing;

public CameraPreview(Context context) {
super(context);
init(context);
}

public CameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

public CameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int) (width / ASPECT_RATIO + 0.5);
setMeasuredDimension(width, height);
}

@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
//L.g().d(TAG, "onVisibilityChanged: visibility=" + visibility);
if (mIsLive) {
if (visibility == VISIBLE && !mIsPreviewing) {
startCameraPreview();
} else {
stopCameraPreview();
}
}
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
startCamera();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopCamera();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
//L.g().d(TAG, "surfaceChanged: format=" + format + ", width=" + w + ", height=" + h);
if (mHolder.getSurface() == null || mCamera == null) return;
mHolder = holder;
try {
mCamera.stopPreview();
} catch (Exception ignored) {}
try {
mCamera.setPreviewDisplay(mHolder);
if (mIsLive && mIsPreviewing) mCamera.startPreview();
} catch (Exception ignored) {}
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {

//work with camera preview

if (mIsPreviewing) camera.setOneShotPreviewCallback(this);
}

private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_SIZE_MAX_WIDTH);
}

private Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPictureSizes(), PICTURE_SIZE_MAX_WIDTH);
}

/**
* This code I found in this repository
* https://github.com/boxme/SquareCamera/blob/master/squarecamera/src/main/java/com/desmond/squarecamera/CameraFragment.java#L368
*/
private Camera.Size determineBestSize(List<Camera.Size> sizes, int widthThreshold) {
Camera.Size bestSize = null;
Camera.Size size;
int numOfSizes = sizes.size();
for (int i = 0; i < numOfSizes; i++) {
size = sizes.get(i);
boolean isDesireRatio = (size.width / 4) == (size.height / 3);
boolean isBetterSize = (bestSize == null) || size.width > bestSize.width;

if (isDesireRatio && isBetterSize) {
bestSize = size;
}
}
if (bestSize == null) {
return sizes.get(sizes.size() - 1);
}
return bestSize;
}

private void init(Context context) {
mHolder = getHolder();
mHolder.addCallback(this);
}

public void startCamera() {
if (!mIsLive) {
//L.g().d(TAG, "startCamera");
mIsPreviewing = false;
mCamera = Camera.open();
if (mCamera != null) {
try {
Camera.Parameters param = mCamera.getParameters();
Camera.Size bestPreviewSize = determineBestPreviewSize(param);
Camera.Size bestPictureSize = determineBestPictureSize(param);
param.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
param.setPictureSize(bestPictureSize.width, bestPictureSize.height);
mCamera.setParameters(param);
} catch (RuntimeException ignored) {}
try {
mCamera.setDisplayOrientation(90);
mCamera.setPreviewCallback(this);
mCamera.setPreviewDisplay(mHolder);
mIsLive = true;
} catch (Exception ignored) {}
}
//else L.g().d(TAG, "startCamera: error launching the camera");
}
}

public void stopCamera() {
if (mCamera != null && mIsLive) {
//L.g().d(TAG, "stopCamera");
mCamera.stopPreview();
mCamera.release();
mCamera = null;
mIsPreviewing = false;
mIsLive = false;
}
}

public void startCameraPreview() {
if (mCamera != null && mIsLive && !mIsPreviewing) {
//L.g().d(TAG, "startCameraPreview");
mCamera.setPreviewCallback(this);
mCamera.startPreview();
mIsPreviewing = true;
}
}

public void stopCameraPreview() {
if (mCamera != null && mIsLive && mIsPreviewing) {
//L.g().d("stopCameraPreview");
mCamera.stopPreview();
mIsPreviewing = false;
}
}
}

0 für die Antwort № 8

Nachdem ich in den letzten Tagen viel gesucht habe, glaube ich, dass ich meine Lösung hier posten muss.

Das einzige, was ich geschafft habe und was gut funktioniert, ist eine Skala hinzuzufügen.

Ich wollte eine Texturansicht mit einem Teil der Kameraausgabe erstellen, aber ich konnte das nicht tun, ohne dass die Vorschau verzerrt wurde.

Nachdem ich mich für die beste Auflösung für das Kamera / Bildschirm-Verhältnis entschieden habe, erhalte ich das Skalierungsverhältnis zwischen der Kameraerfassungshöhe und der Höhe, die ich anzeigen möchte.

mPreviewSize = chooseOptimalSize(...);

int viewHeight = getDP(this, R.dimen.videoCaptureHeight);
float scaleY = mPreviewSize.getHeight() / viewHeight;
setScaleY(scaleY);