2010-07-22 43 views
19

Tôi đang cố chụp ảnh màn hình Android OpenGL.Chụp ảnh màn hình của Android OpenGL

Mã tôi thấy như sau:

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 
    } 

Tôi cũng đã cố gắng một mã từ trang web đó link text

Trong mỗi trường hợp kết quả là một tập tin png đó là hoàn toàn đen. Tôi thấy có một số vấn đề với phương pháp glReadPixels nhưng tôi không biết cách bỏ qua nó.

Trả lời

2

OK!

Sai lầm của tôi là tôi đã nhớ ngữ cảnh GL trong biến lớp. Để chụp ảnh màn hình, tôi phải sử dụng bối cảnh gl được truyền cho OnDraw trong lớp thực hiện giao diện GLSurfaceView.Renderer. Tôi chỉ cần sử dụng mã của tôi trong mệnh đề "if" và mọi thứ hoạt động như mong đợi. Hy vọng rằng nhận xét sẽ giúp bất cứ ai.

Trân trọng, Gordon

22

Xin lỗi vì sự chậm phản ứng ...

Để thực hiện một ảnh chụp màn hình đúng Bạn cần phải đưa vào onDrawFrame của bạn (GL10 gl) xử lý các đoạn mã sau:

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; 
      } 

Trường lớp "ảnh chụp màn hình" được đặt thành true bất cứ khi nào người dùng nhấn nút để tạo ảnh chụp màn hình hoặc tại bất kỳ trường hợp nào khác mà bạn muốn. Bên trong cơ thể "nếu" Bạn có thể đặt bất kỳ ảnh chụp màn hình tạo mẫu mã Bạn tìm thấy trong internet thứ - điều quan trọng nhất là có trường hợp hiện tại của GL10. Ví dụ khi bạn chỉ cần lưu cá thể GL10 vào biến lớp và sau đó sử dụng nó bên ngoài sự kiện để tạo ảnh chụp màn hình Bạn sẽ kết thúc với hình ảnh hoàn toàn trống. Đó là lý do tại sao Bạn phải chụp ảnh màn hình bên trong trình xử lý sự kiện OnDrawFrame, trong đó cá thể GL10 là phiên bản hiện tại. Hy vọng rằng điều đó sẽ hữu ích.

Trân trọng, Gordon.

+0

tôi nhận được màu sắc erroneal với điều này giải pháp, ví dụ, màu vàng được sơn màu xanh ... ¿? làm thế nào để giải quyết nó xin vui lòng? – NullPointerException

+0

@ Gordon Làm thế nào để bạn khởi tạo gl? – XXX

10

Dưới đây là cách để làm điều đó nếu bạn muốn giữ chất lượng (8 bit cho mỗi kênh màu: đỏ, xanh lá cây, xanh dương và alpha quá):

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

Cảm ơn rất nhiều, nó đã tiết kiệm thời gian dài của tôi ....: P @Spartarel –

+0

Tôi đã sử dụng phương pháp của bạn và nó hoạt động tốt nếu tôi lưu bitmap afte 1 giây làm giá trị ảnh chụp màn hình đúng. nếu tôi thậm chí chờ 500 milisec nó tiết kiệm một hình ảnh màu xấu ... là hoạt động đó mất nhiều thời gian hơn? @Spatarel –

+0

@Hissain bạn đã bao giờ tìm ra giải pháp cho vấn đề đó chưa? – anakin78z

Các vấn đề liên quan