Ich habe versucht, die CameraX-Bibliothek mit Android Java Fragment zu verwenden

Ich habe CameraX ausprobiert, das bei Google I / O 2019 auf Fragment in Java eingeführt wurde, daher werde ich es kurz vorstellen.

Vorbereitung

Es ist einfach, mit dem offiziellen [Tutorial] fortzufahren (https://codelabs.developers.google.com/codelabs/camerax-getting-started/#0), also werde ich mit dem Betrachten fortfahren.

Das Erstellen eines Projekts und das Hinzufügen von Abhängigkeiten entsprechen den Anweisungen im Lernprogramm. Daher werde ich sie in diesem Artikel weglassen.

Ansicht für Vorschau hinzugefügt

Fügen Sie textureView zu layout.xml hinzu, um es von Fragment anzuzeigen.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF">

    <TextureView
        android:id="@+id/view_finder"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <RelativeLayout
        android:id="@+id/camera_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#456700"
        android:padding="15dp">

        <ImageButton
            android:id="@+id/camera_back"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/common_backbtn"
            android:layout_alignParentLeft="true"/>

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/camera_bottom_control"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#456700"
        android:padding="20dp">

        <Button
            android:id="@+id/capture_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="Schießen"
            />
        
    </RelativeLayout>

</RelativeLayout>

Es sieht so aus ↓ スクリーンショット 2019-12-12 15.20.00.png

TextureView wird auf der gesamten Oberfläche platziert und mit Bildschirmelementen überlagert.

Kamera starten

Sie müssen lediglich die Vorschau einstellen und an den Fragmentlebenszyklus binden.

Es ist einfach, weil Sie nur die von CameraX.bindToLifecycle erstellte PreviewConfig binden.

public void startCamera() {
	PreviewConfig.Builder builder = new PreviewConfig.Builder();

	builder.setTargetResolution(new Size(App.width, App.height));
	PreviewConfig previewConfig = builder.build();

	preview = new Preview(previewConfig);
	preview.setOnPreviewOutputUpdateListener(new Preview.OnPreviewOutputUpdateListener() {
		@Override
		public void onUpdated(@NonNull Preview.PreviewOutput output) {
			ViewGroup viewGroup = (ViewGroup) viewFinder.getParent();
			viewGroup.removeView(viewFinder);
			viewGroup.addView(viewFinder, 0);

			viewFinder.setSurfaceTexture(output.getSurfaceTexture());
			updateTransform();
		}
	});
	CameraX.bindToLifecycle(this, preview);
}
    
public void updateTransform() {
	Matrix matrix = new Matrix();

	float centerX = viewFinder.getWidth() / 2f;
	float centerY = viewFinder.getHeight() / 2f;

	float rotationDegrees;
	switch (viewFinder.getDisplay().getRotation()) {
		case Surface.ROTATION_0:
			rotationDegrees = 0f;
			break;
		case Surface.ROTATION_90:
			rotationDegrees = 90f;
			break;
		case Surface.ROTATION_180:
			rotationDegrees = 180f;
			break;
		case Surface.ROTATION_270:
			rotationDegrees = 270f;
			break;
		default:
			return;
	}

	matrix.postRotate(-rotationDegrees, centerX, centerY);
	viewFinder.setTransform(matrix);
}

Schreiben Sie dies einfach und wenn Sie startCamera aufrufen, nachdem Sie die Erlaubnis der Kamera erhalten haben, wird die Vorschau angezeigt.

Kameraerfassung

Sie können nichts tun, indem Sie eine Vorschau der Kamera anzeigen. Lassen Sie uns das Bild also in dem Moment aufnehmen, in dem die Taste capture_button gedrückt wird.

Fügen Sie den folgenden Code hinzu, bevor Sie die obige startCamera-Methode binden.

ImageCaptureConfig.Builder imageBuilder = new ImageCaptureConfig.Builder();
imageBuilder.setTargetResolution(new Size(App.width, App.height));
imageBuilder.setCaptureMode(ImageCapture.CaptureMode.MAX_QUALITY);
imageBuilder.setFlashMode(FlashMode.ON);
ImageCaptureConfig imageCaptureConfig = imageBuilder.build();
imageCapture = new ImageCapture(imageCaptureConfig);

Ich richte die Bilderfassung ein. Hier wird Flash aktiviert, um die Qualität zu maximieren. Fügen Sie nach dem Erstellen der ImageCaptureConfig auch die ImageCaptureConfig zur Bindemethode hinzu.

CameraX.bindToLifecycle(this, preview, imageCapture);

Jetzt können Sie loslegen.

Sie können erfassen, indem Sie imageCapture.takePicture () aufrufen. Legen Sie also ein Ereignis für die Schaltfläche fest.

btnCamera.setOnClickListener((View v) -> {

	imageCapture.takePicture(CameraFragment.this, new ImageCapture.OnImageCapturedListener() {
			@Override
			public void onCaptureSuccess(ImageProxy imageProxy, int rotationDegrees) {

			}

			@Override
			public void onError(
				@NonNull ImageCapture.ImageCaptureError imageCaptureError, @NonNull String message,
								@Nullable Throwable cause) {

			}
		});
	}
});
	

