How to load video thumbnails using square picasso library? - android

Currently I'm loading MediaStore Image Thumbnails using picasso into the ListView with the following snippet: (video.getData() returns the actual path of the image such as mnt/sdcard/...)
Picasso.with(this.context)
.load(new File(photo.getData()))
.resize(50, 50).config(config)
.centerCrop()
.into(viewHolder.imageViewItem);
Now I'm and unable to load the MediaStore Video Thumbnails by just passing the video.getData() instead of photo.getData()?

First You need to create VideoRequestHandler
public class VideoRequestHandler extends RequestHandler{
public String SCHEME_VIDEO="video";
#Override
public boolean canHandleRequest(Request data)
{
String scheme = data.uri.getScheme();
return (SCHEME_VIDEO.equals(scheme));
}
#Override
public Result load(Request data, int arg1) throws IOException
{
Bitmap bm;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
Size size = new Size(250, 250);
bm = ThumbnailUtils.createVideoThumbnail(new File(data.uri.getPath()), size, null);
} catch (IOException e) {
e.printStackTrace();
}
}
else
{
bm = ThumbnailUtils.createVideoThumbnail(data.uri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND);
}
return new Result(bm,LoadedFrom.DISK);
}
}
After That
VideoRequestHandler videoRequestHandler;
Picasso picassoInstance;
Build only once
videoRequestHandler = new VideoRequestHandler();
picassoInstance = new Picasso.Builder(context.getApplicationContext())
.addRequestHandler(videoRequestHandler)
.build();
Then load file from path
picassoInstance.load(VideoRequestHandler.SCHEME_VIDEO+":"+filepath).into(holder.videoThumbnailView);
Updated October 2020
ThumbnailUtils.createVideoThumbnail(data.uri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND);
is deprecated in Android Q. I will write in Kotlin:
val bm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ThumbnailUtils.createVideoThumbnail(
File(data.uri.path!!),
Size(200f.toPx(), 200f.toPx()),
CancellationSignal()
)
} else {
ThumbnailUtils.createVideoThumbnail(
data.uri.path!!,
MediaStore.Images.Thumbnails.MINI_KIND
)
}
to Px is an extension function which is like below;
fun Float.toPx() =
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)
.toInt()
You can use any dp value for it :) I hope this can help you :)

Before, you had two options:
1) Do a call beforehand, when you were retrieving your videos for example and storing the bitmap:
Bitmap thumbnailBitmap = MediaStore.Video.Thumbnails.getThumbnail(content, id, MediaStore.Video.Thumbnails.MINI_KIND, options);
2) Creating a custom Downloader (not verified for local media)
But now, with Picasso 2.4, you can create a RequestHandler. You can have a look at this page for example: http://blog.jpardogo.com/requesthandler-api-for-picasso-library/
In my current usage, I fetch the thumbnail path and then call Picasso with that path. To get the thumbnail path, I referred to: android get video thumbnail PATH, not Bitmap.

public void bindTo(MediaListHolder mediaListRowHolder, int i) {
DataPictures message = itemList.get(i);
try {
Uri uri = Uri.fromFile(new File(message.getFilePath()));
if (message.getFileType().equalsIgnoreCase("video")) {
Bitmap bmThumbnail = ThumbnailUtils.extractThumbnail(ThumbnailUtils.createVideoThumbnail(message.getFilePath(),
MediaStore.Video.Thumbnails.FULL_SCREEN_KIND), MAX_WIDTH, MAX_HEIGHT);
mediaListRowHolder.thumbnail.setImageBitmap(bmThumbnail);
} else {
Picasso.with(ApplicationSingleton.getInstance()).load(uri)
.resize(size, size)
.placeholder(R.drawable.logo_slogan)
.into(mediaListRowHolder.thumbnail);
}
Log.i(TAG, "bindTo: ");
} catch (Exception e) {
e.printStackTrace();
}
}

Note - Follow this comment if you simply want to show thumbnail in your image view and apply no extra Picasso functions on it .
I just modified it a little to show circular thumbnail coz it looks cool .
Don't use Picasso . Here's a very simple way to do it .
videoPathUrl = /*your Video File Url */
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(videoPathUrl , MediaStore.Video.Thumbnails.MICRO_KIND);
bMap = transformBitmapToCircularBitmap(bMap);
yourImageView.setImageBitmap(bMap);
and transformBitmapToCircularBitmap function is as follows -
public static Bitmap transformBitmapToCircularBitmap(Bitmap source)
{
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap,
BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}

