In my Android app, I am using a custom ImageView class (Banner) to display images pulled from Facebook Events. While running the app, I notice that there is a large heap size (120 MB) while running the app. I used MAT and I think I've narrowed it down to byte[] and then finally to ImageView. Please check the pictures below to see how I came to this conclusion.
Now, I've read similar posts and I tried recycling my bitmap, using WeakReferences, creating a cache, but nothing seems to be reducing the memory size. However, recycling my bitmap threw me an error which said that I can't use a recycled bitmap (I feel like that may be a hint because it's keeping my bitmap in memory?).
The app isn't running slowly on my phone (It even only says a CPU usage of 1.5% even though the memory is on average 100 MB). I will post my Banner subclass and how I download the images to see if anyone can help me.
Banner.java:
public class Banner extends ImageView {
public Banner(Context context) {
super(context);
}
public Banner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Banner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = 400;
if (getDrawable() != null && getDrawable().getIntrinsicWidth() != 0){
height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
if (height < 500)
height = 700;
}
setMeasuredDimension(width, height);
setColorFilter(Color.rgb(123, 123, 123), android.graphics.PorterDuff.Mode.MULTIPLY);
}
public void onDestroy(){
Drawable drawable = this.getDrawable();
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
bitmap.recycle();
}
this.setImageBitmap(null);
}
}
BannerLoader.java:
public class BannerLoader{
private String url;
private WeakReference<ImageView> cover;
private LruCache<String, WeakReference<Bitmap>> mMemoryCache;
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
public BannerLoader(String cover_url, WeakReference<ImageView> cover, Drawable defaultDrawable) {
this.url = cover_url;
this.cover = cover;
cover.get().setBackground(defaultDrawable);
mMemoryCache = new LruCache<String, WeakReference<Bitmap>>(cacheSize) {
#Override
protected int sizeOf(String key, WeakReference<Bitmap> bitmap) {
// The cache size will be measured in kilobytes rather than
// number of items.
return bitmap.get().getByteCount() / 1024;
}
};
new DownloadImage().execute();
}
public void addBitmapToMemoryCache(String key, WeakReference<Bitmap> bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
public WeakReference<Bitmap> getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
class DownloadImage extends AsyncTask<Void, Void, WeakReference<Bitmap>>{
protected WeakReference<Bitmap> doInBackground(Void... params){
try {
final WeakReference<Bitmap> cachedBitmap = getBitmapFromMemCache(url);
if (cachedBitmap != null){
return cachedBitmap;
} else{
URL pictureURL = new URL(url);
HttpGet httpRequest = null;
httpRequest = new HttpGet(pictureURL.toURI());
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient
.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity b_entity = new BufferedHttpEntity(entity);
InputStream input = b_entity.getContent();
WeakReference<Bitmap> bitmap = new WeakReference<Bitmap>(BitmapFactory.decodeStream(input));
addBitmapToMemoryCache(url, bitmap);
return bitmap;
}
} catch(Exception ex){
ex.printStackTrace();
}
return null;
}
public void onPostExecute(WeakReference<Bitmap> image){
if (image != null && cover.get() != null){
cover.get().setImageBitmap(image.get());
}
}
}
}
So, as an example, I download an image like this:
new BannerLoader(tempEvent.getCover_url(), new WeakReference<ImageView>(thumb_image), context.getResources().getDrawable(R.drawable.placeholder));
Thanks for the help!
Related
I want to load the image from URL through picasso library to subsampling-scale-image-view in android studio.
I had tried the picasso decoder and picasso region decoder but it gives error on okhttp3downloader client constructor.
public class PicassoRegionDecoder implements ImageRegionDecoder {
private OkHttpClient client;
private BitmapRegionDecoder decoder;
private final Object decoderLock = new Object();
public PicassoRegionDecoder (OkHttpClient client) {
this.client = client;
}
#Override
public Point init(Context context, Uri uri) throws Exception {
OkHttp3Downloader downloader=new OkHttp3Downloader(client);
//OkHttpDownloader downloader = new OkHttpDownloader(client);
InputStream inputStream = downloader.load(uri, 0).getInputStream();
this.decoder = BitmapRegionDecoder.newInstance(inputStream, false);
return new Point(this.decoder.getWidth(), this.decoder.getHeight());
}
#Override
public Bitmap decodeRegion(Rect rect, int sampleSize) {
synchronized(this.decoderLock) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = this.decoder.decodeRegion(rect, options);
if(bitmap == null) {
throw new RuntimeException("Region decoder returned null bitmap - image format may not be supported");
} else {
return bitmap;
}
}
}
#Override
public boolean isReady() {
return this.decoder != null && !this.decoder.isRecycled();
}
#Override
public void recycle() {
this.decoder.recycle();
}
}
cannot resolve constructor OkHttpDownloader(client)
ANSWER
Subsampling scale image view is an "old" post.
You have to be careful of the imports, these were working :
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.squareup.okhttp:okhttp:2.1.0'
Now, if you would like to use recent libraries, change your code snippet to :
#Override
public Point init(Context context, Uri uri) throws Exception {
OkHttp3Downloader downloader = new OkHttp3Downloader(client);
okhttp3.Request request = new Request.Builder().url(uri.toString()).build();
InputStream inputStream = downloader.load(request).body().byteStream();
this.decoder = BitmapRegionDecoder.newInstance(inputStream, false);
return new Point(this.decoder.getWidth(), this.decoder.getHeight());
}
PLEASE REFER TO DAVEMORRISSEY'S (the dev) POST HERE
https://gist.github.com/davemorrissey/e2781ba5b966c9e95539
and read the comments
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_image);
imageView = (ImageView) findViewById(R.id.imageView);
Intent intent = getIntent();
Uri imageUri = intent.getData();
// Picasso.with(this).load(imageUri).into(imageView);
if(imageUri == null){
Log.d(TAG, "Check");
}
//BitmapFactory.Options options = new BitmapFactory.Options();
// options.inSampleSize = 8;
// bm = MediaStore.Images.Media.getBitmap(getContentResolver(),imageUri);
Bitmap bm = null;
try{
InputStream image;
try{
image = getContentResolver().openInputStream(imageUri);
bm = BitmapFactory.decodeStream(image);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
catch (Exception e){
e.printStackTrace();
}
//BitmapFactory.Options options = new BitmapFactory.Options();
// bm = BitmapFactory.decodeFile(file.getAbsolutePath(),options);
if ((bm == null)) {
prints("It doesn't work");
}
//Log.d(TAG,"Going to convert image.");
imageView.setImageBitmap(bm);
I've looked at a bunch of StackOverFlow questions, I've tried them all as you can see in the commented code. I'm trying to get a Bitmap that is unchanged when the photo is taken. The pixel position of the Bitmap is crucial for my goal. The image is high quality and maybe a larger file. My Bitmap is always null, I have made sure my Uri isn't. Any ideas?
I think the code below will help you
private void setImage(String path, CircleImageView img) {
options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.showImageOnLoading(R.drawable.user)
.showImageForEmptyUri(R.drawable.user)
.showImageOnFail(R.drawable.user)
.build();
ImageLoader.getInstance().displayImage(path, img, options, new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
super.onLoadingStarted(imageUri, view);
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
super.onLoadingFailed(imageUri, view, failReason);
}
#Override
public void onLoadingCancelled(String imageUri, View view) {
super.onLoadingCancelled(imageUri, view);
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
}
}, new ImageLoadingProgressListener() {
#Override
public void onProgressUpdate(String s, View view, int i, int i1) {
}
});
}
use universal image loader for SimpleImageLoadingListener()
The file has a too big resolution to make a bitmap out of it. There is not enough memory to construct a bitmap and hence a null is returned.
Try with a very small image file to see.
You can direct get Bitmap from URI if it is from your mobile storage from below code.
public Bitmap getBitmapFromURI(Uri uri){
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getActivity().getContentResolver().query(uri, filePathColumn, null, null, null);
if(cursor!=null){
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
File f_image = new File(cursor.getString(columnIndex));
cursor.close();
BitmapFactory.Options o2 = new BitmapFactory.Options();
return BitmapFactory.decodeFile(f_image.getAbsolutePath(), o2);
}
return null;
}
In case of file is too large to load.. You need to compress image and show. For that you need to use Async Task as well.
I have made one Image compressor task you can use it for large image
public class ConvertBase64Task extends AsyncTask<Void, Bitmap, Bitmap> {
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
private File file;
private int CompressionRatio = 80; //You can change it by what ever ratio you want. in 0 to 100.
private boolean shouldrotate = true;
private ImageCompressiorListner imageCompressiorListner;
public ConvertBase64Task(File file) {
this.file = file;
}
public void setRotation(boolean isRotate) {
shouldrotate = isRotate;
}
public void setCompressionRatio(int Ratio) {
CompressionRatio = Ratio;
}
public void setImageCompressiorListner(ImageCompressiorListner imageCompressiorListner) {
this.imageCompressiorListner = imageCompressiorListner;
}
#Override
protected void onPreExecute(){
}
#Override
protected Bitmap doInBackground(Void... params) {
try {
//***** Fatching file
//*****Code for Orientation
Matrix matrix = new Matrix();
if (shouldrotate) {
ExifInterface exif1 = new ExifInterface(file.getAbsolutePath());
int orientation = exif1.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 1);
Log.d("EXIF", "Exif: " + orientation);
if (orientation == 6) {
matrix.postRotate(90);
} else if (orientation == 3) {
matrix.postRotate(180);
} else if (orientation == 8) {
matrix.postRotate(270);
} else {
matrix.postRotate(0);
}
} else {
matrix.postRotate(0);
}
try {
BitmapFactory.Options option = new BitmapFactory.Options();
option.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getAbsolutePath(), option);
int file_size = Integer.parseInt(String.valueOf(file.length() / 1024));
Log.e("ImageSize", "" + file_size);
int scale = 1;
if (file_size < 512) {
Log.e("image size is good", "image size is less");
} else if (file_size < 1024) {
Log.e("image size is 1 mb", "image size is heavy");
scale = 2;
} else if (file_size < 1536) {
Log.e("image size is 1.5 mb", "image size is heavy");
scale = 2;
} else if (file_size < 2048) {
Log.e("image size is 2 mb", "image size is heavy");
scale = 4;
} else {
Log.e("image size > 2 mb", "image size is heavy");
scale = 4;
}
Log.e("Scale", "Finaly Scaling with " + scale);
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap pickimg = BitmapFactory.decodeFile(file.getAbsolutePath(), o2);
if (pickimg.getWidth() > 1280 || pickimg.getHeight() > 1000) {
int width = pickimg.getWidth();
int height = pickimg.getHeight();
while (width > 1280 || height > 700) {
width = (width * 90) / 100;
height = (height * 90) / 100;
}
pickimg = Bitmap.createScaledBitmap(pickimg, width, height, true);
} else {
pickimg = Bitmap.createBitmap(pickimg, 0, 0, pickimg.getWidth(), pickimg.getHeight(), matrix, true); // rotating bitmap
}
pickimg.compress(Bitmap.CompressFormat.JPEG, CompressionRatio, baos);
return pickimg;
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (result != null) {
if(imageCompressiorListner!=null){
imageCompressiorListner.onImageCompressed(result);
}
} else {
if(imageCompressiorListner!=null){
imageCompressiorListner.onError();
}
}
}
public interface ImageCompressiorListner {
void onImageCompressed(Bitmap bitmap);
void onError();
}
}
You can use this as below
ConvertBase64Task task = new ConvertBase64Task(File Object of Image);
task.setImageCompressiorListner(new ConvertBase64Task.ImageCompressiorListner() {
#Override
public void onImageCompressed(Bitmap bitmap) {
}
#Override
public void onError() {
}
});
task.execute();
Hope this will help you out.
hey guys having a problem after reloading an activity multiple times i get an out of memory exception and crashes out of the app i am using the developer google documentation example to load multiple images from what i see i have to recycle the bitmap once i am done with it but i am a bit unsure where to do this considering i have multiple bitmaps and calling the bitmap from an external class
Here is my load bitmap class
public class bitmapHTTP{
Context ctx;
private LruCache<String, Bitmap> mMemoryCache;
int iv;
public bitmapHTTP(Context c){
ctx = c;
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
#Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than
// number of items.
return bitmap.getByteCount() / 1024;
}
};
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if(getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
public void loadBitmap(String resId, ImageView imageView) {
final String imageKey = String.valueOf(resId);
iv = imageView.getWidth();
Bitmap bitmap = getBitmapFromMemCache(imageKey);
if(bitmap != null) {
imageView.setImageBitmap(bitmap);
}else{
if(cancelPotentialWork(imageKey, imageView)){
Bitmap loading = decodeSampledBitmapFromResource(ctx.getResources(), R.drawable.whiteseetrough, imageView.getWidth(), imageView.getWidth());
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
AsyncDrawable asyncDrawable = new AsyncDrawable(ctx.getResources(), loading, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(resId);
}
}
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private String data = null;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
#Override
protected Bitmap doInBackground(String... params) {
data = params[0];
final BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap;
if(data.equals("null")){
bitmap = decodeSampledBitmapFromResource(ctx.getResources(), R.drawable.whiteseetrough, iv, iv);
addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
return bitmap;
}else{
bitmap = getBitmapFromMemCache(data);
if(bitmap == null){
// Process as normal
try {
URL url = new URL(data);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
options.inSampleSize = calculateInSampleSize(options, iv, iv);
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeStream(input, null, options);
addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
return bitmap;
}catch(IOException e){
e.printStackTrace();
return null;
}
}
}
return bitmap;
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
final BitmapWorkerTask bitmapWorkerTask =
getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
public static boolean cancelPotentialWork(String data, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final String bitmapData = bitmapWorkerTask.data;
// If bitmapData is not yet set or it differs from the new data
if(bitmapData == null || bitmapData != data) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
}
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
}
this is how i call the bitmap to load to an imageView
bitmapHTTP getBitmap = new bitmapHTTP(this);
getBitmap.loadBitmap(imageUrl, 1), imageView1);
getBitmap.loadBitmap(imageUrl, 1), imageView2);
getBitmap.loadBitmap(imageUrl, 1), imageView3);
Thats a lot of code. Quickly I would ask: Are you recycling your bitmaps after not needing them? Bitmaps need to be recycled and RAM released especially when loading them via loops and the like and keeping references to them.
Check your code to make sure you recycling properly. I didn't see anything of the kind (releasing the reference is not enough if you want to do a low of bitmaping).
Also, keep in mind that you need to make sure your bitmaps are loaded in properly in available memory and resized so that they don't kill the memory. I believe you are doing it somewhere in there.
I really don't know what I am doing wrong.
onPostExecute, the I loaded the ImageView with the file I just created from bitmap:
public class ComicFragment extends Fragment
{
private final static String URL1 = "http://192.168.1.143/jerson/sample_comic.jpg";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_comic, parent, false);
ImageView imageView = (ImageView) view.findViewById(R.id.imageview_comic);
Point point = getScreenSize();
new DownloadImageTask(getActivity(), imageView, point.x, point.y).execute(URL1);
//Uri uri = Uri.parse("http://192.168.1.143/jerson/sample_comic.jpg");
//simpleDraweeView.setImageURI(uri);
return view;
}
private Point getScreenSize()
{
Point point = new Point();
WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
display.getSize(point);
return point;
}
private byte [] getBitmapByteArray(Bitmap bitmap)
{
int bytes = bitmap.getByteCount();
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bitmap.copyPixelsToBuffer(buffer);
return buffer.array();
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
}
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// From https://developer.android.com/training/displaying-bitmaps/load-bitmap.html#read-bitmap
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth)
{
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth)
{
inSampleSize *= 2;
}
}
return inSampleSize;
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{
private Context context;
private int viewWidth;
private int viewHeight;
private ImageView canvas;
public DownloadImageTask(Context context, ImageView view, int viewWidth, int viewHeight)
{
this.context = context;
this.viewWidth = viewWidth;
this.viewHeight = viewHeight;
canvas = view;
}
#Override
protected Bitmap doInBackground(String ... urls)
{
String url = urls[0];
Bitmap comicBitmap = null;
FileOutputStream out = null;
File root = Environment.getExternalStorageDirectory();
File directory = new File(root.getAbsolutePath() + "/DCIM/tmpimg/cached/");
directory.mkdirs();
File file = new File(directory, "tmp.png");
try
{
InputStream forGettingSizeOnly = new BufferedInputStream(new URL(url).openStream());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(forGettingSizeOnly, null, options);
int outWidth = options.outWidth;
int outHeight = options.outHeight;
options.inSampleSize = calculateInSampleSize(options, viewWidth, viewHeight);
options.inJustDecodeBounds = false;
// Make this not load another image from network the second time...
InputStream actualImage = new BufferedInputStream(new URL(url).openStream());
Bitmap decodedImage = BitmapFactory.decodeStream(actualImage);
out = new FileOutputStream(file);
comicBitmap = Bitmap.createBitmap(decodedImage, 0, 0, outWidth, 400);
comicBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
Log.i(ComicApplication.TAG, "****File saved at : " + file.getAbsolutePath() + "WxH" + outWidth + " x " + comicBitmap.getHeight());
}
catch(Exception e)
{
e.printStackTrace();
Log.i(ComicApplication.TAG, "ERROR : " + e.getMessage());
}
return comicBitmap;
}
#Override
protected void onPostExecute(Bitmap result)
{
File root = Environment.getExternalStorageDirectory();
File file = new File(root.getAbsolutePath() + "/DCIM/tmpimg/cached/tmp/tmp.png");
Picasso.with(context).load(file).into(canvas);
Log.i(ComicApplication.TAG, "FILE LOADED FROM : " + file.getAbsolutePath());
}
}
}
I am able to see the tmp.png from the phone's image viewer. I am not receiving any exceptions, error, whatsoever from Picasso's end?
Can someone help me out on why is Picasso not loading my image from file?
first, make sure that you are giving Picasso the correct file path,
then you have to add the permission of READ_EXTERNAL_STORAGE in the app Manifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
put this line in the manifest level
I have a code that decodes an image from a filepath, however, it takes up too much space and processing in the main thread. I have no idea how to adapt this into an AsyncTask class.
Bitmap bitmap;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
SetBitmapOptions(bitmapOptions);
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(), bitmapOptions);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byte_arr = stream.toByteArray();
image_str = Base64.encodeToString(byte_arr, Base64.DEFAULT);
viewImage.setImageBitmap(bitmap);
I wanted to use the code found here in Android Developer
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
Code
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
#Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
I have no idea what resId is and how to pass my bitmap variable to it
You can pass parameters through the constructor in the Async_BitmapWorkerTask class. You may want to read up on simpler AsyncTask Examples such as this example.
someMethod() {
Bitmap bitmap;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
SetBitmapOptions(bitmapOptions);
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(), bitmapOptions);
// Run the AsyncTask with the bitMap and imageview as a parameters
new Async_BitmapWorkerTask(bitmap, imageView).execute();
}
class Async_BitmapWorkerTask extends AsyncTask<Integer, Void, String> {
private final Bitmap bitmap;
private final ImageView imageView;
private int data = 0;
// Constructor
public Async_BitmapWorkerTask(Bitmap bitmap, ImageView imageView) {
this.bitmap = bitmap;
this.imageView = imageView;
}
// Compress and Decode image in background.
#Override
protected String doInBackground(Integer... params) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byte_arr = stream.toByteArray();
String image_str = Base64.encodeToString(byte_arr, Base64.DEFAULT);
return image_str;
}
// This method is run on the UI thread
#Override
protected void onPostExecute(String string) {
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitMap);
}
}
}
Use this :
class LoadImage extends AsyncTask<Object, Void, Bitmap>{
private ImageView imv;
private String path;
public LoadImage(ImageView imv) {
this.imv = imv;
this.path = imv.getTag().toString();
}
#Override
protected Bitmap doInBackground(Object... params) {
Bitmap bitmap = null;
File file = new File(
Environment.getExternalStorageDirectory().getAbsolutePath() + path);
if(file.exists()){
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
if (!imv.getTag().toString().equals(path)) {
/* The path is not same. This means that this
image view is handled by some other async task.
We don't do anything and return. */
return;
}
if(result != null && imv != null){
imv.setVisibility(View.VISIBLE);
imv.setImageBitmap(result);
}else{
imv.setVisibility(View.GONE);
}
}
}