Für das Argument von takePicture wird Executor benötigt. Daher implementieren wir hier Executor in Fragment, damit UiThread die Verarbeitung nach dem Aufnehmen eines Bildes ausführen kann.


public class CameraFragment implements Executor {

    @Override
    public void execute(Runnable command) {
		if(getActivity() != null){
			getActivity().runOnUiThread(command);
		}
	}
}

Wenn Sie die Aufnahmetaste drücken und die Aufnahme erfolgreich ist, wird onCaptureSuccess (ImageProxy imageProxy, int rotationDegrees) aufgerufen und das Bild kann von imageProxy aufgenommen werden!

Impressionen

Es ist einfach ...

Was wurde auf Camera2 geschrieben?

Es ist ein schwieriges Wort, die Kamera zu montieren, also habe ich darauf gewartet.

Suchtpunkt

Nun, ich habe es sehr leicht beschrieben, aber ich werde es vorstellen, weil es einige süchtig machende Punkte gab.

① Der Verschluss ertönt nicht!

Es ist kein Verschlussgeräusch zu hören. Ja.

Ich habe nach etwas gesucht, das in den Aufnahmeeinstellungen eingestellt werden kann, aber es ist nirgendwo zu finden ...

Wenn Sie es klingen lassen möchten, versuchen Sie es zu erzwingen.

MediaActionSound sound = new MediaActionSound();
sound.play(MediaActionSound.SHUTTER_CLICK);

② ImageProxy Wie konvertieren Sie in Bitmap?

Ja, das ist es.

public Bitmap imageProxyToBitmap(ImageProxy image, int rotationDegrees) {
	ImageProxy.PlaneProxy planeProxy = image.getPlanes()[0];
	ByteBuffer buffer = planeProxy.getBuffer();
	byte[] bytes = new byte[buffer.remaining()];
	buffer.get(bytes);

	Matrix mat = new Matrix();
	mat.postRotate(rotationDegrees);

	if (rotationDegrees != 0) {
		return rotate(BitmapFactory.decodeByteArray(bytes, 0, bytes.length), rotationDegrees);
	} else {
		return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
	}
}

public Bitmap rotate(Bitmap in, int angle) {
		Matrix mat = new Matrix();
		mat.postRotate(angle);
		return Bitmap.createBitmap(in, 0, 0, in.getWidth(), in.getHeight(), mat, true);
}

③ So ordnen Sie TextureView an

F. Warum befindet sich TextureView in der gesamten Layoutdatei? Sollte es nicht in den Vorschaubereich passen?

A. Ich wage es, alles noch einmal zu machen.

Wenn die Größe der Vorschau und das Seitenverhältnis der TextureView-Größe nicht übereinstimmen, wird die Vorschau verzerrt und angezeigt. Wenn Sie einen Bildschirm mit einem Vorschaubereich erstellen, der im Vergleich zur Bildschirmgröße klein ist, haben Sie festgestellt, dass die TextureView an den Vorschaubereich angepasst ist. Die Vorschau ist sehr schwer zu sehen, da die Dinge in der TextureView in verkleinerter Größe angezeigt werden.

Wenn Sie TextureView auf der gesamten Oberfläche platzieren, werden alle oben genannten Probleme gelöst, und Sie können mit dem gleichen Gefühl wie die Kamera auf der gesamten Oberfläche fotografieren, die Sie normalerweise verwenden, sodass Sie ohne Beschwerden fotografieren können.

Wenn Sie nur ein Bild des für den Benutzer sichtbaren Bereichs wünschen, können Sie es nach der Aufnahme ausschneiden.

Am Ende

Bitte beachten Sie, dass CameraX immer noch eine Alpha-Version ist, sodass sich die Benutzeroberfläche in der Release-Version ändern kann.

