Create Bitmap from RelativeLayout in Android - android

I have a RelativeLayout and wanna create a Bitmap from that and send to bluetooth printer in bytes.
According device resolution, when my bitmap is generate changes textviews fontsize - higher the resolution, higher the fontsize.
How can I generate only one size regardless of device resolution?
My Code:
layout.setDrawingCacheEnabled(true);
layout.measure(View.MeasureSpec.makeMeasureSpec(580, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(layout.getMeasuredHeight(), View.MeasureSpec.UNSPECIFIED));
layout.layout(0, 0, layout.getMeasuredWidth(), layout.getMeasuredHeight());
layout.buildDrawingCache(false);
Bitmap sImagem = Bitmap.createBitmap(layout.getDrawingCache(false));
layout.setDrawingCacheEnabled(false);
580 is the size of my paper and that is ok in printer!

try out this
private void takeScreenShot(){
int totalHeight = mScreenshotLayout.getHeight();
int totalWidth = mScreenshotLayout.getWidth();
Bitmap b = getBitmapFromView(mScreenshotLayout,totalHeight,totalWidth);
SendingMail(b);
}
public Bitmap getBitmapFromView(View view, int totalHeight, int totalWidth) {
Bitmap returnedBitmap = Bitmap.createBitmap(totalWidth,totalHeight ,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return returnedBitmap;
}

Related

Create bitmap overlay with some information

I've created a Bitmap [Thumbnail] which is fetched after picking a video from gallery.
Snippet:-
bm= ThumbnailUtils.createVideoThumbnail(currentFileUri.getPath(), MediaStore.Video.Thumbnails.MICRO_KIND);
I'm putting these bitmap in Gallery adapter which is meant from images only, tht's y i'm creating thumbnail of Video and putting there. But
I want to show some difference between image and video in Gallery Strip which can be done by overlaying VideoThumbnail with something like Play Option.
Tried to OverLay my Bitmap with Small Play Icon but it throws NullPointerException on Bitmap.CreateScaledBitmap(..)
Snippet:-
bm= ThumbnailUtils.createVideoThumbnail(currentFileUri.getPath(), MediaStore.Video.Thumbnails.MICRO_KIND);
Bitmap change = null;
Bitmap border = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_media_play);
int width = bm.getWidth();
int height = bm.getHeight();
change = Bitmap.createScaledBitmap(change, width, height, false);
Canvas canvas = new Canvas(change);
Bitmap scaledBorder = Bitmap.createScaledBitmap(border,width/2,height/2, false);
canvas.drawBitmap(scaledBorder, 0, 0,null);
Adding that newly Overlay Created bitmap on my adapter.
AddIPDActivity.this.data.add(bm);
Created Overlay BitMap with LayerDrawable
Bitmap on which overlay need to be done.
bm = ThumbnailUtils.createVideoThumbnail(currentFileUri.getPath(),MediaStore.Video.Thumbnails.MICRO_KIND);
LayerDrawable applied on Bitmap with custom image on it.
Resources r = getResources();
Drawable[] layers = new Drawable[2];
layers[0] = new BitmapDrawable(bm);
layers[1] = r.getDrawable(android.R.drawable.ic_media_play);
LayerDrawable layerDrawable = new LayerDrawable(layers);
Added Bitmap on Gallery - Adapter.
this.data.add(drawableToBitmap(geSingleDrawable(layerDrawable))); //data is adapter for Gallery.
Converting LayerDrawable into BitMap:-
LayerDrawable -> Drawable -> BitMap
public static Drawable geSingleDrawable(LayerDrawable layerDrawable){
int resourceBitmapHeight = 136, resourceBitmapWidth = 153;
float widthInInches = 0.9f;
int widthInPixels = (int)(widthInInches * SmartConsultant.getApplication().getResources().getDisplayMetrics().densityDpi);
int heightInPixels = widthInPixels * resourceBitmapHeight / resourceBitmapWidth;
int insetLeft = 10, insetTop = 10, insetRight = 10, insetBottom = 10;
layerDrawable.setLayerInset(1, insetLeft, insetTop, insetRight, insetBottom);
Bitmap bitmap = Bitmap.createBitmap(widthInPixels, heightInPixels, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
layerDrawable.setBounds(0, 0, widthInPixels, heightInPixels);
layerDrawable.draw(canvas);
BitmapDrawable bitmapDrawable = new BitmapDrawable(SmartConsultant.getApplication().getResources(), bitmap);
bitmapDrawable.setBounds(0, 0, widthInPixels, heightInPixels);
return bitmapDrawable;
}
public static Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
u r getting NPE because
Bitmap change = null;
change = Bitmap.createScaledBitmap(change, width, height, false);
change is always null. U r passing a null value.So, before passing change as a parameter of createScaledBitmap(parameters) assign a bitmap to change after that call this
change = Bitmap.createScaledBitmap(change, width, height, false);

How to convert text into bitmap in android? [duplicate]

This question already has an answer here:
Mirrored text in textview?
(1 answer)
Closed 9 years ago.
How to convert text into bitmap in android? I am facing an issue where I need to convert text to bitmap so that I can create the mirror image of the text.
this is how you get a bitmap from a view. (I assumed that with 'text' you were referring to textview
private static Bitmap get_view_image(View view) {
int w = view.getWidth();
int h = view.getHeight();
Bitmap bmp = Bitmap.createBitmap(w, h,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
canvas.drawColor(Color.WHITE);
Drawable bgDrawable = view.getBackground();
if (bgDrawable!=null) {
bgDrawable.draw(canvas);
}
else {
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
return bmp;
}
You can directly mirror the bitmap (if you have one) using
BitmapDrawable flip(BitmapDrawable d)
{
Matrix m = new Matrix();
m.preScale(-1, 1);
Bitmap src = d.getBitmap();
Bitmap dst = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), m, false);
dst.setDensity(DisplayMetrics.DENSITY_DEFAULT);
return new BitmapDrawable(dst);
}

set bitmap which was created from RelativeLayout to imageView

I have RelativeLayout and I want to convert it to the Bitmap like this:
public static Bitmap getBitmapFromView(View view) {
if (view != null)
{ Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable =view.getBackground();
if (bgDrawable!=null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return returnedBitmap;
}
else
return null;
}
then I create RelativeLayout cView in the onCreate() method dynamically and set it to the ImageView like this:
dialer = (ImageView) findViewById(R.id.imageView_ring);
dialer.setImageBitmap(getBitmapFromView(cView));
and get error:
05-20 13:48:27.509: E/AndroidRuntime(28367):
java.lang.RuntimeException: Unable to start activity
ComponentInfo{ru.biovamp.widget/ru.biovamp.widget.TestCircleAct}:
java.lang.IllegalArgumentException: width and height must be > 0
I also tried to add bitmap to the ImageView from the onStart() method, but got the same result. What solution can I use?
I've solved my issue like this:
public Bitmap getBitmapFromView() {
this.measure(MeasureSpec.makeMeasureSpec(createNewRelativeLayoutParams().width, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(createNewRelativeLayoutParams().height, MeasureSpec.UNSPECIFIED));
this.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight());
Bitmap returnedBitmap = Bitmap.createBitmap(this.getMeasuredWidth(), this.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(returnedBitmap);
this.draw(c);
return returnedBitmap;
}
so solution is that we should to call measure() and layout() methods before drawing it.
oficial explaniton

Getting screenshot from a LinearLayout

I have a LinearLayout that contains a lot of sub LinearLayouts which contain TextViews. I want to get a screenshot from the parent LinearLayout to get a full view of my "Receipt". So I tried to do that:
View v = findViewById(R.id.llReceipt);
v.setDrawingCacheEnabled(true);
Bitmap b = v.getDrawingCache();
the problem is the Bitmap b get a null value.
Is there any solution to solve it?
I don't know why your bitmap is null but I've used this bit before to get a screen shot of a custom view and it worked:
public Bitmap getBitmapFromView(View view, int width, int height) {
Bitmap returnedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = view.getBackground();
if (view==mainPage.boardView) {
canvas.drawColor(BoardView.BOARD_BG_COLOR);
} else if (bgDrawable!=null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
view.layout(0, 0, width, height);
view.draw(canvas);
return returnedBitmap;
}
Taken from here!
I found my problem:
I called the getScreenShot() Function from the onCreate() Function which doesn't work.
it should call it after this step.

Converting a view to Bitmap without displaying it in Android?

I will try to explain what exactly I need to do.
I have 3 separate screens say A,B,C. There is another screen called say HomeScreen where all the 3 screens bitmap should be displayed in Gallery view and the user can select in which view does he wants to go.
I have been able to get the Bitmaps of all the 3 screens and display it in Gallery view by placing all the code in HomeScreen Activity only. Now, this has complicated the code a lot and I will like to simplify it.
So, can I call another Activity from HomeScreen and do not display it and just get the Bitmap of that screen. For example, say I just call HomeScreen and it calls Activity A,B,C and none of the Activities from A,B,C are displayed. It just gives the Bitmap of that screen by getDrawingCache(). And then we can display those bitmaps in Gallery view in HomeScreen.
I hope I have explained the problem very clearly.
Please let me know if this is actually possible.
there is a way to do this. you have to create a Bitmap and a Canvas and call view.draw(canvas);
here is the code:
public static Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap( v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
v.draw(c);
return b;
}
if the view wasn't displayed before the size of it will be zero. Its possible to measure it like this:
if (v.getMeasuredHeight() <= 0) {
v.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.draw(c);
return b;
}
EDIT: according to this post, Passing WRAP_CONTENT as value to makeMeasureSpec() doesn't to do any good (although for some view classes it does work), and the recommended method is:
// Either this
int specWidth = MeasureSpec.makeMeasureSpec(parentWidth, MeasureSpec.AT_MOST);
// Or this
int specWidth = MeasureSpec.makeMeasureSpec(0 /* any */, MeasureSpec.UNSPECIFIED);
view.measure(specWidth, specWidth);
int questionWidth = view.getMeasuredWidth();
here is my solution:
public static Bitmap getBitmapFromView(View view) {
Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable =view.getBackground();
if (bgDrawable!=null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return returnedBitmap;
}
Enjoy :)
I know this may be a stale issue, but I was having problems getting any of these solutions to work for me.
Specifically, I found that if any changes were made to the view after it was inflated that those changes would not get incorporated into the rendered bitmap.
Here's the method which ended up working for my case. With one caveat, however. prior to calling getViewBitmap(View) I inflated my view and asked it to layout with known dimensions. This was needed since my view layout would make it zero height/width until content was placed inside.
View view = LayoutInflater.from(context).inflate(layoutID, null);
//Do some stuff to the view, like add an ImageView, etc.
view.layout(0, 0, width, height);
Bitmap getViewBitmap(View view)
{
//Get the dimensions of the view so we can re-layout the view at its current size
//and create a bitmap of the same size
int width = view.getWidth();
int height = view.getHeight();
int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
//Cause the view to re-layout
view.measure(measuredWidth, measuredHeight);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
//Create a bitmap backed Canvas to draw the view into
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
//Now that the view is laid out and we have a canvas, ask the view to draw itself into the canvas
view.draw(c);
return b;
}
The "magic sauce" for me was found here:
https://groups.google.com/forum/#!topic/android-developers/BxIBAOeTA1Q
Cheers,
Levi
Try this,
/**
* Draw the view into a bitmap.
*/
public static Bitmap getViewBitmap(View v) {
v.clearFocus();
v.setPressed(false);
boolean willNotCache = v.willNotCacheDrawing();
v.setWillNotCacheDrawing(false);
// Reset the drawing cache background color to fully transparent
// for the duration of this operation
int color = v.getDrawingCacheBackgroundColor();
v.setDrawingCacheBackgroundColor(0);
if (color != 0) {
v.destroyDrawingCache();
}
v.buildDrawingCache();
Bitmap cacheBitmap = v.getDrawingCache();
if (cacheBitmap == null) {
Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException());
return null;
}
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
// Restore the view
v.destroyDrawingCache();
v.setWillNotCacheDrawing(willNotCache);
v.setDrawingCacheBackgroundColor(color);
return bitmap;
}
There is a great Kotlin extension function in Android KTX: View.drawToBitmap(Bitmap.Config)
Layout or view to bitmap:
private Bitmap createBitmapFromLayout(View tv) {
int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
tv.measure(spec, spec);
tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap(tv.getMeasuredWidth(), tv.getMeasuredWidth(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
c.translate((-tv.getScrollX()), (-tv.getScrollY()));
tv.draw(c);
return b;
}
Calling Method:
Bitmap src = createBitmapFromLayout(View.inflate(this, R.layout.sample, null)/* or pass your view object*/);
I think this is a bit better :
/**
* draws the view's content to a bitmap. code initially based on :
* http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
*/
#Nullable
public static Bitmap drawToBitmap(final View viewToDrawFrom, int width, int height) {
boolean wasDrawingCacheEnabled = viewToDrawFrom.isDrawingCacheEnabled();
if (!wasDrawingCacheEnabled)
viewToDrawFrom.setDrawingCacheEnabled(true);
if (width <= 0 || height <= 0) {
if (viewToDrawFrom.getWidth() <= 0 || viewToDrawFrom.getHeight() <= 0) {
viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
width = viewToDrawFrom.getMeasuredWidth();
height = viewToDrawFrom.getMeasuredHeight();
}
if (width <= 0 || height <= 0) {
final Bitmap bmp = viewToDrawFrom.getDrawingCache();
final Bitmap result = bmp == null ? null : Bitmap.createBitmap(bmp);
if (!wasDrawingCacheEnabled)
viewToDrawFrom.setDrawingCacheEnabled(false);
return result;
}
viewToDrawFrom.layout(0, 0, width, height);
} else {
viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
}
final Bitmap drawingCache = viewToDrawFrom.getDrawingCache();
final Bitmap bmp = ThumbnailUtils.extractThumbnail(drawingCache, width, height);
final Bitmap result = bmp == null || bmp != drawingCache ? bmp : Bitmap.createBitmap(bmp);
if (!wasDrawingCacheEnabled)
viewToDrawFrom.setDrawingCacheEnabled(false);
return result;
}
Using the above code, you don't have to specify the size of the bitmap (use 0 for width&height) if you want to use the one of the view itself.
Also, if you wish to convert special views (SurfaceView, Surface or Window, for example) to a bitmap, you should consider using PixelCopy class instead. It requires API 24 and above though. I don't know how to do it before.
Hope this helps
View view="some view instance";
view.setDrawingCacheEnabled(true);
Bitmap bitmap=view.getDrawingCache();
view.setDrawingCacheEnabled(false);
Update
getDrawingCache() method is deprecated in API level 28. So look for other alternative for API level > 28.
I used this just a few days ago:
fun generateBitmapFromView(view: View): Bitmap {
val specWidth = View.MeasureSpec.makeMeasureSpec(1324, View.MeasureSpec.AT_MOST)
val specHeight = View.MeasureSpec.makeMeasureSpec(521, View.MeasureSpec.AT_MOST)
view.measure(specWidth, specHeight)
val width = view.measuredWidth
val height = view.measuredHeight
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
view.layout(view.left, view.top, view.right, view.bottom)
view.draw(canvas)
return bitmap
}
This code is based in this gist
I had a similar need and developed something based on codes provided, specially the one by #Azhagthott and the brand new androidx.core.view.drawToBitmap, hopefully this will be hopeful here also,
val view = MyCustomView(context)
view.measure(
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST)
)
view.layout(0, 0, width, height)
val bitmap = view.drawToBitmap()
private fun getBitmapFromView(view: View): Bitmap
{
val returnedBitmap = Bitmap.createBitmap(view.width,
view.height
,Bitmap.Config.ARGB_8888)
val canvas = Canvas(returnedBitmap)
//background image
val bgDrawable = view.background
//background image is selected
if (bgDrawable != null){
bgDrawable.draw(canvas)
}
else{
canvas.drawColor(Color.WHITE)
}
view.draw(canvas)
return returnedBitmap
}
I had the same problem in my project and found a solution, which I will describe here.
public Bitmap catchBitmapFromView(View capture_view){
if (capture_view == null) {
return null;
}
capture_view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(capture_view.getWidth(), capture_view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Drawable bgDrawable = capture_view.getBackground();
if (bgDrawable != null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
capture_view.draw(canvas);
capture_view.setDrawingCacheEnabled(false);
return bitmap;
}
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);

Categories

Resources