Android ImageReader.acquireLatestImage retourne invalide JPG
Je suis en utilisant Android ImageReader classe pour recevoir des Bitmaps de MediaProjection.createVirtualDisplay méthode.
Mon code ressemble tellement loin de cela:
mProjection.createVirtualDisplay("test", width, height, density, flags, mImageReader.getSurface(), new VirtualDisplayCallback(), mHandler);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = mImageReader.acquireLatestImage();
final Image.Plane[] planes = image.getPlanes();
final ByteBuffer buffer = planes[0].getBuffer();
final byte[] data = new byte[buffer.capacity()];
buffer.get(data);
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
if (bitmap==null)
Log.e(TAG, "bitmap is null");
} catch (Exception e) {
if (image!=null)
image.close();
}
}
}, mHandler);
Le problème est que BitmapFactory ne peut pas décoder des données[] retour à la Bitmap, c'est à dire BitmapFactory renvoie toujours null. Les seuls messages je vois de logcat viennent de android_media_ImageReader.cpp et comme ça:
D/ImageReader_JNI(1432): ImageReader_imageSetup: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.
W/ImageReader_JNI(1432): Image_getJpegSize: No JPEG header detected, defaulting to size=width=3891200
Image de l'objet renvoyé par acquireLatestImage n'est pas nul, mais pas valide en JPEG, j'ai essayé de vérifier avec le test suivant qui échoue:
if((buf [0] & 0xFF) == 0xFF && (buf[1] & 0xFF) == 0xD8 && (buf[2] & 0xFF) == 0xFF && (buf[3] & 0xFF) == 0xE0)
Log.e(TAG, "is JPG");
else
Log.e(TAG, "not a valid JPG");
La seule chose que je suis se douter à ce moment est que Android 5.0 émulateur je suis en train de tester contre ne peut pas hanlde les appels d'API.
Des idées?
OriginalL'auteur mtsahakis | 2014-10-31
Vous devez vous connecter pour publier un commentaire.
J'ai testé le code de la première réponse, mais malheureusement, il ne fonctionne pas sur un périphérique réel. Je fais quelques recherches, et le code suivant résolu mon problème:
String name = "/myscreen" + count + ".png";
? Merci beaucoup d'avance!Mon appareil est nexus5, le framerate n'est pas bon, même-je supprimer ces CPU calcul. Je ne sais pas pourquoi.
Cela m'a été signalé par d'autres utilisateurs d'essayer mon code sur un projet de test que j'ai posté sur github github.com/mtsahakis/MediaProjectionDemo. J'ai changé le code de
ImageReader.newInstance(width, height, ImageFormat.JPEG, 5);
àImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 5);
comme je le crois, résout le problème sur certains appareils. Aussi sur mon appareil de test (Nexus 7 avec Android 5.0.2) le taux de capture s'améliore un peu.J'ai été confronté à des problèmes similaires. Changement de format de l'image à PixelFormat.RGBA_8888 Grâce.
Qu'est-ce que les métriques censé être?
OriginalL'auteur Charlesjean
Le code de réponse par @charlesjean fonctionne, mais je préfère ne pas générer de chaque pixel par moi-même. Une meilleure façon d'obtenir l'Image de ImageReader est tout simplement de créer de la bonne taille bitmap et d'utiliser la méthode copyPixelsFromBuffer(). Créer ImageReader comme suit:
Ensuite, vous pouvez obtenir l'image de mImageReader à l'aide du code ci-dessous.
J'ai décrit le processus de capture d'écran à l'aide de MediaProjection API avec les erreurs que la plupart des gens fait lors de l'obtention d'une image à partir de ImageReader dans un post de blog que vous pouvez lire si vous êtes intéressé.
ARGB_8888 résultats dans les 4 octets par pixels sens plus bitmaps par rapport à RGB_565 qui prend 2 octets par pixel. J'avais besoin de plus petits bitmaps mais sinon, il est parfaitement acceptable d'utiliser ARGB_8888 si vous n'êtes pas inquiet au sujet de la mémoire. Ils accident doit être pour quelque autre raison que ce code est copié exactement à partir d'une application que j'ai développé et fonctionne très bien, aucune panne.
J'ai testé le code et j'ai eu
03-11 22:12:27.653 7990-8008/com.mtsahakis.mediaprojectiondemo E/ImageReader_JNI﹕ Producer output buffer format: 0x1, ImageReader configured format: 0x4 03-11 22:12:27.653 7990-8008/com.mtsahakis.mediaprojectiondemo W/System.err﹕ java.lang.UnsupportedOperationException: The producer output buffer format 0x1 doesn't match the ImageReader's configured buffer format 0x4. 03-11 22:12:27.653 7990-8008/com.mtsahakis.mediaprojectiondemo W/System.err﹕ at android.media.ImageReader.nativeImageSetup(Native Method)
quandacquireLatestImage()
est appelé. Des idées?J'ai également eu à changer de "ImageFormat.RGB_565" à "PixelFormat.RGBA_8888" et "Bitmap.Config.RGB_565" à "Bitmap.Config.ARGB_8888" pour le faire fonctionner.
Cela semble être très dépendante du périphérique. Le ImageReader formats dont je dispose ne sont que ceux énumérés dans le developer.android.com/reference/android/media/Image.html, et je ne peux l'utiliser ImageFormat.JPEG, ce qui provoque l'avion pour avoir un pixelStride de 0, donc, je suis une division par zéro exception.
OriginalL'auteur binW
J'ai rencontré exactement votre problème. Mon ImageReader créé de la manière suivante:
La ImageReader ci-dessus ne doit retourner des images compressées, et elles doivent être décompressés. Je acquireLatestImage(), puis le passer à travers les éléments suivants:
Pour moi, l'essentiel était de retour le ByteBuffer. Votre code doit fonctionner de la manière suivante:
Je n'aime pas avoir à copier les ByteBuffer par le biais d'un intermédiaire, byte[], mais le tableau interne est protégé.
Testé à travailler sur 5.0.1 sur un HTC
De mes tests, cela ne fonctionne pas vraiment ... Le tampon d'octets à partir de la
ImageReader
n'est pas au format JPEG, il est dans un format brut quiBitmapFactory.decodeByteArray
est assez intelligent pour détecter et à comprendre, c'est pourquoi l'image n'apparaît.OriginalL'auteur Nicolas
Dans le cas où quelqu'un tombe sur ce, le code de travail est comme suit:
Comme vous le voyez je suis enregistrer l'image capturée à partir de ImageReader à un fileoutput flux et ce produit valide d'un fichier jpeg.
Les messages que je recevais de retour de android_media_ImageReader.cpp n'ont pas été en indiquant toute sorte de mauvais comportement.
Espère que cela aide quelqu'un dans le futur!
Salut Alessandro. Ainsi, les drapeaux que je suis en train sont
final int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
. L'émulateur que j'utilise est assez standard, avec armeabi-v7a CPU, 1024MB de RAM, 32 mo de VM et de tas 1024MB de stockage interne. Je suis en attente de le tester sur un périphérique réel lorsque je obtenir mes mains sur une Sucette 🙂Alors je ne sais vraiment pas ce que je fais mal parce que ce sont les mêmes drapeaux que j'ai défini. La largeur et la hauteur que vous utilisez sont de la taille de l'écran? Demain, je vais le tester sur une Sucette appareil et je vais vous laisser savoir.
Hey Alessandro, vraiment désolé de voir que votre code ne fonctionne pas. Mon code sur la largeur et la hauteur est vraiment simple:
final Display display = getWindowManager().getDefaultDisplay(); final Point size = new Point(); display.getSize(size); final int width = size.x; final int height = size.y;
. Peut-être plus tard aujourd'hui, je vais la mettre sur github pour vous d'avoir un coup d'oeil. Bonne chance!Merci man, vraiment apprécié.
OriginalL'auteur mtsahakis
J'ai essayé d'utiliser de nombreux exemples de code. Mais aucun de ces codes. J'ai mélangé ces codes de moi-même. Et j'ai créé de travail exemple de code.
OriginalL'auteur hurelhuyag