Reputation: 405
as
bm.compress(Bitmap.CompressFormat.PNG, 50, out);
//here 50 will not work as PNG is lossless
how to reduce .png image size? also just coping to external location from drawable make file size increase by 5 to 10 times?
Bitmap bm=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File file = new File(extStorageDirectory, "ic_launcher.PNG");
outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
Upvotes: 5
Views: 9647
Reputation: 8979
You are keeping the quality of bitmap as it is. is it necessary for you? if not so, you can reduce size as bm.compress(Bitmap.CompressFormat.PNG, 50, outStream);
. here the 50 is the quality of bitmap being compressed. another option is to use Bitmap.Option
Before Loading the Bitmap into Memory.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 3;
try{
mBitmapImage = BitmapFactory.decodeFile(mPhotoPath.replace("file://" , ""), options);
}catch(Exception e){
e.printStackTrace();
throw new OutOfMemoryError("Device Out of Memory, can't obtain Bitmap");
}
if you just want to get the size of Bitmap, make options.inJustDecodeBounds = true
. it's helpful to prevent runtime crashes of application
for more information on Bitmap loading and compression refer to the developer docs https://developer.android.com/topic/performance/graphics/load-bitmap
Bitmap class is not that much helpful compressing PNG. It only creates PNG-32 with limited optimization. The aapt, does optimize the PNG file. hence, when you are uncompressing and reading your PNG file into a bitmap, and then compressing it with the bitmap class, you are getting a much larger file. You can use the pngj library, which supports better compression and optimization of PNG files. According to your description you don't seem to edit the files in the app, you may just copy from the resources to the card, so all you need to do is include the PNG file in the raw folder, and retrieve a stream to it by calling openRawResource() method, and copying it directly to card. You may further optimize the original PNG file using TinyPNG before including it in your app.
Upvotes: 0
Reputation: 3513
I know this is old, but I will still answer for any future seekers.
Android's Bitmap class is pretty limited in compressing PNG. It only creates PNG-32 with limited optimization. The aapt program, that packages your apk file, does optimize the PNG file. Therefore when you are uncompressing and reading your PNG file into a bitmap, and then compressing it with the the bitmap class, you are getting a much larger file.
You can use the pngj library, which supports much better compression of PNG files.
But based on your description you don't seem to edit the files in the app, you just copy from the resources to the card, so all you need to do is include the PNG file in the raw
folder, and retrieve a stream to it by calling openRawResource()
, and copying it directly to card. You may further optimize the original PNG file, by using TinyPNG before including it in your app.
Upvotes: 4
Reputation: 438
1)If your pngs are pre defined you can use tiny png service to have very small pngs. The service is reducing png size about 60 percents, without any noticable change. 2)If your pngs are created/get during runtime, try to use Bitmap.createScaledBitmap() method. With this method you can create small size pngs.
In the method
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream)
;
100 is ignored in case of PNG. Because it's lossless. Instead you can use
bm.compress(Bitmap.CompressFormat.JPEG, 80, outStream);
This one will give you small size and will compress faster.
Upvotes: 5
Reputation: 201
Do you want to stick strictly to PNG? Bitmap.compressFormat.JPEG would be able to compress much more.
The only way to reduce PNG file size is to reduce the PNG image dimensions to something smaller. I don't think that's straight forward with pure Android, but there are image libraries you can use for this.
You can also write it yourself by creating a new Bitmap object and manually reading from original using getPixels(...), pocessing them to downscale, and writing the new one. But I would not recommend that, resizing can be tricky to get working properly with anti-aliasing.
Upvotes: 0