I have the common problem of display a picture in the correct rotation. My images are stored on a server. I call an image and display it in my app. Each image is rotated. So I found a correction with handleSamplingAndRotationBitmap.
public static Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage)
throws IOException {
int MAX_HEIGHT = 1024;
int MAX_WIDTH = 1024;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
BitmapFactory.decodeStream(imageStream, null, options);
imageStream.close();
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
imageStream = context.getContentResolver().openInputStream(selectedImage);
Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);
img = rotateImageIfRequired(img, selectedImage);
return img;
}
But it's impossible for me to send the correct Uri selectedImage.
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon = null;
final String myUrlStr = urldisplay;
URL url;
try {
url = new URL(myUrlStr);
uri = Uri.fromFile(new File(urldisplay));
uri2 = Uri.parse((urldisplay).toString());
mIcon = handleSamplingAndRotationBitmap(getContext(),uri2);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
I have the error
} catch (FileNotFoundException e) {
InputStream in = null;
try {
in = new URL(DataConstantes.lien_URLEtb + "Aucune_photo_etablissement.png").openStream();
} catch (IOException e1) {
flagError = true;
}
mIcon = BitmapFactory.decodeStream(in);
} catch (Exception e) {
flagError=true;
}
java.io.FileNotFoundException:
/http:/$$$$$$$$$$/appli/android_connect/Etablissement/abordage.jpg (No
such file or directory)
Do you know how I can send the correct URI ?
Thanks
Related
I am trying to fetch file from device storage and showing it in image view .
Sometimes it is working perfectly fine, but sometimes not. Although bitmap is there but image view remains black.
Kindly suggest.
storage file Location
file:/storage/emulated/0/Download/Full-hd-nature-wallpapers-free-download2.jpg
method which is returning bitmap
public static Bitmap convertToBitmap(File file) {
URI uri = null;
try {
uri = file.toURI();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap bmp = BitmapFactory.decodeStream(uri.toURL().openStream(), new Rect(), options);
//bmp.recycle();
return bmp;
} catch (Exception e) {
return null;
}//catch
}
setting image
imageViewPatientImage.setImageBitmap(convertToBitmap(new File(mImagePath));
Try this:
Bitmap bitmap = getThumbnail(uri);
showImage.setImageBitmap(bitmap);
Pass Bitmap for Optimization:
public Bitmap getThumbnail(Uri uri) throws FileNotFoundException, IOException{
InputStream input = getContext().getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither=true;//optional
onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1))
return null;
int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;
double ratio = (originalSize > 500) ? (originalSize / 500) : 1.0;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
bitmapOptions.inDither=true;//optional
bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
input = getContext().getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
return bitmap;
}
private static int getPowerOfTwoForSampleRatio(double ratio){
int k = Integer.highestOneBit((int)Math.floor(ratio));
if(k==0) return 1;
else return k;
}
I have tried almost everything mentioned anywhere but still i am unable to get the profile pic of the logged in user in my android app.
Following is the code which I am using :-
new AsyncTask<String, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL(params[0]);
return BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (Exception e) {
Log.d("ERROR", "Unable to get Image");
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if(saveFlag) {
saveImage(bitmap);
}
imageView.setImageBitmap(bitmap);
}
}.execute(url);
Url for the image is :- http://graph.facebook.com/{ID}/picture.
I am able to see the image when I go the url from browser.
I have tried both http and https.
Someone help.
Edit: I dont want to use any other api other than fb or normal android's.
you can use picasso and set image using picasso like this:
URL url = new URL(params[0]);
Picasso.with(context).load(url.toString()).into(imageView);
http://square.github.io/picasso/
OR
call the below method in async task and set the returned bitmap as image.
private Bitmap getImage(String imageUrl, int desiredWidth, int desiredHeight)
{
private Bitmap image = null;
int inSampleSize = 0;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = inSampleSize;
try
{
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
InputStream stream = connection.getInputStream();
image = BitmapFactory.decodeStream(stream, null, options);
int imageWidth = options.outWidth;
int imageHeight = options.outHeight;
if(imageWidth > desiredWidth || imageHeight > desiredHeight)
{
System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight);
inSampleSize = inSampleSize + 2;
getImage(imageUrl);
}
else
{
options.inJustDecodeBounds = false;
connection = (HttpURLConnection)url.openConnection();
stream = connection.getInputStream();
image = BitmapFactory.decodeStream(stream, null, options);
return image;
}
}
catch(Exception e)
{
Log.e("getImage", e.toString());
}
return image;
}
I'm having an issue whereby when I write a bitmap to disk, it gets written to disk, however it gets written as a miniscule image (3kb or less in filesize).
I have checked that the source image is indeed the correct dimensions, however the output image seems shrunk despite configuring the bitmap options to not scale.
#Override
protected Void doInBackground(PPImage... params) {
String filename = "pp_" + position + ".jpg";
File externalStorageDirectory = Environment.getExternalStorageDirectory();
final File destination = new File(externalStorageDirectory, filename);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 16;
opts.inPurgeable = true;
opts.inScaled = false;
decode(opts, Uri.parse(params[0].getUri()), getActivity(), new OnBitmapDecodedListener() {
#Override
public void onDecoded(Bitmap bitmap) {
try {
FileOutputStream out = new FileOutputStream(destination, false);
writeImageToFileTask.this.holder.pathToImage = destination.getAbsolutePath();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), destination.getAbsolutePath(), destination.getName(), destination.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
});
return null;
}
private void decode(BitmapFactory.Options options, Uri mUri, Context mContext, OnBitmapDecodedListener listener) {
try {
InputStream inputStream;
if (mUri.getScheme().startsWith("http") || mUri.getScheme().startsWith("https")) {
inputStream = new URL(mUri.toString()).openStream();
} else {
inputStream = mContext.getContentResolver().openInputStream(mUri);
}
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
listener.onDecoded(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
How do I ensure that the image being written to file is the same dimensions as the original source image?
You have specified sample size in your code, which will result in resizing:
opts.inSampleSize = 16;
Just remove this line, and the dimension of the output image should be the same.
About the usage of inSampleSize, according to official doc:
For example, inSampleSize == 4 returns an image that is 1/4 the
width/height of the original, and 1/16 the number of pixels. Any value
<= 1 is treated the same as 1.
I am working on a code sample where I have to choose an image from gallery the code is working but after selection of image from gallery I get OutOfMemoryError in my OnActivityResult
I am able to get small images but large images are creating problem.
Here is my code:
try{
Uri selectedImageUri = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
bitmap = BitmapFactory.decodeFile(filePath);
_profileImage.setImageBitmap(bitmap);
_profileImage.setScaleType(ScaleType.FIT_XY);
Constant._addPhotoBitmap=bitmap;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Bitmap resizedbitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
resizedbitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte [] _byteArray = baos.toByteArray();
String base64 = Base64.encodeToString(_byteArray,Base64.DEFAULT);
Constant._addPhotoBase64 = base64;
}catch (OutOfMemoryError e) {
e.printStackTrace();
Constant.showAlertDialog(Constant.errorTitle,
"Image size is too large.Please upload small image.",
DriverProfileScreen.this, false);
} catch (Exception e) {
e.printStackTrace();
}
You are deirectly decoding the file based on its uri path..thats why it is throwing exception..before loading image set some options..this will reduce the memory for the image loading..Use this method for loading image whatever size you want..
/**
* returns the thumbnail image bitmap from the given url
*
* #param path
* #param thumbnailSize
* #return
*/
private Bitmap getThumbnailBitmap(final String path, final int thumbnailSize) {
Bitmap bitmap;
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, bounds);
if ((bounds.outWidth == -1) || (bounds.outHeight == -1)) {
bitmap = null;
}
int originalSize = (bounds.outHeight > bounds.outWidth) ? bounds.outHeight
: bounds.outWidth;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = originalSize / thumbnailSize;
bitmap = BitmapFactory.decodeFile(path, opts);
return bitmap;
}
In Android Developer document there is Topic called
Displaying Bitmaps Efficiently
So please go through it.
http://developer.android.com/training/displaying-bitmaps/index.html
Hope this will help you.
Generally android device heap size is only 16MB (varies from device/OS see post Heap Sizes), if you are loading the images and it crosses the size of 16MB , it will throw out of memory exception, instead of using the Bitmap for , loading images from SD card or from resources or even from network try to using getImageUri , loading bitmap require more memory , or you can set bitmap to null if your work done with that bitmap.
So,You need to downscale you image using below code:
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
Scale the bitmap first , then load it. It will solve the problem.
You can use the following method to do that.
private Bitmap getScaledBitmap(Uri uri){
Bitmap thumb = null ;
try {
ContentResolver cr = getContentResolver();
InputStream in = cr.openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize=8;
thumb = BitmapFactory.decodeStream(in,null,options);
} catch (FileNotFoundException e) {
Toast.makeText(PhotoTake.this , "File not found" , Toast.LENGTH_SHORT).show();
}
return thumb ;
}
Hope it helps.
try this code:
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.ActivityManager;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
public class UserImageLoaderWithCache implements ComponentCallbacks {
private KCLruCache cache;
public UserImageLoaderWithCache(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass() * 1024 * 1024;
cache = new KCLruCache(memoryClass);
}
public void display(String url, ImageView imageview, int defaultresource) {
imageview.setImageResource(defaultresource);
Bitmap image = cache.get(url);
if (image != null) {
imageview.setImageBitmap(image);
}
else {
new SetImageTask(imageview).execute(url);
}
}
private class KCLruCache extends LruCache<String, Bitmap> {
public KCLruCache(int maxSize) {
super(maxSize);
}
}
private class SetImageTask extends AsyncTask<String, Void, Integer> {
private ImageView imageview;
private Bitmap bmp;
public SetImageTask(ImageView imageview) {
this.imageview = imageview;
}
#Override
protected Integer doInBackground(String... params) {
String url = params[0];
try {
bmp = getBitmapFromURL(url);
if (bmp != null) {
cache.put(url, bmp);
} else {
return 0;
}
} catch (Exception e) {
e.printStackTrace();
return 0;
} catch (OutOfMemoryError o) {
o.printStackTrace();
return 0;
}
return 1;
}
#Override
protected void onPostExecute(Integer result) {
if (result == 1) {
imageview.setImageBitmap(bmp);
}
super.onPostExecute(result);
}
private 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 (Exception e) {
e.printStackTrace();
return null;
}catch (OutOfMemoryError o) {
o.printStackTrace();
return null;
}
}
}
public void onLowMemory() {
}
/*public void onTrimMemory(int level) {
if (level >= TRIM_MEMORY_MODERATE) {
cache.evictAll();
}
else if (level >= TRIM_MEMORY_BACKGROUND) {
cache.trimToSize(cache.size() / 2);
}
}*/
public void onConfigurationChanged(Configuration arg0) {
// TODO Auto-generated method stub
}
}
I have used below code and used bitmap to store resized Image in local storage and It worked like charm
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap b = BitmapFactory.decodeFile(path, options);
here path is image Uri path in String
actually i'm opening png files from assets folder with this code:
public static Bitmap loadImage( String imageName ){
if( imageName.charAt(0) == '/' ) {
imageName = imageName.substring(1);
}
imageName = imageName + ".png";
Bitmap image = BitmapFactory.decodeStream(getResourceAsStream(imageName));
return image;
}
public static InputStream getResourceAsStream( String resourceName ) {
if( resourceName.charAt(0) == '/' ) {
resourceName = resourceName.substring(1);
}
InputStream is = null;
try {
is = context.getAssets().open( resourceName );
} catch (IOException e) {e.printStackTrace();}
return is;
}
This code opens the bitmaps with full cuality and it takes a lot of time to open it. I will try to use RGB_565 to speed up the opening of the bitmap.
What should i change into my code to open the bitmap with RGB_565? As you can see, i dont know the width and the height of the image.
Also any sugerences to speed up the opening of the bitmap will be welcome
Thanks
Add BitmapFactory.Options to to decodeStream() call:
BitmapFactory.Options bitmapLoadingOptions = new BitmapFactory.Options();
bitmapLoadingOptions.inPreferredConfig = Bitmap.Config.RGB_565;
BitmapFactory.decodeStream(instream,null,bitmapLoadingOptions);
As for how to speed up loading the image? Not sure what else you can do except maybe reduce the size of the image if that's possible.
This code worked for me
AssetManager assetManager = getAssets();
InputStream istr = null;
try {
istr = assetManager.open(strName);
} catch (IOException e) {
e.printStackTrace();
}
BitmapFactory.Options bitmapLoadingOptions = new BitmapFactory.Options();
bitmapLoadingOptions.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(istr,null,bitmapLoadingOptions);
return bitmap;