4

I managed to get screenshots but the result is like this:

Screenshot produced

Original:

Original

This is my code which i took from a few sources:

final ImageReader ir = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);
  VirtualDisplay vd= mediaProjection.createVirtualDisplay("screen", width, height, dpi, 
  DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC, ir.getSurface(), null, null);

final String path=getActivity().getFilesDir().getAbsolutePath()+"/myscreen.jpg";
  ir.setOnImageAvailableListener(new OnImageAvailableListener() {

          //  @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = null;
                FileOutputStream fos = null;
                Bitmap bitmap = null;

                try {
                    image = ir.acquireLatestImage();
                    fos = new FileOutputStream( path);
                    final Image.Plane[] planes = image.getPlanes();
                    final Buffer buffer = planes[0].getBuffer().rewind();
                    bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                    bitmap.copyPixelsFromBuffer(buffer);
                    bitmap.compress(CompressFormat.JPEG, 85, fos);
                    image.close();

                } catch (Exception e) {
                    e.printStackTrace();
             ........
             ........
hoshiKuzu
  • 866
  • 1
  • 12
  • 30
  • 2
    Off the cuff, your `width` calculation may be off, as it does not seem to take pixel stride and row stride into account. See [this chunk of code](https://github.com/commonsguy/cw-omnibus/blob/master/MediaProjection/andprojector/app/src/main/java/com/commonsware/andprojector/ImageTransmogrifier.java#L58-L81) for how I do it. – CommonsWare Jan 29 '16 at 19:10
  • Why `width>>1`? btw, putting `bitmapWidth=width + rowPadding / pixelStride` worked, but now I have a 300px wide black bar at the right, – hoshiKuzu Jan 29 '16 at 20:20
  • "Why width>>1?" -- I don't see that, sorry. "now I have a 300px wide black bar at the right" -- that is because of a discrepancy between what size you asked for and the size of the actual images. If you continue down my code listing past the highlighted portion, you will see where I crop the original bitmap to the desired size, and then use the cropped portion. – CommonsWare Jan 29 '16 at 20:22

2 Answers2

5

It's the width and height of your bitmap that's off--atleast your distorted image looks just like what I was seeing. Here's how I got it working.

int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * imageReader.getWidth();
bitmap = Bitmap.createBitmap(imageReader.getWidth() + rowPadding / pixelStride,
                        imageReader.getHeight(), Bitmap.Config.ARGB_8888);

And it's important to use the imageReaders width/height (not the images).

When creating the imageReader/virtualDisplay objects I use the following method to get the display metrics.

   public static DisplayMetrics getScreenMetrics(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

        Display display = wm.getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);

        return dm;
    }

...
ImageReader imageReader = ImageReader.newInstance(displayMetrics.widthPixels, displayMetrics.heightPixels, PixelFormat.RGBA_8888, 2);

I've learned this from trial and error, so I apologize for not being able to give an explanation why.

CamHart
  • 3,825
  • 7
  • 33
  • 69
1

I am using Xamarin(.NET) and was able to FINALLY get this working, except for one problem (java code):

final ImageReader ir = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2);

PixelFormat.RGBA_8888 is not a valid parameter as the ImageReader requires an ImageFormatType. The following .NET code solves this:

_mImageReader = ImageReader.NewInstance(_mWidth, _mHeight, (ImageFormatType)Format.Rgba8888, 2);

Notice the casting of the follwing, with Format being of the Android.Graphics.Format enum:

(ImageFormatType)Format.Rgba8888

I hope this helps someone out there using Xamarin as this caused a ton of frustration over the last day!

hiNasty33
  • 21
  • 2