Related

What is the specific difference between Bitmap from BitmapFactory.decodeFile and BitmapFactory.decodeResource in android

I use this photo filter from https://github.com/Zomato/AndroidPhotoFilters to develop my app
this is my code when i got IllegalStateExpression
Caused by: java.lang.IllegalStateException
at android.graphics.Bitmap.setPixels(Bitmap.java:1556)
at com.zomato.photofilters.imageprocessors.ImageProcessor.doBrightness(ImageProcessor.java:45)
at com.zomato.photofilters.imageprocessors.subfilters.BrightnessSubfilter.process(BrightnessSubfilter.java:28)
at com.zomato.photofilters.imageprocessors.Filter.processFilter(Filter.java:88)
at org.d3ifcool.photostation.PhotoEditorActivity.onCreate(PhotoEditorActivity.java:103)
at org.d3ifcool.photostation.PhotoEditorActivity.onCreate(PhotoEditorActivity.java:104)
on Bitmap image1 = mMyFilter.processFilter(mOriginalImage);
BitmapFactory.Options mOriginalOption = new BitmapFactory.Options();
mOriginalOption.inSampleSize = 2;
Bitmap mOriginalImage = BitmapFactory.decodeFile(selectedImagePath, mOriginalOption);
mMyFilter = SampleFilters.getBlueMessFilter();
Bitmap image1 = mMyFilter.processFilter(mOriginalImage);
loadFilter(image1);
But it'll success if i use this code
context = this.getApplicationContext();
Bitmap outputImage = mMyFilter.processFilter(Bitmap.createScaledBitmap(
BitmapFactory.decodeResource(
context.getResources(), R.drawable.ic_bg_main_activity), 640, 640, false));
loadFilter(outputImage);
And this the methode from the documentation
public Bitmap processFilter(Bitmap inputImage) {
Bitmap outputImage = inputImage;
if (outputImage != null) {
for (SubFilter subFilter : subFilters) {
try {
outputImage = subFilter.process(outputImage);
} catch (OutOfMemoryError oe) {
System.gc();
try {
outputImage = subFilter.process(outputImage);
} catch (OutOfMemoryError ignored) {
}
}
}
}
return outputImage;
}
Why cant i use the BitmapFactory.decodeFile?
I need to pick the image from SD Card, not from the drawable resouce.
Does .decodeFile and .decodeResource have a different type of Bitmap?
Sorry for my bad english
So, as the Bitmap returned by BitmapFactory.decodeFile is not null, your problem is with the processFilter method.
In the second example (the one you say it works), you create a scaled Bitmap before calling processFilter. So in order to solve your issue, you should probably do:
BitmapFactory.Options originalOption = new BitmapFactory.Options();
originalOption.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeFile(selectedImagePath, originalOption );
if (bitmap != null) {
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 640, 640, false);
mMyFilter = SampleFilters.getBlueMessFilter();
Bitmap image1 = mMyFilter.processFilter(scaledBitmap);
loadFilter(image1);
} else {
Log.e("Decode image", "Decoded Bitmap is null");
// Manage the error
}
Before applying filter you need to set its width and height for custom scaling then you can apply zomato(basic image processing library) filters on your bitmap image otherwise it will give you error.
public static void filterApply(Filter filter){
Bitmap bitmcopy = PhotoModel.getInstance().getPhotoCopyBitmap();
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmcopy, bitmcopy.getWidth()-1, bitmcopy.getHeight()-1, false);
filter.processFilter(scaledBitmap);
filterImage.setImageBitmap(scaledBitmap);
}

scaled bitmap according to device resolution

