2010-07-22 73 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