Progressive jpeg on Android [duplicate] - android

I've started getting a
DEBUG/skia(xxxx): --- decoder->decode returned false
issue on a few profile images from Facebook that I use in ImageViews. Most work perfectly, but every once in a while I discover one that never works.
I am compiling my application against Android 1.6 for backward compatibility reasons.
I did some digging and discovered a number of threads on the issue. I'm already using the FlushedInputStream discussed here: http://code.google.com/p/android/issues/detail?id=6066
Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is));
imageView.setImageBitmap(b);
Here's an example that's causing me trouble:
http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs269.snc3/23132_639284607_390_q.jpg
Can someone check out the image and help me figure out what's causing the trouble?

Here is a way that worked for me:
HttpGet httpRequest = new HttpGet(url);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient
.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
Drawable d = Drawable.createFromStream(is, "");
//or bitmap
//Bitmap b = BitmapFactory.decodeStream(is);

The source code from this ImageDownloader.java is a good orientation. It has a bug fix which addresses the Issue 6066 by providing a patched FlushedInputStream class.
Another thing which you might want to take care of, is to execute the decoding in the same thread as the HTTP request was executed:
#Override
protected Bitmap doInBackground(String... url) {
// execute HTTP GET request and decode response
...
return bitmap
}
#Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
I had done the decoding in the onPostExecute(), which is executed in the UI thread, and it would not work anymore, giving me the same error.

