I am saving an image in storage, but the quality of image is lost due to compression. So how could I save the image without compressing it.
I'm using the following code
//Creating bitmap from Resource id
Bitmap bitmap=BitmapFactory.decodeResource(getResources(), BitmapId);
String extStorage=Environment.getExternalStorageDirectory().toString();
File file = new File(extStorage, "name.png");
if(file.exists())
file.delete();
try {
outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
.....
}
Please let me know how to save the image without losing its quality..
The second parameter u supply 100 is actually does not affect ur image quality,but in case if u want to compress more u can reduce the value to even 10 ,u will get a low quality image in that case ,only useful for memory issues,,
But i thing the value 100 will not affect ur quality, its just a guess
Related
I am trying to make an app which can generate an image file(JPEG/PNG) with dimensions equal to the user's phone's screen size and fill it with a single solid color(BLACK/BLUE/GRAY, etc). After generating it, it should save the image to the external storage to be used in any other app.
Any help would be appreciated.
So far I have been able to do this based on a few answers but it doesn't generate any image file. (I have given the permission to write in External Storage)
Bitmap bmp = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);//MUTABLE bitmap
File file = new File(Environment.getExternalStorageDirectory(),"/image" + System.currentTimeMillis() + ".png");
FileOutputStream str;
try {
str = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG,100,str);
}
catch (IOException e) {
e.printStackTrace();
}
This was just an attempt to check whether any image would be generated/stored or not.
try closing the stream: str.close() after you write to it
EDIT: since it worked, let me explain a bit: the stream keeps everything buffered in memory until some time (this isn't a totally deterministic thing), so if you close the stream it flushes everything it has buffered. So it's always a good practice to close streams.
Is there a way to resize a JPEG image file (from filesystem to filesystem) without removing meta data (just like ImageMagicks convert in.jpg -resize 50% out.jpg)?
The only way I found to resize .jpg files I found is BitmapFactory.decodeStream and Bitmap.compress, which looks like a lot of overhead if I manually need to transfer image meta data.
It may be possible to read the metadata with android.media.ExifInterface, compress the image via Bitmap.compress and then save the metadata back:
String filename = "yourfile.jpg";
// this reads all meta data
ExifInterface exif = new ExifInterface(filename);
// read and compress file
Bitmap bitmap = BitmapFactory.decodeFile(filename);
FileOutputStream fos = new FileOutputStream(filename);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
// write meta data back
exif.saveAttributes();
I didn't test it, but looking at the source code of ExifInterface, it may work.
If you don't want to rely on the implementation details, you could of course loop through all attributes and copy them.
Another solution would be to use the Android Exif Extended library. It is a small project to read and write exif data.
I'm using Android-Universal-Image-Loader for downloading image files from my server using .loadImageSync(imageURL) method.
And then I need to save that bitmap to user device external storage.
File file = new File(mContext.getExternalFilesDir(null) + directoryIntermediatePath, fileName);
FileOutputStream fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
My issue is .png file on my server holding size of approx 200KB, which will become approx 700KB after this process on android device storage.
You should not save the loaded image to disk. Instead you should use the file as it had been downloaded.
If I got it right the Android-Universal-Image-Loader library uses a disk cache.
If you set a specific DiskCache implementation while building the ImageLoaderConfiguration you should be able to access this DiskCache later and retrieve it later via:
File f = DiskCacheUtils.findInCache(imageURL, diskCache);
Then you only have to copy the file on byte[] level.
You can try reducing the quality parameter in bitmap.compress to some value less than 100. However, for PNG image, which is a lossless format, Bitmap will ignore the quality parameter. So, an option is to convert to JPEG for reduced size. For example, use this line:
bitmap.compress(Bitmap.CompressFormat.JPEG, 60, fileOutputStream);
For more information on bitmap.compress, check here.
If you want to reduce to a specific size using PNG, you'll have to re-scale your image; this SO link may prove useful.
I tried to make a copy of an image file by first decoding the image file to Bitmap and compress it back to JPEG. The copy(~3mbs) is larger than the original file (~2mbs). Is there any way to create an exact copy?
Bitmap origBitmap = BitmapFactory.decodeFile(file);
FileOutputStream out = new FileOutputStream(file);
origBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
// this will give me a copy larger than the original image
I know I could use FileOutputStream and FileInputStream to create an identical copy. But I want to make some modification to the copy and Android doesn't support Javax.ImageIO.
FileOutputStream out = new FileOutputStream(file);
File old_file = new File(filePath);
FileInputStream input = new FileInputStream(old_file);
copyStream(input, out);
// this will give me an exact copy
JPEG is a lossy format, which means every time you use the algorithm you're losing some data. It'll look worse every time you do this, even at high quality settings.
Your copy is likely larger because you're using a quality setting of 100. I'd bet that the original file was made with a lower quality setting - usually people use between 70 and 90.
When i capture an image from the camera (from the device home screen) and check the image size on the SD card, it shows between 300-500 Kb.
But when i capture an image in my Application using the Camera Intent, and save it on SD card(in a new folder) it shows image size between 5-10 Kb.
This is the code i am using to save the Image on the SD card after taking the picture in the onActivityResult:
Bitmap bit = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bit.compress(Bitmap.CompressFormat.JPEG, 100, bao);
byte[] ba = bao.toByteArray();
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "My - Images");
File f = new File(imagesFolder, "test.jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(ba);
fo.flush();
fo.close();
how to save it as the original sized image(300-500 Kb)?
and is there a way to get the image size before i save it on the SD card??
Thank You
You are using the following to compress the bitmap object you receive:
bit.compress(Bitmap.CompressFormat.JPEG, 100, bao);
That is the reason your bitmap is being stored in a compressed format.
Also, you can use bit.getHeight() and bit.getWidth() to get the dimensions of your bitmap. You can use bit.getByteCount() to get the actual size of your bitmap
Check the answer that is accepted here, hope it may work for you
Android Camera Intent: how to get full sized photo?
Firstly try to find out the size of the picture using the code below
Camera mCamera = null;
Camera.Parameters camParams = mCamera.getParameters();
Size camSize = camParams.getPictureSize();
If the picture size you get is 5-10 KB, then there is nothing wrong with your code, you may have to re-visit your camera parameters to see what quality you have set.