I want load huge image from url and show on my device. I read this post for doing this.
In that example they use native drawable but I want get image from server.
I am using this code
private void getBitmap(ImageView imageView,final String url){
mBitmapOptions = new BitmapFactory.Options();
mBitmapOptions.inJustDecodeBounds = true;
URL mUrl = null;
InputStream is= null;
try {
mUrl = new URL(url);
is = mUrl.openStream();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// BitmapFactory.decodeStream(is,null,mBitmapOptions);
mCurrentBitmap = Bitmap.createBitmap(mBitmapOptions.outWidth,
mBitmapOptions.outHeight, Bitmap.Config.ARGB_8888);
mBitmapOptions.inJustDecodeBounds = false;
mBitmapOptions.inBitmap = mCurrentBitmap;
mBitmapOptions.inSampleSize = 1;
BitmapFactory.decodeStream(is,null,mBitmapOptions);
imageView.setImageBitmap(mCurrentBitmap);
// Bitmap croppedBitmap=Bitmap.createBitmap(Bitmap.createBitmap(mCurrentBitmap, 0, mCurrentBitmap.getHeight()/2, mCurrentBitmap.getWidth(), mCurrentBitmap.getHeight()/2));
// imageView.setImageBitmap(croppedBitmap);
}
I want here get image from url and resize it but I have an exception.
java.lang.IllegalArgumentException: width and height must be > 0
What I did wrong here? or could you suggest me better answer?
I would use Picasso, then what you want to achieve is as simple as this:
Picasso.with(context).load(url).resize(50, 50).into(imageView)
http://square.github.io/picasso/
You get the exception because of:
// BitmapFactory.decodeStream(is,null,mBitmapOptions);
There are no mBitmapOptions set when you try to call:
mCurrentBitmap = Bitmap.createBitmap(mBitmapOptions.outWidth, mBitmapOptions.outHeight, Bitmap.Config.ARGB_8888);
Have a look at the answer in this question to further optimize your code: Getting the size of an image inputstream
I developped a solution based on http://developer.android.com/training/displaying-bitmaps/load-bitmap.html tutorial. Here is my code. The tricky part consist of using a byte array to store image data (because unfortunatly markSupported() is not available for connection.getInputStream()).
public static Bitmap getBitmapFromURL(final String imageUrl, final Options options, int reqWidth, int reqHeight) {
try {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
final InputStream input = connection.getInputStream();
// using byte array to prevent open 2 times a stream
final BufferedInputStream bis = new BufferedInputStream(input, 4*1024);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte)current);
}
bis.close();
byte[] imageData = baf.toByteArray();
if(options != null){
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options optionsSize = new BitmapFactory.Options();
optionsSize.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(imageData, 0, imageData.length, optionsSize);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(optionsSize, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
optionsSize.inJustDecodeBounds = false;
}
Bitmap myBitmap = null;
if(options == null){
myBitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
}
else{
myBitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
}
// close the stream;
input.close();
return myBitmap;
} catch (Exception e) {
return null;
}
}
private 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;
}
Hope it will helps you.
Related
public Bitmap getBitmapFromURL(String imageUrl) {
try {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
Bitmap imageBitmap = BitmapFactory.decodeStream(inputStream);
return imageBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
I use this function to get image from url as a bitmap. For a large image bitmap return null. How can ı solve this?
Code modified. See if this works
If the bitmap is null, this code will replace it with another sample bitmap.
public Bitmap getBitmapFromURL(String imageUrl) {
try {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
Bitmap imageBitmap = BitmapFactory.decodeStream(inputStream);
if(bitmap == null){
imageBitmap =
BitmapFactory.decodeResource(context.getResources(),R.drawable.your_sample_image);
return imageBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
Try this:
private Bitmap getBitmap(String image_link)
{
URL website;
try {
website = new URL(image_link);
HttpURLConnection connection = (HttpURLConnection) website.openConnection();
InputStream is = connection.getInputStream();
if(req_width == 0)
{
return BitmapFactory.decodeStream(is);
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, options);
is.close();
connection = (HttpURLConnection) website.openConnection();
is = connection.getInputStream();
options.inSampleSize = calculateInSampleSize(options, req_width, req_height);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(is, null , options);
} catch (Exception e) {
return null;
}
}
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;
}
I found a lot of documentation on how to load large Bitmaps and avoid outofmemory exception. but the problem is that I have to take the image from my MediaStore.Images.media so the classical
decodeFile(path,options) indicated in the google documentation does not work to me
As you can see below I decommented the line // Bitmap photo= Mediastore.Images, that is the one that triggers the out of memory. on the other side adding
the line Bitmap bm=BitmapFactory.decodeFile(selectedImageToUri,options) returns null, although the compiler can see both the path in selectedImageToUri (that indicates the content provider where the pics are) than the options value, that I set to 8, because I want to subscale all the images
My question is how can I insert in bm the bitmap that is referring to the image selected by the user in the gallery. in the line BitMap photo does not return null and work really well, but I decommented because after I change a couple of images gives me outofmemory exception.
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable final Bundle savedInstanceState) {
if (flagVariable) {
if (selectedImageToUri != null) {
// BitMap photo = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), Uri.parse(selectedImageToUri));
final BitmapFactory.Options options= new BitmapFactory.Options();
options.inSampleSize=8;
Bitmap bm = BitmapFactory.decodeFile(selectedImageToUri, options);
pic = new BitmapDrawable(bm);
getActivity().getWindow().setBackgroundDrawable(pic);
} else {
getDefaultImageBackground(inflater, container);
}
hiddenList = inflater.inflate(R.layout.fragment_as_list_layout_temp, container, false);
} else {
getDefaultImageBackground(inflater, container);
}
listView = (ListView) hiddenList.findViewById(R.id.list_hidden);
MediaStore.getBitmap is just a simple convienence method, it looks like this:
public static final Bitmap getBitmap(ContentResolver cr, Uri url)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(input);
input.close();
return bitmap;
}
You can create your own method based on this that takes the options and calls a different overload on BitmapFactory:
public static final Bitmap getBitmap(ContentResolver cr,
Uri url,
BitmapFactory.Options options)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, options);
input.close();
return bitmap;
}
Usage:
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bm = getBitmap(getActivity().getContentResolver(),
Uri.parse(selectedImageToUri),
options);
I spent a lot of time on this problem, but no one will give me exact answer and finally i solved it. First create method and provide Image URI as argument, and this will return bitmap basically here i calculated image size on bases of, we can manage memory as well as image and get exact image in bitmap form.
you can even display 5000×8000 and 12MiB picture without any error code is tested just copy paste in your class and enjoy.
Use
Bitmap mBitmap = getPhoto(MYIMAGEURI);
Provide URI to method and get Bitmap
Bitmap getPhoto(Uri selectedImage) {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Bitmap photoBitmap = null;
InputStream inputStream = null;
try {
inputStream = getContentResolver().openInputStream(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, bitmapOptions);
int imageWidth = bitmapOptions.outWidth;
int imageHeight = bitmapOptions.outHeight;
#SuppressWarnings("unused")
InputStream is = null;
try {
is = getContentResolver().openInputStream(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
float scale = 1.0f;
if (imageWidth < imageHeight) {
if (imageHeight > width * 1.0f) {
scale = width * 1.0f / (imageHeight * 1.0f);
}
} else {
if (imageWidth > width * 1.0f) {
scale = width * 1.0f / (imageWidth * 1.0f);
}
}
photoBitmap = decodeSampledBitmapFromResource(this,
selectedImage, (int) (imageWidth * scale),
(int) (imageHeight * scale));
return photoBitmap;
}
Decode Bitmap Sample using image size
public static Bitmap decodeSampledBitmapFromResource(Context context,
Uri uri, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream is = null;
try {
is = context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
BitmapFactory.decodeStream(is, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode editBitmap with inSampleSize set
options.inJustDecodeBounds = false;
InputStream inputs = null;
try {
inputs = context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return BitmapFactory.decodeStream(inputs, null, options);
}
Calculate Sample Size
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) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = Math.min(heightRatio, widthRatio);
// inSampleSize = heightRatio < widthRatio ? heightRatio :
// widthRatio;
}
return inSampleSize;
}
Or may be possible to solved using one line of code in manifiest.xml
is in application tag use this
android:largeHeap="true"
I have these two methods, downloadBitmapImage and readBitmapImage. The first pulls an image from a URL, stores it locally on an SDCard and the second returns the image as a Bitmap to be used later. Why does the bitmap continue to be returned as null?
void downloadBitmapImage() {
InputStream input;
try {
URL url = new URL (strURL);
input = url.openStream();
byte[] buffer = new byte[1500];
OutputStream output = new FileOutputStream ("/sdcard/"+pos+".png");
try {
int bytesRead = 0;
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
output.write(buffer, 0, bytesRead);
}
}
finally {
output.close();
buffer = null;
}
}
catch(Exception e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
Bitmap readBitmapImage() {
BitmapFactory.Options bOptions = new BitmapFactory.Options();
bOptions.inTempStorage = new byte[16*1024];
File file = null;
FileOutputStream fos = null;
try
{
file = new File(getExternalFilesDir(null), "/sdcard/"+pos+".png");
fos = new FileOutputStream(file);
}
catch(FileNotFoundException e)
{
e.getMessage();
}
String imageInSD = file.getAbsolutePath().toString();
bitmap = BitmapFactory.decodeFile(imageInSD,bOptions);
return bitmap;
}
I have used following methods in my code.
/**
* Download image from server url and return bitmap
*
* #param stringUrl Imaage download url
* #return Bitmap receieved from server
*/
public static Bitmap downloadImage(String stringUrl) {
URL url;
Bitmap bm = null;
try {
url = new URL(stringUrl);
URLConnection ucon = url.openConnection();
InputStream is;
if (ucon instanceof HttpURLConnection) {
HttpURLConnection httpConn = (HttpURLConnection) ucon;
int statusCode = httpConn.getResponseCode();
if (statusCode == 200) {
is = httpConn.getInputStream();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
BufferedInputStream bis = new BufferedInputStream(is, 8192);
ByteArrayBuffer baf = new ByteArrayBuffer(1024);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
byte[] rawImage = baf.toByteArray();
bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
bis.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return bm;
}
/**
* Decode bitmap from internal storage having specific width and height
*
* #param filePath path of image to be decode
* #param reqWidth width of bitmap
* #param reqHeight hieght of bitmap
* #return bitmap from given path
*/
public static Bitmap decodeScaledBitmapFromSdCard(String filePath, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
/**
* Reduce quality of bitmap for smaller images
*
* #param options various options for BitmapFactory
* #param reqWidth width of bitmap
* #param reqHeight hight of bitmap
* #return lower resolution bitmap
*/
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
Use this method according to your need.
I hope it helps!
I am trying to reduce the size of bitmap from a url. I saw many posts, but all were about sampling a local file. I want to sample the image at url. Here is my code:
public Bitmap getScaledFromUrl(String url) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1 / 10;
try {
return BitmapFactory.decodeStream((InputStream) new URL(url)
.getContent());
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
Is this approach correct? I am getting out of memory crashes in my app at this function. Any ideas?
This works. I found it at http://blog.vandzi.com/2013/01/get-scaled-image-from-url-in-android.html . Use the following snippet of code, pass params as you like.
private static Bitmap getScaledBitmapFromUrl(String imageUrl, int requiredWidth, int requiredHeight) throws IOException {
URL url = new URL(imageUrl);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(url.openConnection().getInputStream(), null, options);
options.inSampleSize = calculateInSampleSize(options, requiredWidth, requiredHeight);
options.inJustDecodeBounds = false;
//don't use same inputstream object as in decodestream above. It will not work because
//decode stream edit input stream. So if you create
//InputStream is =url.openConnection().getInputStream(); and you use this in decodeStream
//above and bellow it will not work!
Bitmap bm = BitmapFactory.decodeStream(url.openConnection().getInputStream(), null, options);
return bm;
}
private 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) {
if (width > height) {
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
It's really flexible.. I think you should try it out.
You are using it wrong. You are asking to make the picture 10 times bigger :) You should give the command in normal numbers, not fraction. For example:
final BitmapFactory.Options options2 = new BitmapFactory.Options();
options2.inSampleSize = 8;
b = BitmapFactory.decodeFile(image, options2);
with this configuration you obtain 8 times smaller picture than the original.
UPDATE: To load image from internet add this class to the project and do the following:
ImageLoader loader = new ImageLoader(context);
Bitmap image = loader.getBitmap(URL);
I'm trying to open an image from a specific uri, checking if this image is too big to resize it, and return it as Base64. My problem is the code I have to resize image never resize images (never indicate that the image is too big). I looked for others questions similar this, but I didn't get any answer.
I don't know why always in this two code lines the values are -1:
final int height = options.outHeight; // Always -1 WHY?
final int width = options.outWidth; // Always -1 WHY?
I attach my code:
private class WriteImage extends AsyncTask<Object, Void, String>{
private static Bitmap decodeSampledBitmapFromStream(InputStream is,
int reqWidth,
int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream aux = inputStreamCopy(is);
BitmapFactory.decodeStream(is, null, options); // SkImageDecoder::Factory returned null
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(aux, null, options);
}
private static InputStream inputStreamCopy(InputStream is) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
byte[] buffer = new byte[1024];
try {
while ((len = is.read(buffer)) > -1) baos.write(buffer, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
return new ByteArrayInputStream(baos.toByteArray());
}
private static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight; // Always -1 WHY?
final int width = options.outWidth; // Always -1 WHY?
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height)
inSampleSize = Math.round((float)height / (float)reqHeight);
else
inSampleSize = Math.round((float)width / (float)reqWidth);
// This offers some additional logic in case the image has a strange
// aspect ratio. For example, a panorama may have a much larger
// width than height. In these cases the total pixels might still
// end up being too large to fit comfortably in memory, so we should
// be more aggressive with sample down the image (=larger
// inSampleSize).
final float totalPixels = width * height;
// Anything more than 2x the requested pixels we'll sample down
// further.
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap)
inSampleSize++;
}
for (int i=5; i>0; i--){
if (Math.pow(2, i)<=inSampleSize){
inSampleSize = (int) Math.pow(2, i);
break;
}
}
return inSampleSize;
}
#Override
protected void onPreExecute(){
}
#Override
protected void onProgressUpdate(Void... values){
}
#Override
protected String doInBackground(Object... params) {
try {
InputStream is = ((android.app.Activity) params[1]).getContentResolver().openInputStream((Uri) params[0]);
Bitmap bitmap = decodeSampledBitmapFromStream(is, 300, 300);
int bytes = bitmap.getWidth()*bitmap.getHeight()*4;
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bitmap.copyPixelsToBuffer(buffer);
return Base64.encodeToString(buffer.array(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result){
}
}
The solution was this! Replace the following:
In decodeSampledBitmapFromStream function:
private Bitmap decodeSampledBitmapFromStream(InputStream is,
int reqWidth,
int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream aux = inputStreamCopy(is);
BitmapFactory.decodeStream(aux, null, options); // SkImageDecoder::Factory returned null
try {
aux.reset();
} catch (IOException e) {
e.printStackTrace();
}
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(aux, null, options);
}
And in doInBackground method:
#Override
protected String doInBackground(Object... params) {
try {
InputStream is = ((android.app.Activity) params[1]).getContentResolver().openInputStream((Uri) params[0]);
Bitmap bitmap = decodeSampledBitmapFromStream(is, 300, 300);
System.gc();
int bytes = bitmap.getWidth()*bitmap.getHeight()*2;
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bitmap.copyPixelsToBuffer(buffer);
return Base64.encodeToString(buffer.array(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
:)