I am getting strange issue of White blank screen when i try to set image inside my image view after scaling it from bitmap.
I am getting random size images from server , I just need to show them in my image view without loose in quality of image. i have taken one layout and add image view dynamically through code.
Here is what i am doing in code :-
Getting Url form server and scaling it accordingly :-
url="http://www.petstory.co/attached_king_photos/hotel/7/attached_d67e2689e0d3370f7e76b5bba9f8e875e42a2e39.jpg"
AsyncTask task = new AsyncTask<String, String, Bitmap>() {
Bitmap bitmap = null;
#Override
protected Bitmap doInBackground(String... params) {
bitmap = getBitmapFromURL(params[0]);
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (result.getHeight() > 7000){
getResizedBitmap(result, 4000, 4000, image);
}else{
getResizedBitmap(result, 800, 800, image);
}
}
}.execute(imageUrl);
public Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight, final ImageView image) {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = bm.getWidth();
int height = bm.getHeight();
final int wantedgeightis = newHeight;
float scaleWidth = metrics.scaledDensity;
float scaleHeight = metrics.scaledDensity;
// float scaleWidth = ((float) newWidth) / width;
// float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
matrix.setRectToRect(new RectF(0, 0, bm.getWidth(), bm.getHeight()), new RectF(0, 0, newWidth, newHeight), Matrix.ScaleToFit.CENTER);
final Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
// final Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//
if (wantedgeightis == 4000) {
image.setScaleType(ImageView.ScaleType.FIT_XY);
image.setImageBitmap(resizedBitmap);
} else {
int bitmapWidth = resizedBitmap.getWidth();
int bitmapHeight = resizedBitmap.getHeight();
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, bitmapHeight);
image.setLayoutParams(params);
image.setPadding(10, 0, 10, 0);
image.setScaleType(ImageView.ScaleType.FIT_XY);
image.setImageBitmap(resizedBitmap);
}
}
});
return resizedBitmap;
}
The Url of image which i am setting in above methods is :-
http://www.petstory.co/attached_king_photos/hotel/7/attached_d67e2689e0d3370f7e76b5bba9f8e875e42a2e39.jpg
i am testing on nexus , rest images are aprearing as expected but only this image displays me white blank screen
I even make use of Glide and pisacco getting same issue for this image or sometimes highly distorted image get appear on screen.
Here is the code of Glide which i used :-
Glide.with(this) //passing context
.load(imageUrl) //passing your url to load image.
.placeholder(R.drawable.petzview_logo) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
.error(R.drawable.petz_test)//in case of any glide exception or not able to download then this image will be appear . if you won't mention this error() then nothing to worry placeHolder image would be remain as it is.
.diskCacheStrategy(DiskCacheStrategy.ALL) //using to load into cache then second time it will load fast.
.fitCenter()//this method help to fit image into center of your ImageView
.dontAnimate()
.override(700, 4000)
.into(image);
I Even tried with bellow code too :-
Glide.with(this)
.load(imageUrl)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.placeholder(R.drawable.petzview_logo)
.dontAnimate()
.fitCenter()
.into(new ViewTarget<ImageView, GlideDrawable>(image) {
#Override
public void onResourceReady(GlideDrawable resource, GlideAnimation anim) {
Toast.makeText(HowAboutHere.this, "success", Toast.LENGTH_LONG).show();
image.setImageDrawable(resource.getCurrent());
}
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
Toast.makeText(HowAboutHere.this, "Glide image load failed for %s -> %s" + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
image.setVisibility(View.INVISIBLE);
}
});
By using .override(700, 4000) , the image is getting displayed but streched and if i change value to .override(700, 4100) , then blank white screen start getting displayed due to very large image size
Or Should i First Save image from URL to any file and then retrieve the image from file and apply inSample size bitmap algo on it this will be time taking and with utilize more memory and make application slow.As mentioned in below two links :-
Best method to download image from url in Android
Strange out of memory issue while loading an image to a Bitmap object
However here i am also posting the image look like when i use Bitmap code form displaying huge image from URL
As you can see the image is still getting stretched.
Any help will be appreciated
Thanks!!!

Android Canvas drawBitmap function efficiency