Obwohl hier nicht vorgestellt, scheint es eine API zu geben, die die Verwendung gerätespezifischer Herstellereffekte (unscharf, HDR, Nachtansicht) vereinfacht. Daher möchte ich dies auch in Zukunft versuchen.

Recommended Posts

Ich habe versucht, die CameraX-Bibliothek mit Android Java Fragment zu verwenden
Ich habe versucht, OpenCV mit Java + Tomcat zu verwenden
Ich habe versucht, Java REPL zu verwenden
Ich habe versucht, das GitHub-Repository als Bibliotheksserver zu verwenden
Ich habe versucht, mit Java zu interagieren
Ich habe versucht, UDP mit Java zu kommunizieren
Ich habe das Java-Framework "Quarkus" ausprobiert.
Ich habe mit der Lautstärketaste mit der Android-App ein Sperrmuster erstellt. Fragment Edition
Ich habe versucht, JWT in Java zu verwenden
[Android] Ich habe versucht, das Koordinatorlayout zu verwenden.
[Android] [Bibliothek] Ich habe versucht, eine Animationsbibliothek namens "Vorher Nachher Animation" zu verwenden.
Ich habe versucht, Java Memo LocalDate zu verwenden
Ich habe versucht, Google HttpClient von Java zu verwenden
Ich habe versucht, eine Android-Anwendung mit MVC zu erstellen (Java)
Ich habe versucht, die Elasticsearch-API in Java zu verwenden
Ich habe versucht, Realm mit Swift UI zu verwenden
Ich habe versucht, Scalar DL mit Docker zu verwenden
Ich habe das neue Yuan-Problem in Java ausprobiert
Ich habe versucht, OnlineConverter mit SpringBoot + JODConverter zu verwenden
Ich habe die AutoValue-Bibliothek mit Intellij ausprobiert
Versuchen Sie es mit der Wii-Fernbedienung in Java
Ich habe versucht, eine Standardauthentifizierung mit Java durchzuführen
[Android] Ich habe SQLite beendet und versucht, Realm zu verwenden
Ich habe mit Ruby einen Blackjack gemacht (ich habe versucht, Minitest zu verwenden)
[API] Ich habe versucht, die Postleitzahlensuch-API zu verwenden
Ich habe versucht, den Profiler von IntelliJ IDEA zu verwenden
Ich habe versucht, den Block mit Java zu brechen (1)
[Java] Ich habe versucht, über den Verbindungspool eine Verbindung mit Servlet (Tomcat) & MySQL & Java herzustellen
Ich habe versucht, Gson zu benutzen
Ich habe versucht, TestNG zu verwenden
Ich habe versucht, Galasa zu benutzen
Ich habe versucht, eine Datenbankverbindung in der Android-Entwicklung zu verwenden
Ich habe versucht, die Server-Push-Funktion von Servlet 4.0 zu verwenden
Ich habe versucht, TCP / IP + BIO mit JAVA zu implementieren
[Java 11] Ich habe versucht, Java auszuführen, ohne mit Javac zu kompilieren
Versuchen Sie, das Eratostenes-Sieb mithilfe der Java-Standardbibliothek zu implementieren
Ich habe versucht, SQS mit AWS Java SDK zu betreiben
Ich habe versucht, das Migration Toolkit für Anwendungsbinärdateien zu verwenden
Ich habe versucht, Log4j2 auf einem Java EE-Server zu verwenden
Ich habe versucht, mit OCR eine PDF-Datei mit Java zu verarbeiten
Ich habe versucht, Sterling Sort mit Java Collector zu implementieren
Versuchen Sie es mit globalem Hooking in Java mithilfe der JNativeHook-Bibliothek
Ich habe versucht, den Mechanismus von Emscripten mit einem deutschen Löser zu untersuchen
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.
Ich habe DI mit Ruby versucht
[Rails] Ich habe zum ersten Mal versucht, die button_to-Methode zu verwenden
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit spiritueller Technik zu erhöhen
[JDBC] Ich habe versucht, von Java aus auf die SQLite3-Datenbank zuzugreifen.
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
Ich habe Drools (Java, InputStream) ausprobiert.
[Java] Versuchen Sie, die Elemente der Json-Zeichenfolge mithilfe der Bibliothek zu bearbeiten
Ich habe versucht, Apache Wicket zu verwenden
Verwenden von Mapper mit Java (Spring)
Ich habe versucht, die Umgebung nach und nach mit Docker aufzubauen
Ich habe das FizzBuzz-Problem ausprobiert
Ich habe UPSERT mit PostgreSQL ausprobiert.