Resize JPEG image in filesystem - android

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.

Related

How to create a gallery app for usb otg?

I know a library called libaums and had implemented it, but I don't know how to open Images and Videos using their library.
According to https://github.com/magnusja/libaums, you can actually read a file from the storage using this:
// read from a file
InputStream is = new UsbFileInputStream(file);
byte[] buffer = new byte[currentFs.getChunkSize()];
is.read(buffer);
Then your buffer contains the image data, so you can convert it to e.g. a Bitmap, like this:
Bitmap bmp = BitmapFactory.decodeByteArray(buffer , 0, buffer .length);
After that you can set it to an ImageView or whatever to show it to your user.
To be short, find your File and implement this logic.

android image file size increased after storing

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.

JPEG to Bitmap to JPEG

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.

Save image in internal storage without compressing

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

Android - Store an image on device?

My application allows users to take a photo using the camera and save it as their profile picture. There can be only 1 image stored at a time?
Is it a bad idea to use SharedPrefertences for this purpose although I am only storing 1 image? (Converting image to Base64). What are the cons?
If storing the image using shared preferences is not a good idea, what are the alternatives?
I think storing binary data in SharedPreferences is not a good idea. Instead save it to the filesystem. Example for that, if the data is coming from an InputStream:
storeImage( new File(context.getFilesDir().getAbsolutePath() + fileDir),
is,
"profile.png" );
public static void storeImage(
File fileDir,
InputStream inputStream,
String fileName ) throws IOException {
File file = new File( fileDir,fileName );
FileOutputStream fos = new FileOutputStream( file );
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
inputStream.close();
fos.close();
bitmap.recycle();
bitmap = null;
}
Where context can be the Application/Activity context.
There is no reason why you can't use SharedPreferences to store a single image as a Base64 String, Of course this isn't really a scalable approach as when the SharedPreferences are loaded, every image would be loaded into memory at once, but that's not what your looking for.
The other possible approaches you can take is to store the images either using the internal or external storage APIs or to store them in a database
In general for this kind of thing you should be looking to use something other than shared preferences, however in this case, I can't see there been an actual issue to the approach your suggesting.

Categories

Resources