System error capturing the output of a MediaProjection virtual display to an ImageReader

前端 未结 2 1643
暗喜
暗喜 2021-01-05 08:48

I am working on an application that needs to capture the screen to a bitmap to transmit. I am attempting to use the new Android 5.0 android.media.projection APIs to do the s

相关标签:
2条回答
  • 2021-01-05 09:16

    A better way to get the Image from ImageReader is just to create right sized bitmap and use the method copyPixelsFromBuffer(). Create ImageReader as follows:

    mImageReader = ImageReader.newInstance(mWidth, mHeight, ImageFormat.RGB_565, 2);
    

    Then you can get the image from mImageReader using the code below.

    final Image.Plane[] planes = image.getPlanes();
    final ByteBuffer buffer = planes[0].getBuffer();
    int offset = 0;
    int pixelStride = planes[0].getPixelStride();
    int rowStride = planes[0].getRowStride();
    int rowPadding = rowStride - pixelStride * mWidth;
    // create bitmap
    bitmap = Bitmap.createBitmap(mWidth+rowPadding/pixelStride, mHeight, Bitmap.Config.RGB_565);
    bitmap.copyPixelsFromBuffer(buffer);
    image.close();
    

    I have described the process of capturing screen using MediaProjection API along with the mistakes most people made when getting image from ImageReader in a blog post which you can read if interested.

    0 讨论(0)
  • 2021-01-05 09:22

    I think I can answer this question now, I met the same problem and after I change ImageFormat.JPEG to PixelFormat.RGBA_8888 everything goes well. It seems ImageFormat.JPEG is not supported.

    You need to use the following code to get the correct bitmap:

                        int width = img.getWidth();
                        int height = img.getHeight();
                        int pixelStride = planes[0].getPixelStride();
                        int rowStride = planes[0].getRowStride();
                        int rowPadding = rowStride - pixelStride * width;
                        byte[] newData = new byte[width * height * 4];
    
                        int offset = 0;
                        bitmap = Bitmap.createBitmap(metrics,width, height, Bitmap.Config.ARGB_8888);
                        ByteBuffer buffer = planes[0].getBuffer();
                        for (int i = 0; i < height; ++i) {
                            for (int j = 0; j < width; ++j) {
                                int pixel = 0;
                                pixel |= (buffer.get(offset) & 0xff) << 16;     // R
                                pixel |= (buffer.get(offset + 1) & 0xff) << 8;  // G
                                pixel |= (buffer.get(offset + 2) & 0xff);       // B
                                pixel |= (buffer.get(offset + 3) & 0xff) << 24; // A
                                bitmap.setPixel(j, i, pixel);
                                offset += pixelStride;
                            }
                            offset += rowPadding;
                        }
    

    From this way, the content of bitmap is what you want.

    PS: I really want to say, the doc of android is pretty bad. we need to investigate too much detail to use sdk api correctly.

    0 讨论(0)
提交回复
热议问题