2011-04-01 13 views
29

tengo que ser capaz de capturar una imagen de un GLSurfaceView en determinado momento en el tiempo. Tengo el siguiente código:captura de pantalla de mapa de bits a GLSurfaceView

relative.setDrawingCacheEnabled(true); 
screenshot = Bitmap.createBitmap(relative.getDrawingCache()); 
relative.setDrawingCacheEnabled(false); 
Log.v(TAG, "Screenshot height: " + screenshot.getHeight()); 
image.setImageBitmap(screenshot); 

El GLSurfaceView está contenido dentro de un RelativeLayout, pero también tienen que trata directamente con el GLSurfaceView para tratar de capturar la imagen. Con esto, creo que la pantalla captura una imagen transparente, es decir, nada allí. Cualquier ayuda será apreciada.

+1

Hola, estoy teniendo el mismo problema encontraste alguna solución, si es así, por favor comparte, gracias. – DroidBot

+0

No he encontrado una respuesta a esta pregunta, lo siento. – SamRowley

+0

¿Está representando continuamente? – srinivasan

Respuesta

42

SurfaceView y GLSurfaceView agujeros en sus ventanas para permitir que se muestren sus superficies. En otras palabras, tienen áreas transparentes.

lo que no puede capturar una imagen llamando GLSurfaceView.getDrawingCache().

Si desea obtener una imagen de GLSurfaceView, debe invocar gl.glReadPixels() en GLSurfaceView.onDrawFrame().

Revisé el método createBitmapFromGLSurface y lo llamé al onDrawFrame().

(El código original podría ser de código skuld 's.)

private Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl) 
     throws OutOfMemoryError { 
    int bitmapBuffer[] = new int[w * h]; 
    int bitmapSource[] = new int[w * h]; 
    IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer); 
    intBuffer.position(0); 

    try { 
     gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer); 
     int offset1, offset2; 
     for (int i = 0; i < h; i++) { 
      offset1 = i * w; 
      offset2 = (h - i - 1) * w; 
      for (int j = 0; j < w; j++) { 
       int texturePixel = bitmapBuffer[offset1 + j]; 
       int blue = (texturePixel >> 16) & 0xff; 
       int red = (texturePixel << 16) & 0x00ff0000; 
       int pixel = (texturePixel & 0xff00ff00) | red | blue; 
       bitmapSource[offset2 + j] = pixel; 
      } 
     } 
    } catch (GLException e) { 
     return null; 
    } 

    return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888); 
} 
+0

Hola Dalinaum, el método anterior, u puede decirme , donde ponemos este método ... – harikrishnan

+1

Puedes poner 'createBitmapFromGLSurface' en la subclase de GLSurfaceView. Llamarlo en 'onDraw()' es importante. – Dalinaum

+1

Pero en onDraw no tienes una instancia de gl. ¿Cómo puedes recuperarlo? – Nativ

2

Nota: En este código, al hacer clic en el botón, se toma la pantalla como imagen y la guarda en la ubicación sdcard . Solía ​​condición booleana y un estado de if en onDraw método, debido a que la clase de procesador puede llamar al método onDraw en cualquier momento y de cualquier manera, y sin la if Este código puede ahorrar una gran cantidad de imágenes en la tarjeta de memoria.

clase MainActivity: Clase

protected boolean printOptionEnable = false; 

saveImageButton.setOnClickListener(new OnClickListener() { 

    @Override 
    public void onClick(View v) { 
     Log.v("hari", "pan button clicked"); 
     isSaveClick = true; 
     myRenderer.printOptionEnable = isSaveClick; 
    } 
}); 

MyRenderer:

int width_surface , height_surface ; 

@Override 
public void onSurfaceChanged(GL10 gl, int width, int height) { 
    Log.i("JO", "onSurfaceChanged"); 
    // Adjust the viewport based on geometry changes, 
    // such as screen rotation 
    GLES20.glViewport(0, 0, width, height); 

    float ratio = (float) width/height; 

    width_surface = width ; 
    height_surface = height ; 
} 

