Bild-Dekodierung und Manipulation mit JNI auf Android

8

Hintergrund

Bei einigen Apps ist es wichtig, große Bilder ohne OOM und auch schnell zu verarbeiten.

Dafür kann JNI (oder pigscript, das leider an Dokumentation fehlt) eine nette Lösung sein.

In der Vergangenheit war es mir gelungen, JNI zu verwenden, um riesige Bitmaps zu drehen, während OOM vermieden wurde (link hier , hier und hier ). es war eine schöne (aber nervend harte) Erfahrung, aber am Ende hat es funktioniert.

das Problem

Das Android-Framework hat viele Funktionen, um Bitmaps zu handhaben, aber ich habe keine Ahnung, was die Situation auf der JNI-Seite ist.

Ich weiß bereits, wie man eine Bitmap von androids "Java-Welt" an die "JNI-Welt" und zurück übergibt.

Was ich nicht weiß ist, welche Funktionen ich auf der JNI-Seite verwenden kann, um mir mit Bitmaps zu helfen.

Ich möchte alle Bildoperationen (einschließlich der Dekodierung) auf JNI durchführen können, so dass ich mir keine Sorgen um OOM machen muss, wenn große Bilder angezeigt werden, und am Ende des Prozesses könnte ich die Daten konvertieren zu Java-Bitmap (um den Benutzer anzuzeigen) und / oder schreiben Sie es in eine Datei.

Ich möchte die Daten auf der JNI-Seite nicht in eine Java-Bitmap konvertieren, nur um diese Operationen ausführen zu können.

Wie sich herausstellt, gibt es einige Bibliotheken, die viele Funktionen bieten (wie JavaCV ) >), aber sie sind ziemlich groß und ich bin mir nicht ganz sicher über ihre Funktionen und wenn sie wirklich die Dekodierung auf der JNI-Seite machen, würde ich lieber wissen, was über die eingebaute JNI-Funktion möglich ist von Android stattdessen.

die Frage

Welche Funktionen stehen für die Bildbearbeitung auf der JNI-Seite auf Android zur Verfügung?

zum Beispiel, wie könnte ich Gesichtserkennung auf Bitmaps ausführen, Matrizen anwenden, Bitmaps verkleinern, Bitmaps skalieren und so weiter ...?

Für einige der Operationen kann ich mir bereits einen Weg vorstellen, sie zu implementieren (die Skalierung von Bildern ist ziemlich einfach und Wikipedia kann sehr hilfreich sein), aber einige sind sehr komplex.

selbst wenn ich die Operationen selbst implementiere, haben vielleicht andere es viel effizienter gemacht und an so viele Optimierungen gedacht, die C / C ++ haben kann.

bin ich wirklich alleine, wenn ich auf die JNI-Seite von Android gehe, wo ich alles von Grund auf neu implementieren muss?

nur um klarzustellen, was mich interessiert, ist:

Eingabe Bitmap auf Java - & gt; Bildmanipulation rein in JNI und C / C ++ (keine Konvertierung in Java-Objekte überhaupt) - & gt; Ausgabe-Bitmap auf Java.

    
android developer 26.07.2013, 15:20
quelle

2 Antworten

5

"eingebaute JNI-Funktion von Android" ist eine Art Oxymoron. Es ist technisch korrekt, dass viele Android Framework Java-Klassen JNI irgendwo in der Kette verwenden, um native Bibliotheken aufzurufen.

Aber es gibt drei Vorbehalte bezüglich dieser Aussage.

  1. Dies sind "Implementierungsdetails" und können sich ohne vorherige Ankündigung in jeder nächsten Version von Android oder einem anderen Zweig (z. B. Kindle) oder sogar einer OEM-Version ändern, die nicht als " fork " (z. B. von Samsung oder für Quallcom SOC gebaut).

  2. Die Art und Weise, wie native Methoden in Java-Kernklassen implementiert werden, unterscheidet sich vom "klassischen" JNI. Diese Methoden werden von der JVM vorab geladen und zwischengespeichert und leiden daher nicht an dem für JNI-Aufrufe typischen Overhead.

  3. Es gibt nichts, was Ihr Java- oder nativer Code tun kann, um direkt mit den JNI-Methoden anderer Klassen zu interagieren, insbesondere mit Klassen, die das System-Framework bilden.

