Take screen shot from web view in android - android

I have a web view that I need to take a screenshot from a site. People suggested me use the function capturePicture(), this function is deprecated. So I create bitmap from current site like this and save it as byte[ ] to the database:
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getWidth(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, stream);
DatabaseHelper.updateData(id, stream.toByteArray());
bitmap.recycle();
And load it in another Activity with Glide:
Glide.with(context).load(items.get(position).getImage())
.placeholder(R.drawable.ic_defualt)
.into(holder.ivShot);
Now, If the number of screenshots increases, The speed of the app decreases and Memory size increases. I know that the issue of bitmaps is very complicated, But there must be a way to take a picture of the web view without any memory leaks or slowdowns.
I try to use threads to get bitmap but it doesn't help. Anyone know How I can do it?

Related

View.draw(canvas) poor quality of child views

I am trying to solve problem when I get bitmap from view (with bad quality of childviews) and store it as PNG. There are some taken pictures using this code:
Bitmap b = Bitmap.createBitmap(
Math.round(General.getDisplayWidthPx()), Math.round(General.getDisplayHeightPx()), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas( b );
wallFrame.invalidate();
wallFrame.draw( canvas );
FileOutputStream out = new FileOutputStream(file);
b.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
When the childview is small the quality of childview is terrible.
But when it's larger the quality is better.
As you can see the smaller the picture, the lower the quality. I also tried deprecated methods:
wallFrame.setDrawingCacheEnabled(true);
Bitmap b = wallFrame.getDrawingCache();
wallFrame is ZoomLayout which extends RelativeLayout. Child views in wallFrame are SubScalingImageView which extends View. I think it's not caused by SubScalingImageView I've tried standard ImageView and result was the same. When I take screenshot of app, the result is better.
Pictures are loaded from user storage using Uri (so not from drawable). SubscalingImageView has own decoders. In app the quality of pictures is perfect.
I think problem is somewhere in view.draw(canvas). But I have no idea how to edit it to make it work.
I appreciate every idea. Thank you!

Android saving webview to gallery, intermediate bitmap is too big

I am trying to write a method in android to save the whole webview as an image as following:
bitmap = Bitmap.createBitmap(webView.getWidth(),
Math.round(webView.getContentHeight() * webView.getScale()), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, JPEG_COMPRESSION, out);
However, the bitmap is too big (more than 100 MB) and takes too much memory. Does anyone know any better method to keep the memory usage low?
The problem is the WebView is small, and the generated JPEG file is small but the intermediate Bitmap which is not used any more in other places is huge.
Set JPEG_COMPRESSION = 0-100 as it is a quality paramater of bitmap 0 meaning compress for small size, 100 meaning compress for max quality.
You can also set bitmap height and width using
BitmapFactory.Options bop
bop.outWidth
bop.outHeight

Android OOM when creating bitmap from view

i am creating a bitmap of layout. Its working fine in most of the devices but in few samsung devices, its throwing OOM. Below is the code I am using to convert the layout to bitmap
private void enableViewCache() {
viewToConvert.setDrawingCacheEnabled(true);
viewToConvert.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.AT_MOST));
viewToConvert.buildDrawingCache(true);
}
public Bitmap getBitmapFromView() {
Bitmap b = Bitmap.createBitmap(viewToConvert.getDrawingCache());
viewToConvert.setDrawingCacheEnabled(false);
viewToConvert.destroyDrawingCache();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
return b;
}
I am getting OOM at Bitmap.createBitmap call. I have checked most of the OOM bitmap issues in stackoverflow which mentioned about using sampling and all but I dont know how to implement that in this usecase.
I'm not sure what you're trying to accomplish, but in MOST cases you don't want to extract a Bitmap from a View. What you usually want is to maintain the bitmap on a different place (LRU Cache maybe?). My guess would be the view's drawing cache is the issue.
Anyway, the problem is probably the way you're handling a large bitmap. Read this article so you know how to sample, scale down, and other techniques so you don't get OOM.