Here is a way that worked for me:
public static Bitmap loadImageFromUrl(String url) {
URL m;
InputStream i = null;
BufferedInputStream bis = null;
ByteArrayOutputStream out =null;
try {
m = new URL(url);
i = (InputStream) m.getContent();
bis = new BufferedInputStream(i,1024 * 8);
out = new ByteArrayOutputStream();
int len=0;
byte[] buffer = new byte[1024];
while((len = bis.read(buffer)) != -1){
out.write(buffer, 0, len);
}
out.close();
bis.close();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = out.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//Drawable d = Drawable.createFromStream(i, "src");
return bitmap;
}
I loaded the image by multithreading, and then I had to loop reading the inputStream when the thread's time was held by another. Make sure the inputStream is read fully.

Here is what the issue was for me:
From the emulator I would save the jpg file locally (on the emulated sdcard) and then attempt to read it up and display it using decode on the emulator and it worked. Then, as a test, I copied the file (using adb pull) to my development (xp) machine and it would display using 'paint'. Then, from the emulator, I uploaded the file (via http post) to my win2003 server. Using 'paint' it displayed there as well. But when I downloaded it back to the emulator (via http get), it failed during the decode.
Then I noticed that the file uploaded to the win2003 server was two bytes smaller than the original. Not totally sure how that happened because I've been using the same upload logic for years and never noticed the issue before. As a test, I simply appended two more random bytes during the upload so the file size was exactly the same. Then, when downloaded back to the emulator, it decoded and displayed properly.
Just as a check, I appended two random bytes over on my xcode projects and then those jpg files also displayed on the android emulator as well.
So, although the files which were two bytes smaller displayed everywhere else, they would not on the emulator. Apparently decode is doing some sort of CRC before it attemps to decode and decides it cannot continue. And hence the error.

Others who are facing issues in Android KitKat 4.4 , following would be helpful
Bitmap b = BitmapFactory.decodeStream(new BufferedInputStream(is));
imageView.setImageBitmap(b);
I was facing this issue in Nexus series After updating to 4.4.

I ran into this issue as well using Xamarin. To fix it I simply used the Universal Image Loader Xamarin Component and it worked like a charm.
Hope this helps!

Related

How to detect if network connection is down while downloading file using InputStream and FileOutputStream in android?

I am downloading a file and then writing it into sdcard using following code:
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
File file = new File(Environment.getExternalStorageDirectory()+"/MyProject/data");
FileOutputStream fos = new FileOutputStream(file);
int inByte;
while((inByte = is.read()) != -1){
fos.write(inByte);
System.out.println("in while loop inByte: "+inByte);
}
fos.close();
is.close();
Everything is working fine. Normally it takes 2 minutes to download file. If i take out network cable during downloading then seems like it stays in while loop forever. That code is in try catch block but i do not get any exception. Is there anyway to get out of that while loop when network cable is unplugged. Thanks in advance.
You should be able to solve this by setting the timeouts on the HttpClient - the socket is staying open in case the server has a delay in the response. You can simply tell it to not wait so long. See the timeout options here:
How to set HttpResponse timeout for Android in Java

Android - Upload coded image (1 - 2 MB) to base64 to the server HTTP POST - JSON

How can I send large image/photo to the server using HTTP POST and JSON? I tried several methods but all methods wasn´t good (OutOfMemory Exceptions etc.).
"Classic" code:
Bitmap image;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
image.recycle();
image = null;
byte[] byteArray = stream.toByteArray();
try {
stream.close();
} catch (IOException e1) {
}
stream = null;
String encoded = Base64.encodeToString(byteArray,
Base64.DEFAULT);
HttpClient httpClient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Globals.URL + "/storageUploadFile");
httppost.setHeader("Token", Globals.Token);
String msg = "";
try {
JSONObject jo = new JSONObject();
jo.put("fileName", fileName);
jo.put("content", encoded);
httppost.setEntity(new StringEntity(jo.toString());
HttpResponse response = httpClient.execute(httppost);
HttpEntity httpentity = response.getEntity();
msg = EntityUtils.toString(httpentity);
//...
In this code I get exception here: httppost.setEntity(new StringEntity(jo.toString());
Image is saved on storage card. What do you recommend to upload the image? Send image chunk by chunk? I rather send it as one "item". I hope 2 MB is not so large. My API has parameter "content" and it´s the image in base64 encoding. Is it good way to transfer image as base64?
If you really need json and if you really need base64, you need to stream it instead of keeping all transformations in memory. If your image is 2Mb, in your method, you use:
2MB for the bytes
4.6MB for the base64 String (java strings are internally represented chars, which are 16bits)
4.6MB for the JSONObject.toString result in the String entity
That's a grand total of more than 11MB for just a simple 2MB image.
First step is to use a Json streaming API (I use Jackson)
Like so:
// The original size prevents automatic resizing which would take twice the memory
ByteArrayOutputStream baos = new ByteArrayOutputStream(byteArray.length * 1.2);
JsonGenerator jo = new JsonFactory().createGenerator(baos);
jo.writeStartObject();
jo.writeStringField("fileName", fileName);
// Jackson takes care of the base64 encoding for us
jo.writeBinaryField("content", byteArray);
jo.writeEndObject();
httppost.setEntity(new ByteArrayEntity(baos.toByteArray());
In this case, we only hold in memory byteArray and baos, with its underlying byte[] for a theoretical total of 2MB + 1.2*2MB = 4.4MB (No string representation is used, only 1 intermediate byte[]). Note that the base64 streaming to the byte[] is done transparently by Jackson.
If you still have memory issues (if you are going to send a 10MB image, for instance), you need to stream the content directly to the connection. For that, you could use HttpUrlConnection and use the connection.getOutputStream() as a parameter to createGenerator.

BitmapFactory.decodeStream not working

I'm having a bit of a problem with decodeStream returning null. It seems to be a fairly common problem around, but it's usually pinned down to one of two problems:
An OutOfMemory exception thrown by attempting to load a large bitmap in it's entirety.
Attempting to use the same input stream twice.
However, I'm not doing either. The code to run it is simply
stream = new java.net.URL(url).openStream();
Bitmap image = BitmapFactory.decodeStream(stream);
stream.close();
with the URL set to here. image is null after this code is complete. This issue's been driving me completely insane - it works fine on PNGs but seems to fall apart under every BMP I can give it, so any help would be appreciated.
Ultimately, the answer was found here, using an InputStream returned by a BufferedHTTPEntity. While it seems needlessly complex, I can only assume that simply getting a stream from the URL object directly doesn't return a stream of the appropriate type, and so it wasn't reading out all the data properly.
Cross-posting the code in case the question is erased:
private static InputStream fetch(String address) throws MalformedURLException,IOException {
HttpGet httpRequest = new HttpGet(URI.create(address) );
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream instream = bufHttpEntity.getContent();
return instream;
}

BitmapFactory : unable to decode Stream

I'm pretty new to Android Development and spent all day looking into issues with my ListAdapter, but couldn't find any answers that helped me solve my problem.
I Have a JSON NewsString parsed from an URL and need to load the Thumbnail into the ListView.
I tried to Load it via Imageloader (https://github.com/novoda/ImageLoader#directloader-utility) and then convert the Bitmap to a Drawable so I can use it in my ListView (Did that before).
I Have the permissions in the Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
And the JsonObject is parsed in an AsyncTask where I try to load the image from Url.
try {
String url = e.getString("imageThumb");
Bitmap bmp = new DirectLoader().download(url);
Drawable d = new BitmapDrawable(null,bmp);
Log.d("getBitmap", d.toString());
row.put("thumb", d);
}catch (Exception e5) {
Log.e("IMG", "Failed to load Thumbnail From URL: "+e5.toString());
Drawable d = MainActivity.hweb_icon;
row.put("thumb", d);
}
but I always get the Same Error Message:
I tried several tutorials and other stuff, but it never worked out for me.
The URL is correct and does not need any encoding.
My previous approach looked like this :
try {
String url = e.getString("imageThumb");
InputStream in = new java.net.URL(url).openStream();
Bitmap bmp = BitmapFactory.decodeStream(in);
Drawable d = new BitmapDrawable(null,bmp);
row.put("thumb", d);
}catch (Exception e5) {
// handle it
Log.e("IMG", "Failed to load Thumbnail From URL : "+e5.toString());
}
Sorry if this question was already answered, but I found many solutions and tried them, but none of them helped me out.
Thx
pwittke
EDIT:
I created a new Testproject and the code below worked fine, so I started to deactivate every part that uses drawables somehow and turned out, that the SimpleAdapter cant load images that way... It can only load images from the resurces and not from an url... thx for your script britzl, it works fine, now I need to find a way to change my adapter for the images...
There are many ways to load a Bitmap from a URL. If you want to roll your own you can try something like:
public Bitmap loadImage(String url) {
DefaultHttpClient client = new DefaultHttpClient();
Bitmap bitmap = null;
try {
HttpResponse response = client.execute(new HttpGet(url));
HttpEntity entity = response.getEntity();
if(entity != null) {
InputStream in = entity.getContent();
bitmap = BitmapFactory.decodeStream(in);
}
}
catch (Exception e) {
}
return bitmap;
}
There's some things to consider, for instance if you run into Skia decoder errors you may have to wrap the stream. Read more here.
I would however recommend that you take a look at existing libraries. The up and coming Picasso library from Square is probably your best bet. Example:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

Android decoder->decode returned false for Bitmap download

I've started getting a
DEBUG/skia(xxxx): --- decoder->decode returned false
issue on a few profile images from Facebook that I use in ImageViews. Most work perfectly, but every once in a while I discover one that never works.
I am compiling my application against Android 1.6 for backward compatibility reasons.
I did some digging and discovered a number of threads on the issue. I'm already using the FlushedInputStream discussed here: http://code.google.com/p/android/issues/detail?id=6066
Bitmap b = BitmapFactory.decodeStream(new FlushedInputStream(is));
imageView.setImageBitmap(b);
Here's an example that's causing me trouble:
http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs269.snc3/23132_639284607_390_q.jpg
Can someone check out the image and help me figure out what's causing the trouble?
Here is a way that worked for me:
HttpGet httpRequest = new HttpGet(url);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient
.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
Drawable d = Drawable.createFromStream(is, "");
//or bitmap
//Bitmap b = BitmapFactory.decodeStream(is);
The source code from this ImageDownloader.java is a good orientation. It has a bug fix which addresses the Issue 6066 by providing a patched FlushedInputStream class.
Another thing which you might want to take care of, is to execute the decoding in the same thread as the HTTP request was executed:
#Override
protected Bitmap doInBackground(String... url) {
// execute HTTP GET request and decode response
...
return bitmap
}
#Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
I had done the decoding in the onPostExecute(), which is executed in the UI thread, and it would not work anymore, giving me the same error.
Here is a way that worked for me:
public static Bitmap loadImageFromUrl(String url) {
URL m;
InputStream i = null;
BufferedInputStream bis = null;
ByteArrayOutputStream out =null;
try {
m = new URL(url);
i = (InputStream) m.getContent();
bis = new BufferedInputStream(i,1024 * 8);
out = new ByteArrayOutputStream();
int len=0;
byte[] buffer = new byte[1024];
while((len = bis.read(buffer)) != -1){
out.write(buffer, 0, len);
}
out.close();
bis.close();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = out.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//Drawable d = Drawable.createFromStream(i, "src");
return bitmap;
}
I loaded the image by multithreading, and then I had to loop reading the inputStream when the thread's time was held by another. Make sure the inputStream is read fully.
Here is what the issue was for me:
From the emulator I would save the jpg file locally (on the emulated sdcard) and then attempt to read it up and display it using decode on the emulator and it worked. Then, as a test, I copied the file (using adb pull) to my development (xp) machine and it would display using 'paint'. Then, from the emulator, I uploaded the file (via http post) to my win2003 server. Using 'paint' it displayed there as well. But when I downloaded it back to the emulator (via http get), it failed during the decode.
Then I noticed that the file uploaded to the win2003 server was two bytes smaller than the original. Not totally sure how that happened because I've been using the same upload logic for years and never noticed the issue before. As a test, I simply appended two more random bytes during the upload so the file size was exactly the same. Then, when downloaded back to the emulator, it decoded and displayed properly.
Just as a check, I appended two random bytes over on my xcode projects and then those jpg files also displayed on the android emulator as well.
So, although the files which were two bytes smaller displayed everywhere else, they would not on the emulator. Apparently decode is doing some sort of CRC before it attemps to decode and decides it cannot continue. And hence the error.
Others who are facing issues in Android KitKat 4.4 , following would be helpful
Bitmap b = BitmapFactory.decodeStream(new BufferedInputStream(is));
imageView.setImageBitmap(b);
I was facing this issue in Nexus series After updating to 4.4.
I ran into this issue as well using Xamarin. To fix it I simply used the Universal Image Loader Xamarin Component and it worked like a charm.
Hope this helps!

Categories

Resources