2010-07-26 4 views
18

Używam previewCallback z kamery, aby spróbować przechwycić obrazy. Oto kod używamBitmapFactory.decodeByteArray() zwraca NULL

private Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback() 
{ 
     public void onPreviewFrame(byte[] data, Camera Cam) { 
       Log.d("CombineTestActivity", "Preview started"); 
       Log.d("CombineTestActivity", "Data length = " 
         + data.length); 
       currentprev = BitmapFactory.decodeByteArray(data, 0, 
         data.length); 

       if(currentprev == null) 
        Log.d("CombineTestActivity", "currentprev is null"); 

       Log.d("CombineTestActivity", "Preview Finished"); 

     } 
}; 

długości danych zawsze przychodzi otu taka sama jak 576000.

Również próbowałem zmianę parametrów kamery więc obraz wraca jak różne formaty. Oto, jak to wygląda, kiedy to robię.

mCamera = Camera.open(); 
camParam = mCamera.getParameters(); 
camParam.setPreviewFormat(ImageFormat.RGB_565); 
mCamera.setParameters(camParam); 
    mCamera.setPreviewCallback(mPrevCallback); 

Jednakże zarówno przy zmianie formatu podglądu a kiedy pozostawić jako jego niewypłacalności NV21, BitmapFactory.decodeByteArray wraca jako null. Próbowałem również zmienić format podglądu na typ JPEG. I nawet dostać oświadczenia debugowania w DDMS, to co mam

"D/skia (14391) --- SkImageDecoder :: Fabryka zwrócone null"

+0

Wróciłem i kliknąłem checkmarks nex t do niektórych odpowiedzi, które tu uzyskałem. Dzięki za informacje – RyoxSinfar

+0

Możliwy duplikat [Pobieranie klatek z obrazu wideo w systemie Android] (http://stackoverflow.com/questions/1893072/getting-frames-from-video-image-in-android) – Tim

Odpowiedz

3

staram się robić to samo . Opierając się na dyskusjach here i here, brzmi to tak, jakby ludzie nie mieli szczęścia otrzymując decodeByteArray() do obsługi formatu NV21 od wersji Androida 2.1/2.2. Z pewnością nie działa w moim emulatorze lub w moim Droid Incredible, chociaż myślę, że to wywołuje natywny kod, więc może działać na niektórych telefonach w zależności od sterowników?

Jako alternatywa, możesz spróbować samemu dekodować NV21 w Javie (patrz przykład powyżej), chociaż jest to najwyraźniej zbyt wolne, aby mogło być użyteczne w większości przypadków. Nie miałem dużo szczęścia, próbując uzyskać CameraPreview wysłać inny format, i spodziewam się, że będzie to problematyczne przy próbie napisania kodu, który jest przenośny na różnych urządzeniach. Jeśli napisałeś metody dekodowania NV21 w NDK, możesz nieco zwiększyć liczbę klatek na sekundę.

Najwyraźniej występują problemy ze stabilnością ze względu na warunki wyścigu, próbując przetworzyć także CameraPreview, chociaż sam nie potwierdziłem tego problemu. Myślę, że możesz tego uniknąć, a także trochę zwiększyć ilość klatek na sekundę za pomocą buforowanej metody wywołania zwrotnego w trybie podglądu setPreviewCallbackWithBuffer(), która została dodana w systemie Android 2.1/2.2. Zostało to dodane w wersji 2.1, ale zostało ukryte do wersji 2.2. To use it in 2.1 you need to hack around the hiding.

Niektórzy sugerują używanie MediaRecorder zamiast CameraPreview. Niestety, wydaje się, że MediaRecorder ma jeszcze mniej możliwości uzyskania ramek podglądu niż CameraPreview, więc nie mogę polecić tej trasy.

+0

Korzystanie z dekodowania NV21 w powyższy link, udało mi się uzyskać pikseli, ale z szybkością ramki około 1 klatki/10 sekund na HTC Droid Incredible. Sądzę jednak, że zmniejszenie próbkowania pikseli może sprawić, że ta liczba klatek na sekundę zwiększy się do prędkości, która może być użyteczna dla niektórych aplikacji. – Chinasaur

37

Dobra, mam nadzieję, że to pomoże.

Przeczesał internet, szukając szybkiego rozwiązania i znalazł idealne rozwiązanie.

To działa jak Android 2.1

Dzięki off3nsiv3 od this page.

// Convert to JPG 
Size previewSize = camera.getParameters().getPreviewSize(); 
YuvImage yuvimage=new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 80, baos); 
byte[] jdata = baos.toByteArray(); 