I'm trying to display a bitmap on canvas using the matrix.
canvas.drawBitmap(currentBitmap, m_matrix, tempPaint);
but the result appears, image seems weird. After that I have shown it using bounds
canvas.drawBitmap(currentBitmap, 0, 0, tempPaint);
But here image looks good, in both the cases image is not scaled.
How should I set matrix properties for the initial display?
Does the matrix display uses something else for showing the image because of that image is getting changed?
Please suggest any tutorials for details explanation.
After searching lot a lot i have finally found the solution, some of the threads related to same issue helped me out.
Quality Issue
Quality problems when resizing an image at runtime
I have followed the google's Tutorials for loading the bitmap and written my own function for scaling the bitmap.
public static Bitmap scaleDownBitmap(Bitmap original, boolean recycleOriginal, int newmaxWidth , int newmaxHeight){
if(original == null)
return null;
Bitmap rtr= null;
try{
int origWidth = original.getWidth();
int origHeight = original.getHeight();
if(origWidth <= newmaxWidth && origHeight <= newmaxWidth){
Bitmap b = Bitmap.createBitmap(original);
if (recycleOriginal && (original != b))
original.recycle();
return b;
}
int newWidth = 0;
int newHeight = 0;
float ratio;
if(origWidth > origHeight){
ratio = (float)origWidth/(float)origHeight;
newWidth = newmaxWidth;
newHeight = (int)((float)newWidth/ratio);
}
else{
ratio = (float)origHeight/(float)origWidth;
newHeight = newmaxHeight;
newWidth = (int)((float)newHeight/ratio);
}
rtr = CreateScaledBitmap(original , newWidth , newHeight);
if(recycleOriginal && original != rtr)
original.recycle();
}
catch (Exception e) {
Log.d("Image Compress Error", e.getMessage());
}
return rtr;
}
public static Bitmap CreateScaledBitmap(Bitmap paramBitmap, int paramInt1, int paramInt2)
{
Bitmap localBitmap = Bitmap.createBitmap(paramInt1, paramInt2, paramBitmap.getConfig());
Canvas localCanvas = new Canvas(localBitmap);
localCanvas.setDrawFilter(new PaintFlagsDrawFilter(0, 2));
localCanvas.drawBitmap(paramBitmap, new Rect(0, 0, paramBitmap.getWidth(), paramBitmap.getHeight()),
new Rect(0, 0, paramInt1, paramInt2), null);
return localBitmap;
}
Now after getting the image i have passed the following parameters to the paint.
tempPaint.setFilterBitmap(true); //Line 1
canvas.drawBitmap(currentBitmap, m_matrix, tempPaint);
You have to use Matrix . post scale to scale the image, like in the example below.
private void drawMatrix(){
Matrix matrix = new Matrix();
matrix.postScale(curScale, curScale);
canvas.drawBitmap(currentBitmap, matrix, tempPaint);}
Haven't tried it yet.... But should work...

Converting pdf file to bitmap images

I am working with pdf files, I want to implement page viewer to my pdf file. My idea is to convert pdf file into bmp images, and then to use viewPager. but I am stuck in converting pdf to bitmap. Any suggestions?
Include dependencies in your gradle
compile 'com.github.barteksc:android-pdf-viewer:2.8.1'
Use following function to convert PDF page to bitmap image
private Bitmap generateImageFromPdf(String assetFileName, int pageNumber, int width, int height) {
PdfiumCore pdfiumCore = new PdfiumCore(mActivity);
try {
File f = FileUtils.fileFromAsset(mActivity, assetFileName);
ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
PdfDocument pdfDocument = pdfiumCore.newDocument(fd);
pdfiumCore.openPage(pdfDocument, pageNumber);
//int width = pdfiumCore.getPageWidthPoint(pdfDocument, pageNumber);
//int height = pdfiumCore.getPageHeightPoint(pdfDocument, pageNumber);
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
pdfiumCore.renderPageBitmap(pdfDocument, bmp, pageNumber, 0, 0, width, height);
//saveImage(bmp, filena);
pdfiumCore.closeDocument(pdfDocument);
return bmp;
} catch(Exception e) {
//todo with exception
}
return null;
}
this is a way to render pdf to image
its take 20 to 25 seconds to render pdf file to image
its working in android 10 , android 9 and all lower versions
private void generateImageFromPdf() {
try {
PDDocument doc=PDDocument.load(new File(fileurl));
PDFRenderer pdfRenderer = new PDFRenderer(doc);
Bitmap bffim = pdfRenderer.renderImageWithDPI(0, 100, Bitmap.Config.RGB_565);
String fileName = "image-" + 0 + ".png";
img.setImageBitmap(bffim);
} catch (IOException e) {
e.printStackTrace();
}
}

How to convert a Drawable to a Bitmap?

