截取Android OpenGL的截图

时间:2010-07-22 16:18:50

标签: android opengl-es

我正试图拍摄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方法存在一些问题,但我不知道如何绕过它。

3 个答案:

答案 0 :(得分: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;
            }

只要用户按下按钮创建屏幕截图,“screenshot”类字段就会设置为true 或者在任何其他情况下你想要的。在“if”主体内你可以放置任何截图创建代码样本你在互联网上找到 - 最重要的是拥有GL10的当前实例。例如,当您只是将GL10实例保存到类变量然后在事件外使用它来创建屏幕截图您将最终得到完全空白的图像。这就是为什么你必须在OnDrawFrame事件处理程序中截取GL10实例是当前实例的截图。 希望它有所帮助。

最好的问候,戈登。

答案 1 :(得分: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;
}

答案 2 :(得分:2)

知道了!

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

祝你好运, 戈登