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.
Related
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 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.
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
I have got some performance problems with iText. It takes about 20 seconds to put an image into the PDF. The thing is that I have time to make those images in any format, but I should be able to add those images to PDF very quickly.
The code is for image creation is:
androidsScreenElement.setDrawingCacheEnabled(true);
androidsScreenElement.buildDrawingCache(true);
Bitmap cache = plot.getDrawingCache();
fos = new FileOutputStream("filepath.png", true);
cache.compress(Bitmap.CompressFormat.PNG, 75, fos);
fos.flush();
fos.close();
This code may run as long as it should to make optimal image for the PDF creator.
The PDF creator code is:
Document document = new Document(PageSize.A4, 30, 10, 70, 70);
PdfWriter writer = PdfWriter.getInstance(document, file);
Image image = Image.getInstance(APsFile.getAbsolutePath());
image.scalePercent(65);
image.setAlignment(Image.ALIGN_CENTER);
document.add(image);
And this is a critical part, PDF code takes too long to execute. I am wondering what an optimal image format would be. Also I cannot do caching because my android device has too litle memory already so I have to keep all 5 images in the file for before it runs the PDF generation code.
I want to download PDF's and images into my app, essentially it will call a JSON web service that returns the link to the PDF, link to the image, and the title. It will download the image and PDF and save them. Then it will display the PDF's and images with the title. My only question is how do I deal with images? They cant be saved to APK since it is locked. The images are high enough resolution that they can scaled down to fit all the other densities, should I just use the large image, and let the activity scale it down when it uses it. Or should I implement an image scaler during the retrieval process?
Eventually the PDF's and images would be loaded into the APK. How would I check the assets folder to remove the images, would I just need to call a service that runs when the Application First starts to check for the files in the assets folder then remove them if they are present?
Sample code for your reference where u can download Images from the web.Its better to store Images in asset folder than Internal Memory and resize the images for good performance.U can delete the folder before making web service call and load new set images.
if (Utility.isWifiPresent()
|| Utility.isMobileConnectionPresent()) {
URL url = new URL(fileUrl);
InputStream iStream = url.openConnection().getInputStream();// .read(data)
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] tmpArray = new byte[1024];
int nRead;
while ((nRead = iStream.read(tmpArray, 0, tmpArray.length)) != -1) {
buffer.write(tmpArray, 0, nRead);
}
buffer.flush();
data = buffer.toByteArray();
FileOutputStream fOut = null;
//path to store
fOut = Utility.getFileOutputStreamForCloud(
sdcardFolderPath, fileUrl);
}
fOut.write(data);
fOut.flush();
fOut.close();