// Convert to Bitmap 
Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length); 

Po prostu drobna modyfikacja kodu off3nsiv3 i gotowe. FPS jest wciąż niesamowicie wysoki w porównaniu do ręcznego dekodowania.

Dla powyższego kodu, 80 to jakość jpeg (0 od 100, 100 jest najlepsza).

+0

Interesujące; czy mógłbyś zamieścić porównanie framerates? – Chinasaur

+0

Mogłem, ale na LG Optimus C FPS był prawie taki sam. Na HTC FPS był taki sam. Nie ma zauważalnego opóźnienia. – Qix

+1

Dobrze wiedzieć; dzięki. Dam temu szansę. – Chinasaur

1

Aktualizacja z moich wcześniejszych odpowiedzi, ale należy pamiętać, odpowiedź QiX, która wygląda prościej

ja rzeczywiście miał przyzwoite wyniki z dekodowaniem w czystej Javie. Framerates około 10-15 fps, o ile rozmiar podglądu nie jest zbyt duży. Niestety aktualizacja systemu Android 2.3 do mojego Droida Inc zdołała zabrać nieco mniejszych rozmiarów opcji podglądu :(Próbowałem też zrobić to w natywnym kodzie, który wyciągnąłem z innego projektu, ale było to błędne i nie wydawało się szybsze dla stosunkowo prostej obróbki robiłem, więc nie prowadzić go dalej Zobacz my Github dla źródła (zarówno Java i native)

-1

spróbuj jak następuje:..

public Bitmap stringtoBitmap(String string) { 
    Bitmap bitmap = null; 
    try { 
     YuvImage yuvimage = new YuvImage(base64.getBytes(),ImageFormat.YUY2, 120, 30, null); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     yuvimage.compressToJpeg(new Rect(0, 0, 20, 20), 100, baos); 
     byte[] jdata = baos.toByteArray(); 
     bitmap = BitmapFactory.decodeByteArray(jdata, 0, jdata.length); 
    } catch (Exception e) { 

    } 
    return bitmap; 
} 
+1

Czy mógłbyś wyjaśnić swoje podejście bardziej szczegółowo? –

+0

Dlaczego połykasz wyjątki? Nie rób tego. – Qix

9

można spróbować tego i to działa ...

mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() { 
       @Override 
       public void onPreviewFrame(byte[] data, Camera camera) { 
        Camera.Parameters parameters = camera.getParameters(); 
        int format = parameters.getPreviewFormat(); 
        //YUV formats require more conversion 
        if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) { 
         int w = parameters.getPreviewSize().width; 
         int h = parameters.getPreviewSize().height; 
         // Get the YuV image 
         YuvImage yuv_image = new YuvImage(data, format, w, h, null); 
         // Convert YuV to Jpeg 
         Rect rect = new Rect(0, 0, w, h); 
         ByteArrayOutputStream output_stream = new ByteArrayOutputStream(); 
         yuv_image.compressToJpeg(rect, 100, output_stream); 
         byte[] byt = output_stream.toByteArray(); 
         FileOutputStream outStream = null; 
         try { 
          // Write to SD Card 
          File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg"); 
          //Uri uriSavedImage = Uri.fromFile(file); 
          outStream = new FileOutputStream(file); 
          outStream.write(byt); 
          outStream.close(); 
         } catch (FileNotFoundException e) { 
          e.printStackTrace(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } finally { 
         } 
        } 
       }