Android Download of bitmap returns null sometimes - android

I am using the code below in asyn task to download a bitmap to be added to my custom class. however sometimes it return nulls with no IOException or any exception. i am not very sure what can be done
public Bitmap downloadFile(String fileUrl){
URL myFileUrl =null;
try {
myFileUrl= new URL(fileUrl);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
conn.setDoInput(true);
//conn.setReadTimeout(500000000);
conn.connect();
InputStream is = conn.getInputStream();
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, o);
is.close();
conn.disconnect();
int scale = 1;
int IMAGE_MAX_SIZE=400;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
conn= (HttpURLConnection)myFileUrl.openConnection();
conn.setDoInput(true);
//conn.setReadTimeout(500000000);
conn.connect();
is = conn.getInputStream();
Bitmap b = BitmapFactory.decodeStream(is, null, o2);
if (b==null)
Log.e(Config.log_id, " Download image failed");
return b;
}
catch (IOException e) {
Log.e(Config.log_id, " Download image failed"+e.getMessage());
e.printStackTrace();
}
return null;
}

I have run into this as well when using unbuffered variants of
stream readers when getting from urls.
The simple solution that worked for me was to use a BufferedHttpEntity to get the image data.
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
public static Bitmap decodeFromUrl(HttpClient client, URL url, Config bitmapCOnfig)
{
HttpResponse response=null;
Bitmap b=null;
InputStream instream=null;
BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
decodeOptions.inPreferredConfig = bitmapCOnfig;
try
{
HttpGet request = new HttpGet(url.toURI());
response = client.execute(request);
if (response.getStatusLine().getStatusCode() != 200)
{
MyLogger.w("Bad response on " + url.toString());
MyLogger.w ("http response: " + response.getStatusLine().toString());
return null;
}
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(response.getEntity());
instream = bufHttpEntity.getContent();
return BitmapFactory.decodeStream(instream, null, decodeOptions);
}
catch (Exception ex)
{
MyLogger.e("error decoding bitmap from:" + url, ex);
if (response != null)
{
MyLogger.e("http status: " + response.getStatusLine().getStatusCode());
}
return null;
}
finally
{
if (instream != null)
{
try {
instream.close();
} catch (IOException e) {
MyLogger.e("error closing stream", e);
}
}
}
}

Related

Get bitmap from input stream and resize

I want to get bitmap from a inputstream, then re-size it. But I am getting below error.
If I return without re-sizing, it works fine.
Can anybody help please?
LOGCAT:
01-07 01:38:33.412: D/skia(1307): --- SkImageDecoder::Factory returned null
CODE:
private Bitmap getBitmap(String url)
{
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setDoInput(true);
conn.setInstanceFollowRedirects(true);
conn.connect();
InputStream is=conn.getInputStream();
//return BitmapFactory.decodeStream(is); // THIS WORKS FINE
bitmap = decodeFile(is);
is.close();
return bitmap;
} catch (Exception ex){
return null;
}
}
private Bitmap decodeFile(InputStream istream){
BufferedInputStream is = new BufferedInputStream(istream);
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is,null,o);
final int REQUIRED_SIZE=60;
int height_tmp=o.outHeight;
int scale=1;
while(true){
if(height_tmp/2<REQUIRED_SIZE)
break;
height_tmp/=2;
scale*=2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
Log.d("insample", "aa: "+scale);
return BitmapFactory.decodeStream(is, null, o2);
} catch (Exception e) {
Log.d("aaa","aa: "+e);
} finally{
try {
is.close();
} catch( IOException ignored ) {}
}
return null;
}
at
iv.setImageResource(resId);
resId is invalid value...
change it to
iv.setImageResource(R.drawable.ic_launcher);
and test the code

Copy inputStream to file and read from it

