Corrupted Images From BitmapFactory - android

Once in a while when I am downloading images, some of them will appear with gray lines as displayed in the sample image below:
This tends to happen exclusively on poor network conditions.
My code for decoding images is essentially a modded version of that from UIL:
Bitmap decodedBitmap = BitmapFactory.decodeStream(stream, null, decodingOptions);
where stream is just an InputStream to the remote file
Now I've seen this behaviour on the Google Play Music app which makes me wonder if it's an issue with the BitmapFactory.
The only solution I've come up with so far is maybe doing a checksum comparison to make sure the entire image was downloaded.
Edit:
HttpURLConnection conn = getConnection(path);
InputStream inputStream = conn.getInputStream()
stream = new ContentLengthInputStream(new BufferedInputStream(download, BUFFER_SIZE), conn.getContentLength())

Solved it by using the following steps:
Open an InputStream to the image as normal
Write the stream to a ByteArrayOutputStream
Compare the length of the ByteArrayOutputStream to the Content-Length header from the HttpURLConnection
If mismatch then you've lost data in transit
Otherwise you can convert your ByteArrayOutputStream to a ByteArrayInputStream and use with the BitmapFactory as you see fit

Related

Why size of image is not same when i download an image from a url?

I am downloading an image from a url and create a bitmap image in my android app. Size of image is 126 kb. When i create an image in my app by downloading it from url then size is around 3.25 mb. I am using following code to downlad image from url:
URL urlConnection = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) urlConnection.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
Why downloaded size of image is bigger and is there any way to download it in the same size? Thanks in advance.
Image you download is probably in some compressed format (.jpg .png). Bitmap you get from BitmapFactory.decodeStream on the other hand is in uncompressed format.
If you dont need to show your bitmap in original resolution you can scale it down (detailed instructions here). Otherwise such memory usage is normal.
Android converts this image to bmp. You can convert it by youself and you get size ~3.5 mb.
Dont use Bitmapfactory for downloads. Use an InputStream and a FileOutputStream to save to internal, external or removable memory directly.
Image size depends on bits per pixel .during conversion you have to give bits per pixel
file size is given by Resolution^2 x Width x Height x Bits per sample รท 8,192

Why does creating a Drawable from an InputStream cause an OutOfMemoryError when the InputStream comes from a url but not from a asset?

I am working on an app that displays floor plans for buildings. The floor plans are .png files hosted on a server.
This code causes an OutOfMemoryError:
InputStream is = null;
HttpGet httpGet = new HttpGet("http://server/image.png");
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(httpGet);
is = response.getEntity().getContent();
Drawable d = Drawable.createFromStream(is, null); //this line causes an OutOfMemoryException
imageView.setImageDrawable(d);
But this code does not:
InputStream is = assetManager.open("image.png");
Drawable d = Drawable.createFromStream(is, null);
imageView.setImageDrawable(d);
The images are fairly large in dimension (5100 x 3300 for one example) but that image is only ~100 KB viewing it online, and it's not much smaller (~95 KB) when looking at it in the .apk file.
Does anyone know why the first code snippet causes the error but the second one doesn't? During debugging the first InputStream is only ~102000 bytes in size and the second InputStream is only ~95000 bytes in size. That doesn't seem like a big enough size difference to explain the error.
The drawable stream is going to create a bitmap drawable for it. That means it needs to store the uncompressed full bitmap in memory. To do that, it needs to allocate the entire memory- 5100*3300*4 bytes, or 64 MB. That's way way too large for Android.
When going from assets, it probably isn't reading the file until it has to, and isn't creating an in memory bitmap. It can just keep the file pointer in memory. But you can't do that with a stream, the stream may not be value by the time you get around to reading it, and you can't read it more than once (while you can a file).

How to speed up image loading from a server - Android

I am still a beginner in Android and java. I am trying to load an image from a server by using AsyncTask. The size of the image is around 50kb. Yet it takes several seconds to show up. The following code is used to download the image from the server.
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(input);
Bitmap myBitmap = BitmapFactory.decodeStream(bis);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
Can someone please tell me how to speed up this process. What are the factors this process depends on apart from the network speed?
Thank you in advance.
Firstly, I suggest you to search image size reduce algorithms. Then, you can choose some methologies to load picture. For example, in first step, you can load low sized images. After that , you can load normal size images in background and update each reduced sized images to normal sized images.
Here is a great resource on loading Bitmaps efficiently.
Android Developer site - Loading Large Bitmaps Efficiently
It also includes a code sample.

Assigning GIF data to Bitmap object

I've read in numerous places that Android does not have native gif support. As a result, my code is failing on BitmapFactory.decodeByteArray. Here's my code:
URL url = new URL(imgURL); //you can write here any link
HttpURLConnection ucon = (HttpURLConnection)url.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(5000);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
image = BitmapFactory.decodeByteArray(baf.toByteArray(), 0, baf.toByteArray().length);
Using the debugger I confirmed the header data is loaded properly and is of GIF format. But once the decode function runs I'm left with a null value. My first guess is that I need to do a GIF -> PNG conversion. How can I do this? Are there other options?
The GifView class at http://code.google.com/p/android-gifview/ works well. That project is intended for animated gifs, however it works fine with static gifs as well.
So despite Android complaining about the GIF and decode failing I think the issue resided through other failures in my code. Changes I made which cause the code to now work.
Made sure I closed the input stream
Removed an incident which could cause infinite looping and thread generation (this was a failure on my parsing rules that pulled out the list of GIF files from an HTML source)
Ensured my storage of the Bitmap files in a List object were always properly casted before being used.
I found help and details through this posting which was an almost identical issue. There are links that follow through on the issue.
In the end I didn't touch my Bitmap or InputStream objects at all, the data was being received properly (as per my confirmation with the GIF header bytes) but was a failure of using the data afterwards.

Android: Upload JPG image without losing EXIF

I'm uploading JPG image as byte[] but Bitmap strips of EXIF before converting to byte[]. How do I upload raw jpg without converting it to Bitmap?
File imagefile = new File(filepath + "DSC00021.jpg");
FileInputStream fis = new FileInputStream(imagefile);
Bitmap bi = BitmapFactory.decodeStream(fis); // EXIF info lost
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bi.compress(Bitmap.CompressFormat.JPG, 100, baos);
byte[] data = baos.toByteArray();
p.s. I don't want to use any 3rd party library. ExifInterface can only write to file and not streams/byte arrays.
Above code will not work most cases. In case if you want to decode large size image you will get "out of memory error". Decode using bitmpafactory options.
Convert the file to bitmap by
Bitmap bi = BitmapFactory.decode(filepath + "DSC00021.jpg");
You can specify options too, look at API documentation
Or if you want to exchange the meta data from one file to another, sanselan will probably be the best choice. This would be much helpful when you manipulating the image, for example re-size.
The sample code will guide you in a right direction.

Categories

Resources