This question already has answers here:
Convert view to bitmap on Android
(9 answers)
Closed 6 years ago.
Ok, so I'll try my best to explain my problem.
I have used this code to get a "screenshot" of my FrameLayout
/**
* Function that takes a screenshot of the view passed and returns a bitmap for it.
*
* #param view {#link View}
* #return screenshot of the view passed
*/
public Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
Here is my FrameLayout
<FrameLayout
android:id="#+id/frame_layout_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/photoImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter" />
<com.my.android.util.DrawCustomView
android:id="#+id/draw_custom_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
DrawCustomView is used to paint on photoImageView.
Now I also have different activity to crop image. So, I saved this bitmap (using screenshot(view)) in a file and send the file path to this crop activity. In my crop activity I am using https://github.com/ArthurHub/Android-Image-Cropper library's CropImageView to crop the image.
When I try to crop the painted photo sent to crop activity I get a weird crop, something like this :
The image doubles on cropping too much :
https://drive.google.com/open?id=0B4jK5QX65b0ZSHdMTWIzZXluZXc
Before zooming in :
https://drive.google.com/open?id=0B4jK5QX65b0ZeUk3NUlGUHRSQ0E
This is how a normal picture appears in crop activity :
https://drive.google.com/open?id=0B4jK5QX65b0ZNk9oSG1ZaGxYOVk
I also notice that the bounds for cropping are restricted to image size in the normal case but when edited using screenshot(), the bounds take the size of the screen.
I have tested my crop activity beforehand and it works fine for images sent from camera.
I also tried to send a picture that is not obtained using screenshot function, and it worked fine in crop activity.
I'll be happy to provide more info, any help is much appreciated... I am relatively new to android development :)
EDIT
This video might give more perspective to the problem
https://drive.google.com/open?id=0B4jK5QX65b0ZSUVFZDlQeTc4QnM
public static Bitmap shot(View view) {
view.setDrawingCacheEnabled(true);
Bitmap bitmap = view.getDrawingCache();
view.setDrawingCacheEnabled(false);
return bitmap;
}
You can try this method to capture a screenshot of your view.
/**
* this method capture the image from provided view and save it to application internal directory.
*
* #param view to capture image.
* #return path of image saved in the phone.
*/
public static String captureScreenShotAndSave(Context mContext, View view) {
view.setBackgroundColor(Color.WHITE);
String mPath = mContext.getApplicationContext().getExternalCacheDir() + "/" + "IMG_" + DateTimeUtils.getCurrentTimeStamp() + "_" + SHARE_IMAGE_NAME;
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
view.draw(c);
c.drawBitmap(bitmap, 0, 0, null);
OutputStream fout = null;
File imageFile = new File(mPath);
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fout);//set image quality and formate as you required.
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return imageFile.getAbsolutePath();
}
You can call this method like YourUtilsClass.captureScreenShotAndSave(mContext, mViewToCapture);
Related
I am trying to capture a photo and after that, allow to the user to add some effects, draw, drag other assets to the image, add text, etc. Like snapchat camera.
I have followed the Camera 2 API sample. The major part of the code is at
Camera2BasicFragment.java
I have achieved the capture and preview image, but the example set the image in a TextureView, but I do not have idea how to continue to manipulate the image.
I dont know if I should use a TextureView or a Canvas or a SurfaceView.
An example of the final image result that I want:
Thanks in advance.
Capture your photo , save your image. Then in an ImageView you can apply all kind of effects that you want using Bitmap and ColorMatrix.
Here I give a small sample to make an image grayscale
public void toGrayscale() {
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
imageView.setColorFilter(filter);
}
After applying the effects just save drawable to image file like this:
public void saveDrawable(ImageView imageView) throws FileNotFoundException {
Bitmap bitmap = getBitmapFromImageView(imageView);
OutputStream fOut = null;
try {
fOut = new FileOutputStream(absolutePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, fOut);
} finally {
if (fOut != null) {
try {
fOut.close();
} catch (IOException e) {
//report error
}
}
}
}
#NonNull
private Bitmap getBitmapFromImageView(ImageView imageView) {
Drawable drawable = imageView.getDrawable();
Rect bounds = drawable.getBounds();
Bitmap bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.draw(canvas);
return bitmap;
}
There is a good library that will help you https://github.com/chrisbanes/PhotoView
To draw with a finger this question how to draw line on imageview along with finger in android should help you
Hope its helps!!
I have a LinearLayout and I am want to save the contents of that view as an image. I have it half working.
File imageFile;
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/a.png";
// create bitmap screen capture
View v1 = getWindow().getDecorView().getRootView();
Bitmap bitmap;
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
OutputStream fout = null;
imageFile = new File(mPath);
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 10, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
With the above code it will save a copy of the view, but only what's seen on the device screen. I have more information on the view that I want saved. The code above from here and this will only save the information seen on the screen as an image. I want all the information saved, even the information that is not on the screen (where you need to scroll to see).
How can I achieve that?
Another option is to use:
Bitmap b = Bitmap.createBitmap(width, height....)
v1.setLayoutParams // Full width and height of content
Canvas c = new Canvas(b);
v1.draw(c); // You now have full bitmap
saveBitmap(b);
Run a measure/layout pass on it and draw it to a canvas. Suppose your parent was called "view" and was a vertical LinearLayout:
view.measure(someWidth, MeasureSpec.UNSPECIFIED);
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.draw(c);
Everything I tried with setDrawingCacheEnabled and getDrawingCache was not working. The system was making an image but it just looked black.
Other people on SO seemed to be having a similar problem but the answers seemed either too complicated or irrelevant to my situation. Here are some of the ones I looked at:
Save view like bitmap, I only get black screen
Screenshot shows black
getDrawingCache always returns the same Bitmap
Convert view to bitmap on Android
bitmap is not saving properly only black image
Custom view converting to bitmap returning black image
And here is my code:
view.setDrawingCacheEnabled(true);
Bitmap bitmap = view.getDrawingCache();
try {
FileOutputStream stream = new FileOutputStream(getApplicationContext().getCacheDir() + "/image.jpg");
bitmap.compress(CompressFormat.JPEG, 80, stream);
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
view.setDrawingCacheEnabled(false);
I'm sharing my answer below in case anyone else makes the same mistake I did.
My problem was that my view was a TextView. The text on the TextView was black (naturally) and in the app the background looked white. However, I later recalled reading that a view's background is by default transparent so that whatever color is below shows through.
So I added android:background="#color/white" to the layout xml for the view and it worked. When I had been viewing the image before I had been looking at black text over a black background.
See the answer by #BraisGabin for an alternate way that does not require overdrawing the UI.
I just found a good option:
final boolean cachePreviousState = view.isDrawingCacheEnabled();
final int backgroundPreviousColor = view.getDrawingCacheBackgroundColor();
view.setDrawingCacheEnabled(true);
view.setDrawingCacheBackgroundColor(0xfffafafa);
final Bitmap bitmap = view.getDrawingCache();
view.setDrawingCacheBackgroundColor(backgroundPreviousColor);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
view.setDrawingCacheEnabled(cachePreviousState);
Where 0xfffafafa is the desired background color.
Used below code to get bitmap image for view it work fine.
public Bitmap loadBitmapFromView(View v) {
DisplayMetrics dm = getResources().getDisplayMetrics();
v.measure(View.MeasureSpec.makeMeasureSpec(dm.widthPixels,
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(dm.heightPixels,
View.MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap returnedBitmap =
Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(returnedBitmap);
v.draw(c);
return returnedBitmap;
}
This question already has answers here:
Convert view to bitmap on Android
(9 answers)
Closed 1 year ago.
I have posted same question but it's in near to my problem that's why i have posted it second time
Hi i want to capture image from RelativeLayout, for that i have used below code
captureRelativeLayout.setDrawingCacheEnabled(true);
bitmap = captureRelativeLayout.getDrawingCache(true).copy(
Config.ARGB_8888, false);
the problem is that when i start activity and get image from that view at that time it will work fine, but if i use it second time, the image is not being refreshed, means that previous bitmap is every time i getting.
Now if i close my activity and agian start it then i will get updated image but again not in second time
:( for more information look at the
can't share image properly android
Here are two ways to convert a view to a bitmap:
Use Drawing Cache:
RelativeLayout view = (RelativeLayout)findViewById(R.id.relativelayout);
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
view.setDrawingCacheEnabled(false);
I've had some issue with the drawing cache method when the view is very large (for example, a TextView in a ScrollView that goes far off the visable screen). In that case, using the next method would be better.
Use Canvas:
RelativeLayout view = (RelativeLayout)findViewById(R.id.relativelayout);
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
You should destroy the drawing cache after copying it, so the cache will be built again next time you call getDrawingCache().
The code would look like this:
captureRelativeLayout.setDrawingCacheEnabled(true);
bitmap = captureRelativeLayout.getDrawingCache(true).copy(Config.ARGB_8888, false);
captureRelativeLayout.destroyDrawingCache();
Or like this if you don't want to enable the flag:
captureRelativeLayout.buildDrawingCache(true);
bitmap = captureRelativeLayout.getDrawingCache(true).copy(Config.ARGB_8888, false);
captureRelativeLayout.destroyDrawingCache();
Reference: https://groups.google.com/d/msg/android-developers/IkRXuMtOA5w/zlP6SKlfX-0J
There is a Kotlin extension function in Android KTX:
val config: Bitmap.Config = Bitmap.Config.ARGB_8888
val bitmap = canvasView.drawToBitmap(config)
finally i got solution from this view.getDrawingCache() only works once
i just forget to put
captureRelativeLayout.setDrawingCacheEnabled(false);
i have done it by below code,
try {
if (bitmap != null) {
bitmap.recycle();
bitmap = null;
}
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
captureRelativeLayout.setDrawingCacheEnabled(true);
File sdcard = Environment.getExternalStorageDirectory();
File f = new File(sdcard, "temp.jpg");
FileOutputStream out = null;
out = new FileOutputStream(f);
captureRelativeLayout.setDrawingCacheEnabled(true);
bitmap = captureRelativeLayout.getDrawingCache(true).copy(
Config.ARGB_8888, false);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.close();
captureRelativeLayout.setDrawingCacheEnabled(false);
sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f)); // imageUri
sharingIntent.setType("image/jpg");
sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f)); // imageUri
startActivity(Intent.createChooser(sharingIntent, "Share Image"));
} catch (Exception e) {
e.printStackTrace();
}
As DrawingCache is depracated then in kotlin:
fun View.createBitmap(): Bitmap {
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
Canvas(bitmap).apply {
background?.draw(this) ?: this.drawColor(Color.WHITE)
draw(this)
}
return bitmap
}
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
"bitmap" is the final bitmap..
Is it possible to get a full bitmap from a viewgroup-object?
This code takes a 'screenshot' off the view group that's currently on the screen, but I want the whole view, also what's not currently on the screen.
public void export(ViewGroup view){
view.setDrawingCacheEnabled(true);
view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap bitmap = view.getDrawingCache(true);
}
Here I used ScrollView to get the whole view to bitmap
so Here u can use instead of scrollview anyother view group like linerlayout etc..
Bitmap map = loadBitmapFromView(getApplicationContext(),scrollView);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
map.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
//you can create a new file name "test.jpg" in sdcard folder.
File f = new File("/sdcard" +"/" + "mainemailpdf.jpg");
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
bArray = bytes.toByteArray();
// remember close de FileOutput
fo.close();
and for loadBitmapFromView method is:
public static Bitmap loadBitmapFromView(Context context, View v) {
Toast.makeText(context,
v.getMeasuredHeight() + "::::::::::::" + v.getMeasuredWidth(),
Toast.LENGTH_LONG).show();
if (v.getMeasuredHeight() > 0) {
v.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getWidth(), v.getWidth());
v.draw(c);
return b;
}
return null;
}
I hope it helps :)
Any query let me know.
It is not possible since Android system scales down the bitmap.
For ex - if your bitmap size is 480*800 then its size is 480*800*4 = 1536000.
The multiplication with 4 is because each pixel is 4 bytes - RGBA.
Meaning more than a mega and a half for every unscaled image. If the Android won't scale down image you will probably get
OutOfMemoryException after a few image loadings.
as
you have 3 options:
1) view.draw(canvas) you'll get the visible portion of the image(only what is actually being drawn to the screen)
2) getDrawingCache() - will give you the scaled down image.
3) Create custom view which saves the bitmap to the disk and loads it from there when requested