Nach alldem können Sie den Quellcode von Android studieren, um die nativen Bibliotheken zu finden, die spezifische Klassen und Methoden unterstützen (z. B. Gesichtserkennung), und verwenden Sie diese Bibliotheken in Ihrem nativen Code oder erstellen Sie eine eigene JNI-Ebene, um diese Bibliotheken aus Ihrem Java-Code zu verwenden.

Um ein konkretes Beispiel zu nennen: Gesichtserkennung in Android wird über android.media.FaceDetector Klasse, die libFFTEm.so lädt. Sie können sich den nativen Code ansehen und ihn nach Belieben verwenden. Sie sollten nicht davon ausgehen, dass libFFTEm.so auf dem Gerät vorhanden ist oder dass die Bibliothek auf dem Gerät dieselbe API hat.

Aber in diesem speziellen Fall ist das kein Problem, weil die gesamte Arbeit von neven vollständig softwarebasiert ist. Daher können Sie diesen Code in seiner Gesamtheit oder nur in relevanten Teilen davon kopieren und in Ihre native Bibliothek integrieren. Beachten Sie, dass Sie für viele Geräte einfach /system/lib/libFFTEm.so laden und verwenden können und niemals Unbehagen verspüren, bis Sie auf ein System stoßen, das sich schlecht benimmt.

Eine bemerkenswerte Schlussfolgerung, die Sie aus dem nativen Code ziehen können, ist dass die zugrundeliegenden Algorithmen die Farbinformation ignorieren. Wenn das Bild, für das Sie Gesichtskoordinaten suchen möchten, aus der YUV-Quelle stammt, können Sie daher viel Aufwand vermeiden, wenn Sie

aufrufen %Vor%

direkt mit Ihrem YUV (oder Y) Byte-Array, anstatt es in RGB und zurück zu YUV in android.media.FaceDetector.findFaces () . Wenn Ihr YUV-Puffer aus Java stammt, können Sie Ihre eigene Klasse YuvFaceDetector erstellen, die eine Kopie von android.media.FaceDetector mit dem einzigen Unterschied, dass YuvFaceDetector.findFaces() nur Y (Luminanz) -Werte anstelle einer Bitmap verwendet und die RGB zu Y Konvertierung vermeidet.

Einige andere Situationen sind nicht so einfach. Zum Beispiel sind die Video-Codecs eng mit der Hardware-Plattform verbunden und Sie können den Code nicht einfach von libstagefright.so zu Ihrem Projekt. Jpeg Codec ist ein besonderes Tier. In modernen Systemen (IIRC, seit 2.2) können Sie erwarten, dass /system/lib/libjpeg.so vorhanden ist. Aber viele Plattformen haben auch viel effizientere HW-Implementierungen von Jpeg-Codecs durch libstagefright.so oder OpenMAX, und oft werden diese in android.graphics.Bitmap.compress () und android.graphics.BitmapFactory.decode *** () Methoden.

Und es gibt auch einen optimierten libjpeg-turbo , der gegenüber% Vorteile hat. co_de%.

    
Alex Cohn 06.02.2014 11:05
quelle
1

Es scheint, dass sich Ihre Frage eher auf C / C ++ - Bildverarbeitungsbibliotheken bezieht als auf Android. Zu diesem Zweck finden Sie hier einige weitere StackOverflow-Fragen, die möglicherweise nützliche Informationen enthalten:

Schnelle plattformübergreifende C / C ++ Bildverarbeitungsbibliotheken

C ++ - Bildverarbeitungsbibliotheken

    
jph 10.02.2014 23:09
quelle