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;
}
Related
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 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.
Hi I download images from url & save them in cache. Then load those images from cache into carousel view.
but the problem is when phone resolution(720X1124) is high image size become small.
Here I give the code of images save & show them from cach...
private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(300000000);
conn.setReadTimeout(300000000);
conn.setInstanceFollowRedirects(true);
InputStream inputstream=conn.getInputStream();
OutputStream outputstream = new FileOutputStream(f);
Utils.CopyStream(inputstream, outputstream);
outputstream.close();
conn.disconnect();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
}
public void getDimension(int width,int height){
widthScreen=width;
heightScreen=height;
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
final int IMAGE_MAX_SIZE = 120000000; // 1.2MP
BitmapFactory.Options scaleOptions = new BitmapFactory.Options();
scaleOptions.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,scaleOptions);
stream1.close();
// find the correct scale value as a power of 2.
int scale = 1;
while (scaleOptions.outWidth / scale / 2 >= widthScreen
&& scaleOptions.outHeight / scale / 2 >= heightScreen) {
scale *= 2;
}
Bitmap bitmap = null;
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
scaleOptions = new BitmapFactory.Options();
scaleOptions.inSampleSize = scale;
bitmap = BitmapFactory.decodeStream(stream1, null, scaleOptions);
int width=widthScreen;
int height=heightScreen;
double y=height;
double x=width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) x,
(int) y, true);
bitmap.recycle();
bitmap = scaledBitmap;
System.gc();
} else {
bitmap = BitmapFactory.decodeStream(stream1);
}
if((widthScreen>=450)&& (heightScreen>=750) ) {
sample=1;
}
else{
sample=2;
}
//decode with inSampleSize
BitmapFactory.Options scalOption = new BitmapFactory.Options();
scalOption.inSampleSize=sample;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitMap=BitmapFactory.decodeStream(stream2, null, scalOption);
stream2.close();
return bitMap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
how to increase the image sizes according phone resolution. I have tired more days to overcome this problem. But it doesn't work. So give me right instruction.......
thanks............
You need to define your layout for the different screen sizes / resolutions.
See Supporting Multiple Screens.
try to load images with this image loader library
public 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;
}
put this method in my code and call this method as following way ,
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
Matrix matrix = new Matrix();
// matrix.postScale(scaleWidth, scaleHeight);
matrix.postRotate(45);
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
//calculateInSampleSize1(o, widthScreen,heightScreen);
o2.inSampleSize=calculateInSampleSize(o, widthScreen,heightScreen);;
FileInputStream stream2 = new FileInputStream(f);
o2.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
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;
}
:)