I want to copy the content of an input-stream which is actually a bitmap to a file-output-stream. After that I want to pass the content of the file-output-stream to BitmapFactory.decodeStream. The result is that I am getting damaged images! my code for these things is the below.
private void copyInStreamToFile(InputStream is) {
byte buf[] = new byte[1024];
int len;
FileOutputStream fos;
try {
fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
while ((len = is.read(buf)) > 0)
fos.write(buf, 0, len);
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static FileInputStream getStream() throws FileNotFoundException {
return context.openFileInput(FILENAME);
}
I am calling this inside the download method
Bitmap downloadBitmap(String url) {
final int IO_BUFFER_SIZE = 4 * 1024;
// AndroidHttpClient is not allowed to be used from the main thread
final HttpClient client = AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode
+ " while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
copyInStreamToFile(new FlushedInputStream(inputStream));
DeviceProperties device = new DeviceProperties(activity);
return decodeBitampFromResource(device.getDeviceHeight(),
device.getDeviceWidth());
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
and the last method which makes the decoding is this:
public static Bitmap decodeBitampFromResource(int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
FileInputStream fis;
InputStream is;
Bitmap bitmap = null;
// kanonika tha vriskei to megethos tis photo alla kapoio problima
// iparxei me ton sixronismo
try {
fis = getStream();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(fis, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
fis.close();
fis = getStream();
bitmap = BitmapFactory.decodeStream(fis, null, options);
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bitmap;
}
Do I have to clear the content of the file-output-stream? As I know from android developers openFileOutput opens the file and override it's content or creates it if it doesn't exist.

How to receive a byte array and convert it to image in Android?

I have used:
InputStream in;
Bitmap bmp=BitmapFactory.decodeStream(in);
but the process waits for a long time and nothing happens. On the server side, i have the image converted into byte[].
I think this piece of code will be useful for you:
public Bitmap DownloadImage(String url)
{
HttpClient client = new DefaultHttpClient();
HttpResponse httpResponse;
Bitmap bmp = null;
try{
httpResponse = client.execute(new HttpGet(url));
responseCode = httpResponse.getStatusLine().getStatusCode();
HttpEntity entity = httpResponse.getEntity();
if (entity != null)
{
InputStream in = entity.getContent();
bmp = BitmapFactory.decodeStream(in);
in.close();
}
} catch (ClientProtocolException e) {
client.getConnectionManager().shutdown();
e.printStackTrace();
} catch (IOException e) {
client.getConnectionManager().shutdown();
e.printStackTrace();
}
return bmp;
}
Try this way to convert to bitmap.
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn =
(HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
InputStream is;
OutputStream os = new FileOutputStream(f);
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
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;
}

How can I resize the image that was retrieved via URL and save it?

I am getting an image via URL from the Internet and trying to resize (to a smaller size) before saving it. I managed to save it, but I'm unable to resize it. How could I do that? Here is the code:
URL url = new URL(LogoURL);
InputStream input = url.openStream();
try {
OutputStream output = new FileOutputStream("data/data/com.android.mylogo/logo.jpg");
try {
//byte[] buffer = new byte[aReasonableSize];
int bytesRead = 0;
System.out.println("Buffer Length is \t:-" + buffer.length);
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
System.out.println("inside while");
output.write(buffer, 0, bytesRead);
}
} finally {
output.close();
System.out.println("saved image");
}
} finally {
input.close();
}
If you want to downscale the image to particular dimensions, you can use the following code:
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(LogoURL);
try {
HttpResponse response = client.execute(request);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w(LOG_TAG, "Error " + statusCode + " while retrieving bitmap from " + url);
return null;
}
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream is = null;
BufferedInputStream bis = null;
try {
is = url.openStream();
bis = new BufferedInputStream(is);
int sampleSize = 1;
bis.mark(Integer.MAX_VALUE);
Options bounds = new Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeStream(bis, null, bounds);
if (bounds.outWidth != -1) {
int width = bounds.outWidth;
int height = bounds.outHeight;
boolean withinBounds = width <= YOUR_DESIRED_WIDTH && height <= YOUR_DESIRED_HEIGHT;
int newWidth = width;
int newHeight = height;
while (!withinBounds) {
newWidth /= 2;
newHeight /= 2;
sampleSize *= 2;
withinBounds = newWidth <= YOUR_DESIRED_WIDTH && newHeight <= YOUR_DESIRED_HEIGHT;
}
} else {
Log.w(LOG_TAG, "Can't open bitmap at " + url);
return null;
}
try {
bis.reset();
} catch (IOException e) {
if(is != null){
is.close();
}
if(bis != null){
bis.close();
}
if(!entity.isRepeatable()){
entity.consumeContent();
response = client.execute(request);
entity = response.getEntity();
}
is = entity.getContent();
bis = new BufferedInputStream(is);
}
Options opts = new Options();
opts.inSampleSize = sampleSize;
Bitmap bm = BitmapFactory.decodeStream(bis, null, opts);
return bm;
} finally {
if (is != null) {
is.close();
}
if (bis != null) {
bis.close();
}
entity.consumeContent();
}
}
} catch (IOException e) {
request.abort();
Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
} catch (IllegalStateException e) {
request.abort();
Log.w(LOG_TAG, "Incorrect URL: " + url);
} catch (Exception e) {
request.abort();
Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
}
When you open the image with Options bounds = new Options(); bounds.inJustDecodeBounds = true;, then the image data won't be downloaded, only the size of the image. I use this size to calculate the new scale ratio to get the desired width and height.
With the option Options opts = new Options(); opts.inSampleSize = sampleSize; the BitmapFactory will download an already resized image. You save memory, and bandwidth this way.
Note, that the sampleSize values should be powers of 2. It works with different numbers as well, but this is much more efficient.
JPGs are compressed anyway, so there's no need to try to compress them any further.
In general, to compress something, have a look at the classes of java.util.zip package.

Android : Big error while downloading images

I have tried three ways of downloading images. All suggest by members of Stackoverflow .
All the three methods fail to download all the images from the server. Few are downloaded and few are not.
I noticed a thing that each of the method fail to download image from particular position.
That is method 3 always fails to download the first three images. I changed the images but even then , the first three images are not downloaded.
Method 1:
public Bitmap downloadFromUrl( String imageurl )
{
Bitmap bm=null;
String imageUrl = imageurl;
try {
URL url = new URL(imageUrl); //you can write here any link
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
bm= BitmapFactory.decodeByteArray(baf.toByteArray(), 0, baf.toByteArray().length);
} catch (IOException e) {
Log.d("ImageManager", "Error: " + e);
}
return bm;
}
Here the error i get for missed images is :SKIimagedecoder , the factory returned null.
Method: 2
public static Bitmap loadBitmap(String url)
{
Bitmap bitmap = null;
InputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new URL(url).openStream(), 4*1024);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, 4 * 1024);
int byte_;
while ((byte_ = in.read()) != -1)
out.write(byte_);
out.flush();
final byte[] data = dataStream.toByteArray();
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 1;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,options);
} catch (IOException e) {
System.out.println(e);
Log.e("","Could not load Bitmap from: " + url);
} finally {
try{
in.close();
out.close();
}catch( IOException e )
{
System.out.println(e);
}
}
return bitmap;
}
The error i get here is same as above.
Method 3:
private Bitmap downloadFile(String fileUrl){
URL bitmapUrl =null;
Bitmap bmImg = null;
try {
bitmapUrl= new URL(fileUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
HttpGet httpRequest = null;
try {
httpRequest = new HttpGet(bitmapUrl.toURI());
} catch (URISyntaxException e) {
e.printStackTrace();
}
try {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient
.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream instream = bufHttpEntity.getContent();
bmImg = BitmapFactory.decodeStream(instream);
} catch (Exception e) {
System.out.println(e);
}
return bmImg;
}
The error i get here is : org.apache.http.NoHttpResponseException: The target server failed to respond.
please help. It is the only thing stopping me from completing the project.
Take a look at this.. Clearly explained about image download from the Server..Image from Server....
I'm assuming you are downloading the images to display rather than just save on the device. If this is the case, I recommend looking into using Droid-Fu, more specifically WebImageView. You can just pass the URL to the WebImageView and it will load the image as it can, which will avoid having an image fail to load because of the connection timing out, which I'm guessing is the problem you are having.
In XML:
<com.github.droidfu.widgets.WebImageView
android:id="#+id/image"
android:layout_width="70dip"
android:layout_height="70dip"
droidfu:autoLoad="true"
droidfu:progressDrawable="..."
/>
In Code:
WebImageView image = (WebImageView) convertView.findViewById(R.id.image);
image.setImageUrl(image_url);
image.loadImage();
It's possible that your creation of bitmaps takes time and therefore the connection times out. You could possibly get references to all the inputstreams and then download and create. This is a rough-cut answer, but if the reasoning is right, you can improve on it:
public Bitmap[] downloadFromUrl(String[] imageUrls)
{
Bitmap[] bm = new Bitmap[imageUrls.length];
BufferedInputStream[] bis = new BufferedInputStream[imageUrls.length];
for (int i = 0; i < imageUrls.length; i++)
{
try
{
URL url = new URL(imageUrls[i]); // you can write here any link
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
bis[i] = new BufferedInputStream(is);
}
catch (IOException e)
{
e.printStackTrace();
}
}
for (int i = 0; i < bis.length; i++)
{
try
{
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis[i].read()) != -1)
{
baf.append((byte) current);
}
bm[i] = BitmapFactory.decodeByteArray(baf.toByteArray(), 0, baf.toByteArray().length);
}
catch (IOException e)
{
e.printStackTrace();
}
}
return bm;
}

Categories

Resources