@Override 
public void onDrawFrame(GL10 gl) { 
    try { 
     if (printOptionEnable) { 
      printOptionEnable = false ; 
      Log.i("hari", "printOptionEnable if condition:" + printOptionEnable); 
      int w = width_surface ; 
      int h = height_surface ; 

      Log.i("hari", "w:"+w+"-----h:"+h); 

      int b[]=new int[(int) (w*h)]; 
      int bt[]=new int[(int) (w*h)]; 
      IntBuffer buffer=IntBuffer.wrap(b); 
      buffer.position(0); 
      GLES20.glReadPixels(0, 0, w, h,GLES20.GL_RGBA,GLES20.GL_UNSIGNED_BYTE, buffer); 
      for(int i=0; i<h; i++) 
      { 
       //remember, that OpenGL bitmap is incompatible with Android bitmap 
       //and so, some correction need.   
       for(int j=0; j<w; j++) 
       { 
        int pix=b[i*w+j]; 
        int pb=(pix>>16)&0xff; 
        int pr=(pix<<16)&0x00ff0000; 
        int pix1=(pix&0xff00ff00) | pr | pb; 
        bt[(h-i-1)*w+j]=pix1; 
       } 
      }   
      Bitmap inBitmap = null ; 
      if (inBitmap == null || !inBitmap.isMutable() 
       || inBitmap.getWidth() != w || inBitmap.getHeight() != h) { 
       inBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
      } 
      //Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
      inBitmap.copyPixelsFromBuffer(buffer); 
      //return inBitmap ; 
      // return Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888); 
      inBitmap = Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888); 

      ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
      inBitmap.compress(CompressFormat.JPEG, 90, bos); 
      byte[] bitmapdata = bos.toByteArray(); 
      ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata); 

      final Calendar c=Calendar.getInstance(); 
      long mytimestamp=c.getTimeInMillis(); 
      String timeStamp=String.valueOf(mytimestamp); 
      String myfile="hari"+timeStamp+".jpeg"; 

      dir_image = new File(Environment.getExternalStorageDirectory()+File.separator+ 
      "printerscreenshots"+File.separator+"image"); 
      dir_image.mkdirs(); 

      try { 
       File tmpFile = new File(dir_image,myfile); 
       FileOutputStream fos = new FileOutputStream(tmpFile); 

       byte[] buf = new byte[1024]; 
       int len; 
       while ((len = fis.read(buf)) > 0) { 
       fos.write(buf, 0, len); 
      } 
      fis.close(); 
      fos.close(); 
      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      Log.v("hari", "screenshots:"+dir_image.toString()); 
     } 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 
11

Aquí es una solución completa si está utilizando una biblioteca de terceros que 'pasa en' sólo un GLSurfaceView definido en su diseño . No tendrá un control sobre onDrawFrame() del renderizador, esto puede ser un problema ...

Para hacer esto, necesita ponerlo en cola para que GLSurfaceView lo maneje.

private GLSurfaceView glSurfaceView; // findById() in onCreate 
private Bitmap snapshotBitmap; 

private interface BitmapReadyCallbacks { 
    void onBitmapReady(Bitmap bitmap); 
} 

/* Usage code 
    captureBitmap(new BitmapReadyCallbacks() { 

     @Override 
     public void onBitmapReady(Bitmap bitmap) { 
      someImageView.setImageBitmap(bitmap); 
     } 
    }); 
*/ 

// supporting methods 
private void captureBitmap(final BitmapReadyCallbacks bitmapReadyCallbacks) { 
    glSurfaceView.queueEvent(new Runnable() { 
     @Override 
     public void run() { 
      EGL10 egl = (EGL10) EGLContext.getEGL(); 
      GL10 gl = (GL10)egl.eglGetCurrentContext().getGL(); 
      snapshotBitmap = createBitmapFromGLSurface(0, 0, glSurfaceView.getWidth(), glSurfaceView.getHeight(), gl); 

      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        bitmapReadyCallbacks.onBitmapReady(snapshotBitmap); 
       } 
      }); 

     } 
    }); 

} 

// from other answer in this question 
private Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl) { 

    int bitmapBuffer[] = new int[w * h]; 
    int bitmapSource[] = new int[w * h]; 
    IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer); 
    intBuffer.position(0); 

    try { 
     gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer); 
     int offset1, offset2; 
     for (int i = 0; i < h; i++) { 
      offset1 = i * w; 
      offset2 = (h - i - 1) * w; 
      for (int j = 0; j < w; j++) { 
       int texturePixel = bitmapBuffer[offset1 + j]; 
       int blue = (texturePixel >> 16) & 0xff; 
       int red = (texturePixel << 16) & 0x00ff0000; 
       int pixel = (texturePixel & 0xff00ff00) | red | blue; 
       bitmapSource[offset2 + j] = pixel; 
      } 
     } 
    } catch (GLException e) { 
     Log.e(TAG, "createBitmapFromGLSurface: " + e.getMessage(), e); 
     return null; 
    } 

    return Bitmap.createBitmap(bitmapSource, w, h, Config.ARGB_8888); 
} 
Cuestiones relacionadas