I am working on recording my screen with MediaProjection
as follows
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x;
displayHeight = size.y;
imageReader = ImageReader.newInstance(displayWidth, displayHeight, ImageFormat.JPEG, 5);
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
DisplayMetrics metrics = getResources().getDisplayMetrics();
int density = metrics.densityDpi;
mediaProjection.createVirtualDisplay("test", displayWidth, displayHeight, density, flags,
imageReader.getSurface(), null, projectionHandler);
Image image = imageReader.acquireLatestImage();
byte[] data = getDataFromImage(image);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Problem is that captured images contains black frame like image below.
EDIT
The above issue can be solved with bitmap operations.
However, I am now looking for a solution that can be applied to MediaProjection or to SurfaceView of ImageReader to implement device recording.
I had a similar issue. The following code exhibits this problem.
final DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
final int width = metrics.widthPixels;
final int height = metrics.heightPixels;
final int densityDpi = metrics.densityDpi;
final int MAX_IMAGES = 10;
mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, MAX_IMAGES);
mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCaptureTest",
width, height, densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);
Replacing this:
getWindowManager().getDefaultDisplay().getMetrics(metrics);
With this:
getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
Fixes it. The problem is that the decorations around the image corrupt the actual resolution of the screen. getMetrics() returns a height (or width in landscape) that is not accurte, and has the home, back, etc, buttons subtracted. The actual display area available for developers is (1440 x 2326... or something like that). But of course, the captured image is going to be the full 1440 X 2560 screen resolution.
If you do not have control over the image yourself, you can modify it by doing something like, assuming your Bitmap is called image.
Bitmap imageWithBG = Bitmap.createBitmap(image.getWidth(), image.getHeight(),image.getConfig()); // Create another image the same size
imageWithBG.eraseColor(Color.BLACK); // set its background to white, or whatever color you want
Canvas canvas = new Canvas(imageWithBG); // create a canvas to draw on the new image
canvas.drawBitmap(image, 0f, 0f, null); // draw old image on the background
image.recycle();
Based on your comments I think this is what you are looking for
Bitmap bitmap; //field
Bitmap croppedBitmap; // field
Image image;// field
Handler mHandler; //field
new Thread() {
#Override
public void run() {
Looper.prepare();
mHandler = new Handler();
Looper.loop();
}
}.start();
imageAvailableListener = new ImageReader.OnImageAvailableListener {
#Override
public void onImageAvailable(ImageReader reader) {
try {
image = reader.acquireLatestImage();
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Rect rect = image.getCropRect();
croppedBitmap = Bitmap.createBitmap(bitmap,rect.left,rect.top,rect.width(),rect.height());
\\Do whatever here...
image.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bitmap!=null) {
bitmap.recycle();
}
if (croppedBitmap!=null) {
bitmap.recycle();
}
if (image!=null) {
image.close();
}
}
}
}
imageReader.setOnImageAvailableListener(imageAvailableListener, mHandler);
Related
I am trying to set bitmap as wallpaper. I am scaling the bitmap to the size of the screen (desired wallpaper size) before setting the wallpaper. Logging the desired size and the size of the scaled image shows confirms that the bitmap has the expected size. Still, the wallpaper gets zoomed in and the whole image isn't visible on the wallpaper. Could anyone point me in the correct direction? Here is the code I am using to scale and set the wallpaper.
DisplayMetrics metrics = new DisplayMetrics();
WindowManager windowManager =
(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
display.getMetrics(metrics);
final int screenWidth = metrics.widthPixels;
final int screenHeight = metrics.heightPixels;
Context thisContext = MyApplication.getApp().getApplicationContext();
WallpaperManager myWallpaperManager = WallpaperManager.getInstance(thisContext);
// myWallpaperManager.setWallpaperOffsetSteps(1, 1);
// myWallpaperManager.suggestDesiredDimensions(screenWidth, screenHeight);
// 3. Get the desired size.
final int width = myWallpaperManager.getDesiredMinimumWidth();
final int height = myWallpaperManager.getDesiredMinimumHeight();
// 4. Scale the wallpaper.
Bitmap bitmap = getBitmap();
Bitmap wallpaper = Bitmap.createScaledBitmap(bitmap, width, height, true);
Log.i("wapper", "updateWallpaper: "+width+" "+height+" "+wallpaper.getWidth()+" "+wallpaper.getHeight());
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
// sets both at same time
myWallpaperManager.setBitmap(
wallpaper,null, false,
WallpaperManager.FLAG_LOCK | WallpaperManager.FLAG_SYSTEM);
LogUtil.LOG_D(TAG, "completed updating wallpapers");
} else {
myWallpaperManager.setBitmap(wallpaper);
}
The code I am using to set a background to a bitmap is
wallpaperManager.setBitmap(result, null, true, WallpaperManager.FLAG_SYSTEM);
wallpaperManager2.setBitmap(result, null, true, WallpaperManager.FLAG_LOCK);
However, the image is not centered and I believe it has to do with the null parameter, which accepts a Rect as visibleCropHint.
How would I set the result bitmap to be centered by X and Y?
As doc says:
Passing null for this parameter means that the full image should be
displayed if possible given the image's and device's aspect ratios,
etc.
So can't guarantee image displayed fully.
Try this(from here):
Bitmap img = BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.paper));
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Bitmap bitmap = Bitmap.createScaledBitmap(img, width, height, true);
WallpaperManager wallpaperManager = WallpaperManager.getInstance(MainActivity.this);
try {
wallpaperManager.setBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
Using the MediaProjection API for screen capture, I create an ImageReader and feed use it as a point of access for captured screens as below:
mImageReader = ImageReader.newInstance(mWidth, mHeight, ImageFormat.JPEG, 2);
and
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
Bitmap bitmap = null;
image = mImageReader.acquireLatestImage();
Image.Plane[] planes = image.getPlanes();
Buffer buffer = planes[0].getBuffer().rewind();
bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
}
});
But the resulting image is always a blank transparent image and all pixels in the resulting bitmap are set to #00000000 :(
I've been stuck on this for a while and could really use some help so any advice is welcome. (Also I've already tried these posts but its all the same result - this, this and this)
Edit:
I pass the image reader surface in this line:
DisplayMetrics metrics = getResources().getDisplayMetrics();
int density = metrics.densityDpi;
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
mWidth = size.x;
mHeight = size.y;
mMediaProjection.createVirtualDisplay("screencap", mWidth, mHeight, density, flags, mImageReader.getSurface(), null, mHandler);
Whenever i set a wallpaper, after 1 sec it is zooming and stretching. How to set my image as fit wallpaper? (My image is good enough for wallpaper. 1080*1920).
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Bitmap tempbitMap = BitmapFactory.decodeResource(
getResources(), R.drawable.a);
Bitmap bitmap = Bitmap.createScaledBitmap(tempbitMap, width,
height, true);
WallpaperManager wallpaperManager = WallpaperManager
.getInstance(MainActivity.this);
wallpaperManager.setWallpaperOffsetSteps(1, 1);
wallpaperManager.suggestDesiredDimensions(width, height);
try {
wallpaperManager.setBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}`
This problem happens only in original device. For emulator it works fine.
This question already has answers here:
Android scaling of images to screen density
(3 answers)
Closed 7 months ago.
actually I'm trying to create simple app with wallpapers.
I'm trying to scale my image to user device screen size.
I'm using code like bellow:
/*
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
*/
Display metrics = getWindowManager().getDefaultDisplay();
int height = metrics.getHeight();
int width = metrics.getWidth();
float fourToThree;
int wymiar;
Bitmap mbitmap; //definicja zmiennej przechowującej bitmapę
try {
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), cardBase.cardImages[position]);
//UP - zapisanie obrazu z tablicy do zmiennej bitmapy
/*if(height>=width) {
fourToThree = height * 0.75f; //height
wymiar = (int)Math.round(fourToThree);
mbitmap = Bitmap.createScaledBitmap(myBitmap, height, wymiar, true);
} else {
fourToThree = height * 0.75f;
wymiar = (int)Math.round(fourToThree);
mbitmap = Bitmap.createScaledBitmap(myBitmap, width, wymiar, true);
}*/
mbitmap = Bitmap.createScaledBitmap(myBitmap, width, height, true);
myWallpaper.setBitmap(mbitmap);
Toast.makeText(SelectedCard.this, "Wallpaper changed", Toast.LENGTH_LONG).show();
}
catch (IOException e) {
e.printStackTrace();
Toast.makeText(SelectedCard.this, "Sorry, an error occurred", Toast.LENGTH_LONG).show();
}
I was trying many other ways but still have my image larger then device screen :(
I'm testing it on virtual phone and I was trying to create image dit 160 dpi as a device screen, it's not working too.
Can anyone tell me, how can I scale my image (jpg - 320 x 480 px, 300 dpi) to set it as a wallpaper on device ?
Any ideas ?
thanks :)
Ps. sorry for text mistakes, English is my second language ;p
Ok, i have something like that:
imgView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
WallpaperManager myWallpaper = WallpaperManager.getInstance(getApplicationContext());
try
/*{
myWallpaper.setResource(HdImageBase.HdImages[position]);
Toast.makeText(ImageMini.this, "Wallpaper changed", Toast.LENGTH_LONG).show();
}*/
{
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
float fourToThree;
int wymiar;
Bitmap mbitmap; //definicja zmiennej przechowującej bitmapę
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), cardBase.cardImages[position]);
mbitmap = Bitmap.createScaledBitmap(myBitmap, width, height, true);
myWallpaper.setBitmap(mbitmap);
Toast.makeText(SelectedCard.this, "Wallpaper changed \n" + width + "\n" + height, Toast.LENGTH_LONG).show();
}
catch (IOException e) {
e.printStackTrace();
Toast.makeText(SelectedCard.this, "Sorry, an error occurred", Toast.LENGTH_LONG).show();
}
}
});
Width and height values are correct 320 x 480 but image which I'm setting as a wallpaper is still more bigger then my device scren.
After test on my real phone LG L5 with new android (not sure which version). Image is set as wallpaper correct (in portrait mode - 1 image for all 5 "roll screens" without scaling).
How can i tested it on other devices ?
Mean... is this portrait mode for wallpapers is available only in new android version ?
Try this may work :
ImageView property :android:scaleType=“fitXY”
There are 2 ways to scale bitmap to fit a screen:
1st:
the follow function draws the specified bitmap, scaling/translating automatically to fill the destination rectangle:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect src, dst;
int widthOfBitmapSrc, heightOfBitmapSrc;
widthOfBitmapSrc = mBitmapSrc.getWidth();
heightOfBitmapSrc = mBitmapSrc.getHeight();
src = new Rect(0, 0, widthOfBitmapSrc, heightOfBitmapSrc);//size of bitmap
dst = new Rect(0,0,this.getWidth(),this.getHeight());//size of this view
canvas.drawBitmap(mBitmapSrc, src, dst, null);//scale bitmap from src to dst
}
see this link:http://developer.android.com/reference/android/graphics/Canvas.html
2nd:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int widthOfNewBitmap, heightOfNewBitmap;
widthOfNewBitmap = this.getWidth();//width of this view
heightOfNewBitmap = this.getHeight();//height of this view
Bitmap newBitmap = Bitmap.createScaledBitmap(mBitmapSrc, widthOfNewBitmap,heightOfNewBitmap,true);
canvas.drawBitmap(mBitmapSrc, 0, 0, null);//copy bitmap to canvas of this view without scale
}