Merging image from camera with image from drawables

I´m trying to merge 2 images, one is bitmap from camera, second one is .png file stored in drawables. What I did was that I used both images as bitmaps and I tried to merge them by using canvas, something like this:
Bitmap topImage = BitmapFactory.decodeFile("gui.png");
Bitmap bottomImage = BitmapFactory.decodeByteArray(arg0, 0, arg0.length);
Canvas canvas = new Canvas(bottomImage);
canvas.drawBitmap(topImage, 0, 0, null);
But I keep getting "Bitmap size exceeds VM budget" error all the time. I tried nearly everything, but still, it keeps throwing this error. Is there another way of merging 2 images? What i need to do is simple - I need to take photo and save it merged with that .PNG image stored in drawables. For example this app is very close to what i need - https://play.google.com/store/apps/details?id=com.hl2.hud&feature=search_result#?t=W251bGwsMSwyLDEsImNvbS5obDIuaHVkIl0.
Thanks :)
See the below code for combining two images.
This method returns combined bitmap
public Bitmap combineImages(Bitmap frame, Bitmap image) {
Bitmap cs = null;
Bitmap rs = null;
rs = Bitmap.createScaledBitmap(frame, image.getWidth() + 50,
image.getHeight() + 50, true);
cs = Bitmap.createBitmap(rs.getWidth(), rs.getHeight(),
Bitmap.Config.RGB_565);
Canvas comboImage = new Canvas(cs);
comboImage.drawBitmap(image, 25, 25, null);
comboImage.drawBitmap(rs, 0, 0, null);
if (rs != null) {
rs.recycle();
rs = null;
}
Runtime.getRuntime().gc();
return cs;
}
You can change height and width as per your requirements
Hope this will help...
How large are the images? I've only encountered this problem when trying to load large images into memory.
Is the byte array your decoding actually an image?
From a quick look at the android docs you can capture an image using the default camera app which may work in this situation.
http://developer.android.com/training/camera/photobasics.html
Also see this question: Capture Image from Camera and Display in Activity
Edit: You may also need to scale the image from the camera down if it is very large. See the end of the android page I linked to for details on that.

Android custom view save visible screen to bitmap

In my app the user manipulates a image, rotates, pinch, zoom etc. This is make within onDraw() using canvas.translate(), canvas.rotate() etc. Of course the image is big and after the manipulation of the image the user performs interactions with other Views. The thing is I don't want to redraw the whole big image over and over again only the visible part. So I'd like, after the user finishes operations, SAVE the current VISIBLE image on the screen to memory/bitmap/cache and redraw only that.
How can I achieve this ?
In the constructor of your custom View, enable the drawing cache like this: setDrawingCacheEnabled(true);. Then whenever you want to save the state of your Canvas you can call getDrawingCache(), which returns the desired Bitmap.
Documentation: getDrawingCache()
In your on draw initialize your Canvas with a bitmap.
keep a reference of this bitmap and save it whenever required.
I've found a really great article about what I needed HERE
To kepp thing clear, first I need to create a bitmap with the size of my View, then create a canvas for it, draw on canvas and then save it.
public void saveScreenshot() {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.draw(myGiganticImage)
File file = new File(context.getFilesDir() + "/cache.jpg");
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
cachedBackground = BitmapFactory.decodeFile(context.getFilesDir() + "/cache.jpg"
invalidate()
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
I simply call this on onDraw() when I need it. It will save a bitmap on internal memory which I can use to draw, instead of the big picture.
Following may help you :
(1)
View v = view.getRootView();
v.setDrawingCacheEnabled(true);
Bitmap b = v.getDrawingCache();
(2) This is a similar to another question at How to capture the android device screen content?
(3) You can try using this library
http://code.google.com/p/android-screenshot-library/ It introduces an Android Screenshot Library (ASL) which enables to programmatically capture screenshots from Android devices without requirement of having root access privileges.

Categories

Resources