I would like to set a certain Drawable as the device's wallpaper, but all wallpaper functions accept Bitmaps only. I cannot use WallpaperManager because I'm pre 2.1.
Also, my drawables are downloaded from the web and do not reside in R.drawable.
This piece of code helps.
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon_resource);
Here a version where the image gets downloaded.
String name = c.getString(str_url);
URL url_value = new URL(name);
ImageView profile = (ImageView)v.findViewById(R.id.vdo_icon);
if (profile != null) {
Bitmap mIcon1 =
BitmapFactory.decodeStream(url_value.openConnection().getInputStream());
profile.setImageBitmap(mIcon1);
}
public static Bitmap drawableToBitmap (Drawable drawable) {
Bitmap bitmap = null;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if(bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
This converts a BitmapDrawable to a Bitmap.
Drawable d = ImagesArrayList.get(0);
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
A Drawable can be drawn onto a Canvas, and a Canvas can be backed by a Bitmap:
(Updated to handle a quick conversion for BitmapDrawables and to ensure that the Bitmap created has a valid size)
public static Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
int width = drawable.getIntrinsicWidth();
width = width > 0 ? width : 1;
int height = drawable.getIntrinsicHeight();
height = height > 0 ? height : 1;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
METHOD 1 : Either you can directly convert to bitmap like this
Bitmap myLogo = BitmapFactory.decodeResource(context.getResources(), R.drawable.my_drawable);
METHOD 2 : You can even convert the resource into the drawable and from that you can get bitmap like this
Bitmap myLogo = ((BitmapDrawable)getResources().getDrawable(R.drawable.logo)).getBitmap();
For API > 22 getDrawable method moved to the ResourcesCompat class so for that you do something like this
Bitmap myLogo = ((BitmapDrawable) ResourcesCompat.getDrawable(context.getResources(), R.drawable.logo, null)).getBitmap();
android-ktx has Drawable.toBitmap method: https://android.github.io/android-ktx/core-ktx/androidx.graphics.drawable/android.graphics.drawable.-drawable/to-bitmap.html
From Kotlin
val bitmap = myDrawable.toBitmap()
1) Drawable to Bitmap :
Bitmap mIcon = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon);
// mImageView.setImageBitmap(mIcon);
2) Bitmap to Drawable :
Drawable mDrawable = new BitmapDrawable(getResources(), bitmap);
// mImageView.setDrawable(mDrawable);
very simple
Bitmap tempBMP = BitmapFactory.decodeResource(getResources(),R.drawable.image);
The latest androidx core library (androidx.core:core-ktx:1.2.0) now has an extension function: Drawable.toBitmap(...) to convert a Drawable to a Bitmap.
So after looking (and using) of the other answers, seems they all handling ColorDrawable and PaintDrawable badly. (Especially on lollipop) seemed that Shaders were tweaked so solid blocks of colors were not handled correctly.
I am using the following code now:
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
// We ask for the bounds if they have been set as they would be most
// correct, then we check we are > 0
final int width = !drawable.getBounds().isEmpty() ?
drawable.getBounds().width() : drawable.getIntrinsicWidth();
final int height = !drawable.getBounds().isEmpty() ?
drawable.getBounds().height() : drawable.getIntrinsicHeight();
// Now we check we are > 0
final Bitmap bitmap = Bitmap.createBitmap(width <= 0 ? 1 : width, height <= 0 ? 1 : height,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Unlike the others, if you call setBounds on the Drawable before asking to turn it into a bitmap, it will draw the bitmap at the correct size!
Maybe this will help someone...
From PictureDrawable to Bitmap, use:
private Bitmap pictureDrawableToBitmap(PictureDrawable pictureDrawable){
Bitmap bmp = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(), pictureDrawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
canvas.drawPicture(pictureDrawable.getPicture());
return bmp;
}
... implemented as such:
Bitmap bmp = pictureDrawableToBitmap((PictureDrawable) drawable);
Here is the nice Kotlin version of the answer provided by #Chris.Jenkins here: https://stackoverflow.com/a/27543712/1016462
fun Drawable.toBitmap(): Bitmap {
if (this is BitmapDrawable) {
return bitmap
}
val width = if (bounds.isEmpty) intrinsicWidth else bounds.width()
val height = if (bounds.isEmpty) intrinsicHeight else bounds.height()
return Bitmap.createBitmap(width.nonZero(), height.nonZero(), Bitmap.Config.ARGB_8888).also {
val canvas = Canvas(it)
setBounds(0, 0, canvas.width, canvas.height)
draw(canvas)
}
}
private fun Int.nonZero() = if (this <= 0) 1 else this
Here is better resolution
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;
}
public static InputStream bitmapToInputStream(Bitmap bitmap) {
int size = bitmap.getHeight() * bitmap.getRowBytes();
ByteBuffer buffer = ByteBuffer.allocate(size);
bitmap.copyPixelsToBuffer(buffer);
return new ByteArrayInputStream(buffer.array());
}
Code from How to read drawable bits as InputStream
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon);
This will not work every time for example if your drawable is layer list drawable then it gives a null response, so as an alternative you need to draw your drawable into canvas then save as bitmap, please refer below a cup of code.
public void drawableToBitMap(Context context, int drawable, int widthPixels, int heightPixels) {
try {
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/", "drawable.png");
FileOutputStream fOut = new FileOutputStream(file);
Drawable drw = ResourcesCompat.getDrawable(context.getResources(), drawable, null);
if (drw != null) {
convertToBitmap(drw, widthPixels, heightPixels).compress(Bitmap.CompressFormat.PNG, 100, fOut);
}
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private Bitmap convertToBitmap(Drawable drawable, int widthPixels, int heightPixels) {
Bitmap bitmap = Bitmap.createBitmap(widthPixels, heightPixels, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, widthPixels, heightPixels);
drawable.draw(canvas);
return bitmap;
}
above code save you're drawable as drawable.png in the download directory
Android provides a non straight foward solution: BitmapDrawable. To get the Bitmap , we'll have to provide the resource id R.drawable.flower_pic to the a BitmapDrawable and then cast it to a Bitmap.
Bitmap bm = ((BitmapDrawable) getResources().getDrawable(R.drawable.flower_pic)).getBitmap();
BitmapFactory.decodeResource() automatically scales the bitmap, so your bitmap may turn out fuzzy. To prevent scaling, do this:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap source = BitmapFactory.decodeResource(context.getResources(),
R.drawable.resource_name, options);
or
InputStream is = context.getResources().openRawResource(R.drawable.resource_name)
bitmap = BitmapFactory.decodeStream(is);
Use this code.it will help you for achieving your goal.
Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.profileimage);
if (bmp!=null) {
Bitmap bitmap_round=getRoundedShape(bmp);
if (bitmap_round!=null) {
profileimage.setImageBitmap(bitmap_round);
}
}
public Bitmap getRoundedShape(Bitmap scaleBitmapImage) {
int targetWidth = 100;
int targetHeight = 100;
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth,
targetHeight,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
path.addCircle(((float) targetWidth - 1) / 2,
((float) targetHeight - 1) / 2,
(Math.min(((float) targetWidth),
((float) targetHeight)) / 2),
Path.Direction.CCW);
canvas.clipPath(path);
Bitmap sourceBitmap = scaleBitmapImage;
canvas.drawBitmap(sourceBitmap,
new Rect(0, 0, sourceBitmap.getWidth(),
sourceBitmap.getHeight()),
new Rect(0, 0, targetWidth, targetHeight), new Paint(Paint.FILTER_BITMAP_FLAG));
return targetBitmap;
}
ImageWorker Library can convert bitmap to drawable or base64 and vice versa.
val bitmap: Bitmap? = ImageWorker.convert().drawableToBitmap(sourceDrawable)
Implementation
In Project Level Gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
In Application Level Gradle
dependencies {
implementation 'com.github.1AboveAll:ImageWorker:0.51'
}
You can also store and retrieve bitmaps/drawables/base64 images from external.
Check here. https://github.com/1AboveAll/ImageWorker/edit/master/README.md
if you are using kotlin the use below code. it'll work
// for using image path
val image = Drawable.createFromPath(path)
val bitmap = (image as BitmapDrawable).bitmap
In Kotlin, the easiest way is:
Drawable.toBitmap(width: Int, height: Int, config: Bitmap.Config?): Bitmap
like this:
val bitmapResult = yourDrawable.toBitmap(1,1,null)
where, just need a drawable variable, No resource, No context, No id
// get image path from gallery
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
super.onActivityResult(requestCode, resultcode, intent);
if (requestCode == 1) {
if (intent != null && resultcode == RESULT_OK) {
Uri selectedImage = intent.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
//display image using BitmapFactory
cursor.close(); bmp = BitmapFactory.decodeFile(filepath);
iv.setBackgroundResource(0);
iv.setImageBitmap(bmp);
}
}
}
I've used a few answers on this thread but some of them didn't work as expected (maybe they had worked in older versions) but I wanted to share mine after a few tries and errors, using an extension function:
val markerOption = MarkerOptions().apply {
position(LatLng(driver.lat, driver.lng))
icon(R.drawabel.your_drawable.toBitmapDescriptor(context))
snippet(driver.driverId.toString())
}
mMap.addMarker(markerOption)
This is the extension function:
fun Int.toBitmapDescriptor(context: Context): BitmapDescriptor {
val vectorDrawable = ResourcesCompat.getDrawable(context.resources, this, context.theme)
val bitmap = vectorDrawable?.toBitmap(
vectorDrawable.intrinsicWidth,
vectorDrawable.intrinsicHeight,
Bitmap.Config.ARGB_8888
)
return BitmapDescriptorFactory.fromBitmap(bitmap!!)
}

Categories

Resources