2010-07-22 13 views
19

Estoy tratando de tomar una captura de pantalla de Android OpenGL.Toma de captura de pantalla de Android OpenGL

El código que he encontrado es la siguiente:

nt size = width * height; 
    ByteBuffer buf = ByteBuffer.allocateDirect(size * 4); 
    buf.order(ByteOrder.nativeOrder()); 
    glContext.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buf); 
    int data[] = new int[size]; 
    buf.asIntBuffer().get(data); 
    buf = null; 
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 
    bitmap.setPixels(data, size-width, -width, 0, 0, width, height); 
    data = null; 

    short sdata[] = new short[size]; 
    ShortBuffer sbuf = ShortBuffer.wrap(sdata); 
    bitmap.copyPixelsToBuffer(sbuf); 
    for (int i = 0; i < size; ++i) { 
     //BGR-565 to RGB-565 
     short v = sdata[i]; 
     sdata[i] = (short) (((v&0x1f) << 11) | (v&0x7e0) | ((v&0xf800) >> 11)); 
    } 
    sbuf.rewind(); 
    bitmap.copyPixelsFromBuffer(sbuf); 

    try { 
     FileOutputStream fos = new FileOutputStream("/sdcard/screeshot.png"); 
     bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); 
     fos.flush(); 
     fos.close(); 
    } catch (Exception e) { 
     // handle 
    } 

me trataron también un código de ese sitio link text

En cada caso, el resultado es un archivo PNG que es completamente negro. Encontré que hay algún problema con el método glReadPixels pero no sé cómo eludirlo.

Respuesta

2

¡Lo tengo!

Mi error fue que estaba recordando el contexto GL en la variable de clase. Para tomar una captura de pantalla, tengo que usar el contexto gl pasado al OnDraw en la clase que implementa la interfaz GLSurfaceView.Renderer. Simplemente uso mi código en la cláusula "si" y todo funciona como se esperaba. Espero que ese comentario ayude a cualquiera.

Saludos, Gordon

22

Lo siento por la respuesta tardía ...

el fin de realizar una captura de pantalla correcto Usted tiene que poner en su onDrawFrame (GL10 gl) manejador el siguiente código:

if(screenshot){      
       int screenshotSize = width * height; 
       ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4); 
       bb.order(ByteOrder.nativeOrder()); 
       gl.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb); 
       int pixelsBuffer[] = new int[screenshotSize]; 
       bb.asIntBuffer().get(pixelsBuffer); 
       bb = null; 
       Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 
       bitmap.setPixels(pixelsBuffer, screenshotSize-width, -width, 0, 0, width, height); 
       pixelsBuffer = null; 

       short sBuffer[] = new short[screenshotSize]; 
       ShortBuffer sb = ShortBuffer.wrap(sBuffer); 
       bitmap.copyPixelsToBuffer(sb); 

       //Making created bitmap (from OpenGL points) compatible with Android bitmap 
       for (int i = 0; i < screenshotSize; ++i) {     
        short v = sBuffer[i]; 
        sBuffer[i] = (short) (((v&0x1f) << 11) | (v&0x7e0) | ((v&0xf800) >> 11)); 
       } 
       sb.rewind(); 
       bitmap.copyPixelsFromBuffer(sb); 
       lastScreenshot = bitmap; 

       screenshot = false; 
      } 

El campo de clase "captura de pantalla" se establece en verdadero cuando el usuario presiona el botón para crear una captura de pantalla o en cualquier otra circunstancia que desee. Dentro del cuerpo "si" Puede colocar cualquier captura de pantalla creando una muestra de código. En Internet, lo más importante es tener la instancia actual de GL10. Por ejemplo, cuando solo guarda la instancia de GL10 en la variable de clase y luego la usa fuera del evento para crear la captura de pantalla, terminará con la imagen completamente en blanco. Es por eso que debe tomar una captura de pantalla dentro del controlador de eventos OnDrawFrame donde la instancia GL10 es la actual. Espero que ayude.

Saludos cordiales, Gordon.

+0

estoy consiguiendo colores erroneal con este solución, por ejemplo, los colores amarillos están pintados de azul ... ¿? cómo resolverlo por favor? – NullPointerException

+0

@ Gordon ¿Cómo inicializas gl? – XXX

10

Aquí es la manera de hacerlo si desea conservar la calidad (8 bits para cada canal de color: rojo, verde, azul y alfa también):

if (this.screenshot) { 
    int screenshotSize = this.width * this.height; 
    ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4); 
    bb.order(ByteOrder.nativeOrder()); 
    gl.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb); 
    int pixelsBuffer[] = new int[screenshotSize]; 
    bb.asIntBuffer().get(pixelsBuffer); 
    bb = null; 

    for (int i = 0; i < screenshotSize; ++i) { 
     // The alpha and green channels' positions are preserved while the red and blue are swapped 
     pixelsBuffer[i] = ((pixelsBuffer[i] & 0xff00ff00)) | ((pixelsBuffer[i] & 0x000000ff) << 16) | ((pixelsBuffer[i] & 0x00ff0000) >> 16); 
    } 

    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
    bitmap.setPixels(pixelsBuffer, screenshotSize-width, -width, 0, 0, width, height); 
    this.screenshot = false; 
} 
+0

Muchas gracias, salvó mi gran aprecio ...: P @Spartarel –

+0

Utilicé su método y funciona bien si guardo el mapa de bits después de 1 seg de hacer verdadero el valor de captura de pantalla. si incluso espero 500 milisegundos, se ahorra una mala imagen de color ... ¿esa operación lleva más tiempo? @Spatarel –

+0

@Hissain ¿alguna vez encontró una solución a ese problema? – anakin78z

Cuestiones relacionadas