2010-07-22 76 views
19

我正在尝试截取Android OpenGL截图。截取Android OpenGL

我发现的代码如下:

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 
    } 

我还试图从该网站 link text

在每种情况下,结果是PNG文件,其是全黑的码。 我发现glReadPixels方法存在一些问题,但我不知道如何绕过它。

回答

2

Got it!

我的错误是,我记得在类变量GL上下文。为了获得屏幕截图,我必须在实现GLSurfaceView.Renderer接口的类中使用传递给OnDraw的gl上下文。我只是在“if”子句中使用我的代码,一切都按预期工作。希望这句话能帮助任何人。

最好的问候, 戈登

22

对不起,我迟到响应...

为了执行一个正确的截图中,你必须把你的onDrawFrame(GL10 GL)代码如下:

每当用户按下按钮,创建一个屏幕截图 或在任何其他情况下,你想
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; 
      } 

的“截图”类字段设置为true。在“if”体内部你可以放置任何截图创建代码示例你可以在互联网中找到 - 最重要的是拥有当前的GL10实例。例如,当您将GL10实例保存到类变量,然后在事件之外使用它来创建屏幕截图时,您将最终得到完全空白的图像。这就是为什么你必须在当前GL10实例的OnDrawFrame事件处理程序中进行截图。 希望它有帮助。

最好的问候,戈登。

+0

我越来越erroneal颜色与此解决方案,例如,黄色被涂成蓝色......¿?请问如何解决? – NullPointerException 2011-11-16 09:21:42

+0

@ Gordon你如何初始化gl? – XXX 2013-03-09 21:45:00

10

这里是这样做,如果你想保持质量的方式(8位每个颜色通道:红色,绿色,蓝色和Alpha太):

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

非常感谢,它节省了我很长时间珍惜....:P @Spartarel – 2013-11-12 19:32:28

+0

我用你的方法,它工作正常,如果我保存位图后1秒的截图值真实。如果我甚至等待500毫秒,它可以保存一个不好的彩色图像...是否需要更多时间? @Spatarel – 2013-11-14 18:12:34

+0

@Hissain你曾经找到过解决这个问题的办法吗? – anakin78z 2014-01-31 18:26:59