I am creating an android app and want to read a file from sdcard and send it to a rest webservice. Everything works fine but when I read the file from sdcard its filesize is much bigger than its originalsize. A 10 KB file is getting 260 KB.
I am doing the following...
File f = new File(uri);
Log.d("ORIGINAL FILESIZE:"+f.length());
Filesize 10752 Bytes on SDCARD.
This is exactly the same size the image has on the phone.
Bitmap bmp = BitmapFactory.decodeFile(uri);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, bao);
Log.d("FILESIZE AFTER:"+bao.size());
Filesize 260904 Bytes after decode / compress.
This is the filesize the server receives and writes to disk.
It's the same Image and Quality but about 20 times bigger.
Does anyone know what I am doing wrong?
If your original file is a jpeg with high compression rate, it's normal that the decoded bitmap is much larger, especially if you use a quality of 100 in the compress() method (which means high quality).
Did you try using compress() with a lower quality value (cf documentation) ?
It is not wrong. Or at least it could be. The bytes rapresentation of a bitmap in memory, requires (a 32-bit image) height * widht * 4 bytes. And of course it differs from the file size becaouse of the compression.
Related
I am now a newbie to android programming.
I am very confused when processing with images.
I am now trying to load a jpeg image to bitmap and then convert bitmap to byte array and vice versa.
I am testing with the first case: load jpeg to bitmap and get byte array.
My input image 520 x 390 (24 bit color) 24KB JPEG.
My output byte array is ~ 290000 bytes ~ 290KB, very large from the original one.
How can I convert it into byte array with the same size or nearly the same size as the original JPEG?
Therefore, I wonder if the inverse conversion will convert byte array to jpeg the same size or not ?
Here is my code:
Resources r = this.getResources();
Bitmap bm = BitmapFactory.decodeResource(r,R.drawable.plot);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,100,baos);
byte[] byteArray = baos.toByteArray();
bitmap.compress has a property of quality (the 2nd one). try reducing if from 100 to a lower number (0-100).
The JPEG you loaded is most likely to have a level of compression, which is what makes JPEGs smaller, by trading quality for size.
In your code you are setting a compression level of 100, this means no compression at all, so the bitmap is saved in JPEG format, but as it is without any size/quality reduction at all.
If you change the compression level to anything lower than 100 you will see how the file size gets smaller. Try between 80 to 90 to keep a good quality while getting a smaller file.
How can I convert it into byte array with the same size or nearly the same size as the original JPEG?
Just load the jpg file in a byte array if you need it in a byte array.
There is no need to convert to bitmap first.
I need to compress an image to send it to my server. I am trying to do it this way:
private Bitmap compressImage(Bitmap bitmapImg){
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmapImg.compress(Bitmap.CompressFormat.JPEG, 50, out);
Bitmap compressed = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
return compressed;
}
But when I compare the Byte count of the original Bitmap object and the compressed one, I get the same number:
Log.e("UNCOMPRESSED", Integer.toString(mBitmapImg.getByteCount()));
E/UNCOMPRESSED: 23970816
Log.e("COMPRESSED", Integer.toString(compressedBitmapImg.getByteCount()));
E/COMPRESSED: 23970816
How can I fix this to have a smaller file?
But when I compare the Byte count of the original Bitmap object and the compressed one, I get the same number:
The size of a Bitmap in memory is based only on its resolution (width and height in pixels) and bit depth (the number of bytes per pixel, for controlling how many colors can be used per pixel).
How can I fix this to have a smaller file?
You do not have a file. You have a Bitmap object in memory. An image file is usually stored in a compressed form. In particular, this is true for JPEG, PNG, WebP, and GIF, the four major image formats used in Android. So, for example, out.toByteArray() will be smaller than 23,970,816 bytes.
Moreover, you are not sending a Bitmap to the server. You are sending an image to the server. You need to read the documentation for the server, or talk to the server developers, to determine what image format(s) they support and how to send the image to the server (ideally, something efficient like an HTTP PUT).
If you want to reduce the in-memory size of the Bitmap, scale it to a lower-resolution image (e.g., via createScaledBitmap()).
You can change your bitmap format to RGB_565 from ARGB_8888. That'll reduce your bitmap's memory footprint to half, but, would lead to loss of quality as well. Unfortunately, that's the most you can do with Bitmap.
Having said that, the compression method that you're using should work fine for most situations. It's also the advocated method for a number of platforms. An example for Firebase is this.
I'm trying to reduce the file size from gallery before upload to the server with base64. I've tried ALL the suggestions from stackoverflow & elsewhere I've found on the internet without success.
For images > 2MB, they seem to be reduced in size once written on the server (down to ~500KB). However, for images < 500KB they seem to be bigger than original file size once decoded and written on the server (again ~500KB). It seems like there's threshold that base64 can't get lower beyond). Is it true? Any other way I can reduce the image file size and upload to server programmatically?
private String string(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 50, stream);
return Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT);
}
Pass bitmap into string method, to convert into String. compressFormat is in PNG which automatically lower the size and quality.
I use the following code to obtain a bitmap from an ImageView. This image is not saved anywhere else on my device. I want to upload this image into an online mysqli database. However, to do so I need to decrease the size of the file first. I found a lot of links about this, however they all require the file to be saved on the device and then use FileOutputStream. I am looking for a way to reduce the file size so that it can be comfortably transferred using the Volley API ( i am currently receiving either run out of memory exceptions or broken pipe errors). Hence I am looking for a way to modify this code to be able to significantly decrease the file size, whilst still maintaining a quality which can be comfortably shown on a mobile device. The original image is taken straight from the camera hence the size is quite large. Here is my code:
ImageView pic_holder = (ImageView) findViewById(R.id.picturedisplay);
Bitmap bitmap = ((BitmapDrawable)pic_holder.getDrawable()).getBitmap();
ByteArrayOutputStream stream=new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
byte[] image=stream.toByteArray();
String img_str = Base64.encodeToString(image, 0);
I would like to decrease the size of the img_str which is passed to my Volley method.
I have a problem in saving images in my app.
The process is simple:
1 - I read the image into a bitmap for display
2 - Save the bitmap as a new file
At this point, I do not understand why the final file has a size much larger than the original image. For example, a 170 kb image is saved in a new file 1 mb.
I know the difference in the management of compression between PNG and JPG, but I expect that if I read a PNG file, and save it in the same format, the size remains the same.
Thank you all for the help.
Edit
This is my code for saving method:
Bitmap resized = Bitmap.createScaledBitmap(original, generateWidth, generateHeight, false);
FileOutputStream out = new FileOutputStream(tempResizedFile.getPath());
resized.compress(generateType.CompressFormat(),
qualityBar.getProgress(), out);
out.close();