I read a lot of topics where bitmap was resizes by decodeFile and createScaledBitmap. But I would like to change this file, without create extra bitmaps or files. It means, just when I open this file bitmap will be smaller/bigger. Is it possibility?
Edit:
Specifically, I have jpeg files and I will zip this files, and before making zip I set size of images (in zip file).
I'm not clearly understood, what you want to obtain,
but here is a simple code to resize image file
String your_file_path = "image.png";
int set_scale_your_need = 2;
//getting your image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(your_file_path, o);
o.inJustDecodeBounds = false;
o.inSampleSize = set_scale_your_need;
Bitmap bitmap = BitmapFactory.decodeFile(your_file_path, o);
FileOutputStream fos = new FileOutputStream(your_file_path, false);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
If you just want to have it open as a smaller version of it's self you can use BitmapFactory.Options.inSampleSize to reduce the load size. If you want to actually resize the image and resave it to the file system, you will want to do that in an AsyncTask,
something like this:
public class ImageResizerTask extends AsyncTask<Integer, Void, Bitmap> {
Bitmap mBitmap;
String filePath;
Context mContext;
Activity mCallBack;
//ProgressDialog pd;
public ImageResizerTask(Context context, String path,
Activity callBack) {
mContext = context;
filePath = path;
mBitmap = BitmapFactory.decodeFile(filePath);
mCallBack = callBack;
}
#Override
protected void onPreExecute() {
}
#Override
protected Bitmap doInBackground(Integer... params) {
// TODO Auto-generated method stub
resize(mBitmap);
return mBitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
//pd.dismiss();
bitmap.recycle();
mCallBack.onImageResized(filePath);
}
private void resize(Bitmap tmp) {
final Bitmap bitmap = Bitmap.createBitmap(500, 500,
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
Log.v("TMPBMP",
"temp bmp width:" + tmp.getWidth() + " height:"
+ tmp.getHeight());
if (tmp.getWidth() < tmp.getHeight()) {
final int width = (int) (1f * tmp.getWidth() / tmp.getHeight() * 500);
final int height = 500;
final Bitmap scaled = Bitmap.createScaledBitmap(tmp, width, height,
false);
final int leftOffset = (bitmap.getWidth() - scaled.getWidth()) / 2;
final int topOffset = 0;
canvas.drawBitmap(scaled, leftOffset, topOffset, null);
} else {
final int width = 500;
final int height = (int) (1f * tmp.getHeight() / tmp.getWidth() * 500);
;
final Bitmap scaled = Bitmap.createScaledBitmap(tmp, width, height,
false);
final int leftOffset = 0;
final int topOffset = (bitmap.getHeight() - scaled.getHeight()) / 2;
canvas.drawBitmap(scaled, leftOffset, topOffset, null);
}
FileOutputStream outStream;
try {
outStream = new FileOutputStream(filePath);
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Related
I have a function to send a file (picture from camera or gallery) to a WebService.
I would like to reduce the image size of fileUri before post (50% per example).
The file is a gallery or camera image.
This is my postFile function :
public static void postFile(Context context, String url, String fileUri, AsyncHttpResponseHandler responseHandler) {
if (myCookieStore == null)
{
myCookieStore = new PersistentCookieStore(context);
client.setCookieStore(myCookieStore);
}
File myFile = new File(Uri.parse(fileUri).getPath());
RequestParams params = new RequestParams();
try {
params.put("profile_picture", myFile);
} catch(FileNotFoundException e) {
Log.d("error", "error catch");
}
Log.d("absolute url", "" + "*" + getAbsoluteUrl(url) + "*");
client.post(context, getAbsoluteUrl(url), params, responseHandler);
}
How can I do that ?
There is this library, that can compress your images to kb from mb, it is very powerful i have used it alot of times, it works file uploads are superfast. link
Snippet : compressedImageFile = Compressor.getDefault(this).compressToFile(actualImageFile);
It internally uses google webp format, WebP is a modern image format that provides superior lossless and lossy compression for images on the web. Using WebP, webmasters and web developers can create smaller, richer images that make the web faster.
The library is great at size compression, it does a really good job, at large files that was based on my observations, like 2mb up, however there are some memory leaks that you need to address, i solved mine by using leak canary , though every developer should always use it. Overall it is awesome fork it and use as please.
I used this code in many projects and always it gives me good results, i remember if i choose a image having size of 5-7MB(image from 12/13 MP camera) this code returns an image of size 1MB or less than 2MB.
public static boolean validateUri(Uri uri) {
if (uri == null)
return false;
else {
String path = uri.getPath();
return !(uri.equals(Uri.EMPTY) || path == null || path.equals("null"));
}
}
First we need a full image and rotate if needed.
public static Bitmap getFullSizeImage(Context context, Uri uri) {
String filePath;
if (validateUri(uri) && uri.toString().contains("file"))
filePath = uri.getPath();
else
filePath = getRealPathFromURI(context, uri, MediaStore.Images.Media.DATA);
if (filePath == null)
return null;
try {
int rotation = 0;
ExifInterface exifInterface = new ExifInterface(filePath);
int exifRotation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
if (exifRotation != ExifInterface.ORIENTATION_UNDEFINED) {
switch (exifRotation) {
case ExifInterface.ORIENTATION_ROTATE_180:
rotation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotation = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotation = 90;
break;
}
}
Matrix matrix = new Matrix();
matrix.setRotate(rotation);
// you can use other than 400 as required width/height
Bitmap sourceBitmap = getBitmapFromPath(400, filePath);
if (sourceBitmap == null)
return null;
return Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(),
sourceBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Now we need a real path from URI
public static String getRealPathFromURI(Context context, Uri contentUri, String type) {
Cursor cursor = null;
String path = null;
try {
// String[] proj = { MediaStore.Images.Media.DATA };
String[] projection = {type};
cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
if (cursor == null)
return null;
int columnIndex = cursor.getColumnIndexOrThrow(type);
cursor.moveToFirst();
path = cursor.getString(columnIndex);
// we choose image from drive etc.
if (path == null)
path = getDocumentRealPathFromUri(context, contentUri);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return path;
}
If we choose a picture from drive etc. we still need a real path of given URI
public static String getDocumentRealPathFromUri(Context context, Uri contentUri) {
Cursor cursor = context.getContentResolver().query(contentUri, null,
null, null, null);
if (cursor == null)
return null;
cursor.moveToFirst();
String documentId = cursor.getString(0);
documentId = documentId.substring(documentId.lastIndexOf(":") + 1);
cursor.close();
cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null, MediaStore.Images.Media._ID + " = ? ",
new String[]{documentId}, null);
if (cursor == null)
return null;
cursor.moveToFirst();
String path = cursor.getString(cursor
.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
return path;
}
Now we've a real path of selected image so we can get a bitmap from this path using sample size
public static Bitmap getBitmapFromPath(int size, String realPathFromURI) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(realPathFromURI, options);
options.inSampleSize = calculateInSampleSizeUsingPower2(options, size, size);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(realPathFromURI, options);
}
public static int calculateInSampleSizeUsingPower2(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth)
inSampleSize *= 2;
}
return inSampleSize;
}
At this point we've a compressed bitmap, further more we can again compress this bitmap if we perform Base64 operation on a given bitmap.
public static String convertToBase64(Bitmap bitmap) {
if (bitmap == null)
return null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)) {
String base64 = encodeToString(byteArrayOutputStream.toByteArray(), DEFAULT);
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return base64;
}
return null;
}
On your sever end you can decode Base64 and convert back to file stream and save your image.
Example
Bitmap bitmap = getFullSizeImage(context, selectedPhotoUri);
if(bitmap != null){
String base64Image = convertToBase64(bitmap);
if (base64Image != null) {
RequestParams params = new RequestParams();
try {
params.put("title", "your_image_name");
params.put("profile_picture", base64Image);
} catch(FileNotFoundException e) {
Log.d("error", "error catch");
}
}
}
Note
If you don't want to perform Base64 you can use your bitmap to convert into stream and send it to your server.
Use this one to change image width and height
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
you can use this one for change the size ...This is the Best Example.....
private Bitmap decodeFile(File f){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
Try this function.It will reduce the size of the bitmap to 512 if its width or height is greater than 512
public static Bitmap resizeBitmap(Bitmap bm) {
if (bm.getWidth() > maxSize || bm.getHeight() > maxSize) {
if (bm.getWidth() > bm.getHeight()) {
newWidth = maxSize;
newHeight = (bm.getHeight() * maxSize) / bm.getWidth();
bm = Bitmap.createScaledBitmap(bm, newHeight, newWidth, true);
return bm;
} else {
newHeight = maxSize;
newWidth = (bm.getWidth() * maxSize) / bm.getHeight();
bm = Bitmap.createScaledBitmap(bm, newHeight, newWidth, true);
return bm;
}
}
return bm;
}
You just have to pass the bitmap to this method.
The method to get the bitmap from URI is
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
If the camera image is JPEG, you can use the Bitmap compression method, like:
Bitmap bitmap = BitmapFactory.decodeStream(...uri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
int compression_factor = 50; // represents 50% compression
bitmap.compress(Bitmap.CompressFormat.JPEG, compression_factor, baos);
byte[] image = baos.toByteArray();
// now update web service asynchronously...
...
} finally {
baos.close();
}
Convert the image into bitmap then use below method
public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
float scaleX = newWidth / (float) bitmap.getWidth();
float scaleY = newHeight / (float) bitmap.getHeight();
float pivotX = 0;
float pivotY = 0;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
}
I am developing a application in which I want to resize captured image before store it in specified folder of sdcard.
I have used all the permissions required for write the data in sdcard but still I am unable to do it.
my code:
try{
Bitmap bitmap = Constant.decodeFile(fileName);
bitmap = Bitmap.createScaledBitmap(bitmap, 480, 320, true);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bytes);
File f = new File(fileName.toString());
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
}catch (Exception e) {
e.printStackTrace();
}catch (OutOfMemoryError o) {
o.printStackTrace();
}
You have forgot to flush the Stream after writing data into into. use FileOutputStream.flush() after writing data... and
try this...
File file = new File(fileName.toString());
try {
FileOutputStream stream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, stream);
stream.flush();
stream.close();
} catch (Exception e) {
// TODO: handle exception
}
You can use createBitmap() to resize the original image.
FOllowing are the parameters:
(Bitmap source, int x, int y, int width, int height)
source The bitmap we are subsetting
x The x coordinate of the first pixel in source
y The y coordinate of the first pixel in source
width The number of pixels in each row
height The number of rows
Example:
Bitmap newbitmap = Bitmap.createBitmap(originalBitmap, 2, 2, bitmap.getWidth() - 4, bitmap.getHeight() - 120);
There is a nice tutorial on resizing images:
BitmapScaler scaler = new BitmapScaler(getResources(), R.drawable.moorwen, newWidth);
imageView.setImageBitmap(scaler.getScaled());
BitmapScaler class follows:
class BitmapScaler {
private static class Size {
int sample;
float scale;
}
private Bitmap scaled;
BitmapScaler(Resources resources, int resId, int newWidth)
throws IOException {
Size size = getRoughSize(resources, resId, newWidth);
roughScaleImage(resources, resId, size);
scaleImage(newWidth);
}
BitmapScaler(File file, int newWidth) throws IOException {
InputStream is = null;
try {
is = new FileInputStream(file);
Size size = getRoughSize(is, newWidth);
try {
is = new FileInputStream(file);
roughScaleImage(is, size);
scaleImage(newWidth);
} finally {
is.close();
}
} finally {
is.close();
}
}
BitmapScaler(AssetManager manager, String assetName, int newWidth)
throws IOException {
InputStream is = null;
try {
is = manager.open(assetName);
Size size = getRoughSize(is, newWidth);
try {
is = manager.open(assetName);
roughScaleImage(is, size);
scaleImage(newWidth);
} finally {
is.close();
}
} finally {
is.close();
}
}
Bitmap getScaled() {
return scaled;
}
private void scaleImage(int newWidth) {
int width = scaled.getWidth();
int height = scaled.getHeight();
float scaleWidth = ((float) newWidth) / width;
float ratio = ((float) scaled.getWidth()) / newWidth;
int newHeight = (int) (height / ratio);
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
scaled = Bitmap.createBitmap(scaled, 0, 0, width, height, matrix, true);
}
private void roughScaleImage(InputStream is, Size size) {
Matrix matrix = new Matrix();
matrix.postScale(size.scale, size.scale);
BitmapFactory.Options scaledOpts = new BitmapFactory.Options();
scaledOpts.inSampleSize = size.sample;
scaled = BitmapFactory.decodeStream(is, null, scaledOpts);
}
private void roughScaleImage(Resources resources, int resId, Size size) {
Matrix matrix = new Matrix();
matrix.postScale(size.scale, size.scale);
BitmapFactory.Options scaledOpts = new BitmapFactory.Options();
scaledOpts.inSampleSize = size.sample;
scaled = BitmapFactory.decodeResource(resources, resId, scaledOpts);
}
private Size getRoughSize(InputStream is, int newWidth) {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, o);
Size size = getRoughSize(o.outWidth, o.outHeight, newWidth);
return size;
}
private Size getRoughSize(Resources resources, int resId, int newWidth) {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeResource(resources, resId, o);
Size size = getRoughSize(o.outWidth, o.outHeight, newWidth);
return size;
}
private Size getRoughSize(int outWidth, int outHeight, int newWidth) {
Size size = new Size();
size.scale = outWidth / newWidth;
size.sample = 1;
int width = outWidth;
int height = outHeight;
int newHeight = (int) (outHeight / size.scale);
while (true) {
if (width / 2 < newWidth || height / 2 < newHeight) {
break;
}
width /= 2;
height /= 2;
size.sample *= 2;
}
return size;
}
}
http://zerocredibility.wordpress.com/2011/01/27/android-bitmap-scaling/
if you are using PNG format then it will not compress your image because PNG is a lossless format. use JPEG for compressing your your image and use 0 instead of 100 in quality.
What's the problem exactly? Doesn't your code manage to open the file ? does it crash or have you just no error, but no output file?
By the way, you should call bitmap.recycle() at the end
It could help you harry
crop-image
BitmapFactory.Options optionsSignature = new BitmapFactory.Options();
final Bitmap bitmapSignature = BitmapFactory.decodeFile(
fileUriSignature.getPath(), optionsSignature);
Bitmap resizedSignature = Bitmap.createScaledBitmap(bitmapSignature, 256, 128, true);
signature.setImageBitmap(resizedSignature);
Here is the disk cache tutorial I'm following. I've downloaded the source code to DiskLruCache but none of the methods used in this example exist in the source code.
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#disk-cache
Do I need to implement these methods myself or is there a version of DiskLruCache that I'm missing somewhere?
Here is the complete implementation of DiskLruCache.
First download DiskLruCache.java from AOSP.
Here is my DiskCache.java a helper class for basic cache operations.
/**
* Created by Babar on 12-Aug-15.
*/
public class DiskCache
{
private Context context;
private static DiskCache diskCache;
public DiskLruCache mDiskLruCache;
private final Object mDiskCacheLock = new Object();
private BitmapProcessor bitmapProcessor;
private static final int DISK_CACHE_INDEX = 0;
public static boolean mDiskCacheStarting = true;
private static final String DISK_CACHE_SUBDIR = "ooredoo_thumbnails";
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 100; // 100MB
public static DiskCache getInstance()
{
if(diskCache == null)
{
diskCache = new DiskCache();
}
return diskCache;
}
private DiskCache() {}
public void requestInit(Context context)
{
this.context = context;
bitmapProcessor = new BitmapProcessor();
new DiskCacheTask(this).execute(DiskCacheTask.INIT);
}
public void init() throws IOException {
synchronized (mDiskCacheLock)
{
if(mDiskLruCache == null || mDiskLruCache.isClosed())
{
File cacheDir = FileUtils.getDiskCacheDir(context, DISK_CACHE_SUBDIR);
if(!cacheDir.exists())
{
cacheDir.mkdir();
}
if(FileUtils.getUsableSpace(cacheDir) > DISK_CACHE_SIZE)
{
mDiskLruCache = DiskLruCache.open(cacheDir, 1, 1, DISK_CACHE_SIZE);
}
else
{
Logger.print("InitDiskCache failed: NOT enough space on disk");
}
}
mDiskCacheStarting = false; // Finished initialization
mDiskCacheLock.notifyAll(); // Wake any waiting threads
}
}
public void addBitmapToDiskCache(final String key, final Bitmap value) {
if (key == null || value == null) {
return;
}
synchronized (mDiskCacheLock)
{
if (mDiskLruCache != null) {
OutputStream out = null;
String encryptedKey = CryptoUtils.encryptToMD5(key);
Logger.print("addBitmapToDiskCache encryptToMD5: " + encryptedKey);
try {
DiskLruCache.Snapshot snapshot = mDiskLruCache.get(encryptedKey);
if (snapshot == null) {
final DiskLruCache.Editor editor = mDiskLruCache.edit(encryptedKey);
if (editor != null) {
out = editor.newOutputStream(DISK_CACHE_INDEX);
value.compress(Bitmap.CompressFormat.JPEG, 100, out);
editor.commit();
out.close();
}
} else {
snapshot.getInputStream(DISK_CACHE_INDEX).close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* Get from disk cache.
*
* #param key Unique identifier for which item to get
* #return The bitmap if found in cache, null otherwise
*/
public Bitmap getBitmapFromDiskCache(final String key)
{
Bitmap bitmap = null;
String encryptedKey = CryptoUtils.encryptToMD5(key);
Logger.print("getBitmapFromDiskCache encryptToMD5: " + encryptedKey);
synchronized (mDiskCacheLock)
{
Logger.print("mDiskcachestarting: "+mDiskCacheStarting);
// Wait while disk cache is started from background thread
while (mDiskCacheStarting)
{
try
{
mDiskCacheLock.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
if(mDiskLruCache != null)
{
InputStream inputStream = null;
try
{
final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(encryptedKey);
if(snapshot != null)
{
Logger.print("Disk cache hit");
inputStream = snapshot.getInputStream(DISK_CACHE_INDEX);
if(inputStream != null)
{
FileDescriptor fd = ((FileInputStream) inputStream).getFD();
// Decode bitmap, but we don't want to sample so give
// MAX_VALUE as the target dimensions
bitmap = bitmapProcessor.decodeSampledBitmapFromDescriptor(fd);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(inputStream != null)
{
try
{
inputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
Logger.print("dCache getBitmapFromDiskCache synchronized completed");
}
Logger.print("dCache getBitmapFromDiskCache returning Bitmap");
return bitmap;
}
public void requestFlush()
{
new DiskCacheTask(this).execute(DiskCacheTask.FLUSH);
}
/**
* Flushes the disk cache associated with this ImageCache object. Note that this includes
* disk access so this should not be executed on the main/UI thread.
*/
public void flush()
{
synchronized (mDiskCacheLock)
{
if(mDiskLruCache != null)
{
try
{
mDiskLruCache.flush();
Logger.print("flush: disk cache flushed");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
public void requestClose()
{
new DiskCacheTask(this).execute(DiskCacheTask.CLOSE);
}
/**
* Closes the disk cache associated with this ImageCache object. Note that this includes
* disk access so this should not be executed on the main/UI thread.
*/
public void close()
{
synchronized (mDiskCacheLock)
{
if(mDiskLruCache != null)
{
if(!mDiskLruCache.isClosed())
{
try
{
mDiskLruCache.close();
mDiskLruCache = null;
Logger.print("disk cache closed");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
/**
* Do not call this method unless you need to explicitly clear disk cache
*/
public void requestTearDown()
{
new DiskCacheTask(this).execute(DiskCacheTask.TEAR_DOWN);
}
public final void tearDown()
{
synchronized (mDiskCacheLock)
{
mDiskCacheStarting = true;
if(mDiskLruCache != null && !mDiskLruCache.isClosed())
{
try
{
mDiskLruCache.delete();
Logger.print("disk cache cleared");
}
catch (IOException e)
{
e.printStackTrace();
}
mDiskLruCache = null;
}
}
}
}
Here is BitmapProcesser.java
/**
* #author Babar
* #since 15-Jun-15.
*/
public class BitmapProcessor
{
public Bitmap decodeSampledBitmapFromStream(InputStream inputStream, URL url,
int reqWidth, int reqHeight) throws IOException {
Bitmap bitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, options);
int width = options.outWidth;
int height = options.outHeight;
Logger.print("#Req Width: "+reqWidth);
Logger.print("#Req Height: " + reqHeight);
Logger.print("#Actual Width: "+width);
Logger.print("#Actual Height: " + height);
int sampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;
inputStream = url.openStream();
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
if(bitmap != null)
{
width = bitmap.getWidth();
height = bitmap.getHeight();
Logger.print("#inSample:"+sampleSize);
Logger.print("#Modified Width: "+width);
Logger.print("#Modified Height: " + height);
}
return bitmap;
}
public Bitmap decodeSampledBitmapFromDescriptor(FileDescriptor fd)
{
/*final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fd, null, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;*/
return BitmapFactory.decodeFileDescriptor(fd);
}
public Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) throws IOException {
Bitmap bitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
int width = options.outWidth;
int height = options.outHeight;
Logger.print("#Req Width: "+reqWidth);
Logger.print("#Req Height: " + reqHeight);
Logger.print("#Actual Width: "+width);
Logger.print("#Actual Height: " + height);
int sampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;
bitmap = BitmapFactory.decodeFile(pathName, options);
if(bitmap != null)
{
width = bitmap.getWidth();
height = bitmap.getHeight();
Logger.print("#inSample:"+sampleSize);
Logger.print("#Modified Width: "+width);
Logger.print("#Modified Height: " + height);
}
return bitmap != null ? rotateBitmapIfNeeded(pathName, bitmap) : null;
}
public int calculateInSampleSize(BitmapFactory.Options options,
int requiredWidth, int requiredHeight)
{
final int width = options.outWidth;
final int height = options.outHeight;
int inSampleSize = 1;
if(width > requiredWidth || height > requiredHeight)
{
final int halfWidth = width / 2;
final int halfHeight = height / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfWidth / inSampleSize) > requiredWidth
&&
(halfHeight / inSampleSize) > requiredHeight)
{
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap rotateBitmapIfNeeded(String pathName, Bitmap bitmap) throws IOException {
ExifInterface exifInterface = new ExifInterface(pathName);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
Logger.logI("BITMAP_ORIENTATION: " + orientation, pathName);
switch (orientation)
{
case ExifInterface.ORIENTATION_ROTATE_90:
return rotateBitmap(bitmap, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotateBitmap(bitmap, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotateBitmap(bitmap, 270);
}
return bitmap;
}
public Bitmap makeBitmapRound(Bitmap src)
{
int width = src.getWidth();
int height = src.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
// Canvas canvas = new Canvas(bitmap);
BitmapShader shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rectF = new RectF(0.0f, 0.0f, width, height);
// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
Canvas canvas = new Canvas(src);
canvas.drawRoundRect(rectF, 30, 30, paint);
return src;
}
public static Bitmap rotateBitmap(Bitmap bitmap, int degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
}
Here is CryptoUtils.java
/**
* #author Babar
* #since 29-Jun-15.
*/
public class CryptoUtils
{
private static final String MD5_ALGO = "MD5";
public static String encryptToMD5(String text)
{
try
{
java.security.MessageDigest md = java.security.MessageDigest.getInstance(MD5_ALGO);
md.update(text.getBytes());
byte[] bytes = md.digest();
String hex = bytesToHexString(bytes);
return hex;
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
return String.valueOf(text.hashCode());
}
}
private static String bytesToHexString(byte[] bytes)
{
StringBuffer sb = new StringBuffer();
for(int i = 0; i < bytes.length; i++)
{
String hex = Integer.toHexString(0xFF & bytes[i]);
if(hex.length() == 1)
{
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
public static String encodeToBase64(String str) {
String tmp = "";
if(isNotNullOrEmpty(str)) {
try {
tmp = new String(Base64.encode(str.getBytes(), Base64.DEFAULT)).trim();
} catch(Throwable e) {
e.printStackTrace();
}
}
return tmp;
}
}
Here is DiskCacheTask.java
/**
* Created by Babar on 12-Aug-15.
*/
public class DiskCacheTask extends BaseAsyncTask<Integer, Void, Void>
{
private DiskCache diskCache;
public static final int INIT = 1;
public static final int FLUSH = 2;
public static final int CLOSE = 3;
public static final int TEAR_DOWN = 4;
public static final int REMOVE = 5;
public DiskCacheTask(DiskCache diskCache)
{
this.diskCache = diskCache;
}
#Override
protected Void doInBackground(Integer... params)
{
switch (params[0])
{
case INIT:
try
{
diskCache.init();
}
catch (IOException e)
{
e.printStackTrace();
}
break;
case FLUSH:
diskCache.flush();
break;
case CLOSE:
diskCache.close();
break;
case TEAR_DOWN:
diskCache.tearDown();
break;
case REMOVE:
diskCache.remove();
break;
}
return null;
}
}
To initialize the cache simply call new DiskCache().getInstance().requestInit(); ideally from your MainActivity's onCreate(). Also note Disk operation should be done in separate thread for example Handler , AsyncTask. So when ever you want to add/get bitmap to/from disk cache do this from a worker thread.
You will need to wrap the DiskLruCache with your own cache that offers higher level abstractions. Someone has already done this for bitmaps, see Using DiskLruCache in android 4.0 does not provide for openCache method
Alternatively, you can use an open source library such as Picasso.
when I screen shot the map. I cannot success to shot the all screen.it only show the path.
I want to know what my problem is on my code. I hope someone can help me. thank you
It is my result:
// Screen shot
private static Bitmap takeScreenShot(Activity activity) {
// View to shot View
View view = activity.getWindow().getDecorView();
//View view = getPopupViews(getDecorViews())[0];
Log.i("ABC", view.getClass().getName());
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
// the height
Rect frame = new Rect();
view.getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
System.out.println(statusBarHeight);
// width and height
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay().getHeight();
// del the state bar
// Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height - statusBarHeight);
view.destroyDrawingCache();
return b;
}
// save image to sdcard
private static void savePic(Bitmap b, String strFileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strFileName);
if (null != fos) {
b.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void shoot() {
shoot(this);
}
// call function
public static void shoot(Activity a) {
savePic(takeScreenShot(a), "data/data/com.example.map/"+number+".png");
}
try this code, and pass mapView in this
public final static Bitmap takeScreenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
private Bitmap getMapImage() {
MapController mc = mapView.getController();
mc.setCenter(GEO_POINT);
mc.setZoom(ZOOM_LEVEL);
/* Capture drawing cache as bitmap */
mapView.setDrawingCacheEnabled(true);
Bitmap bmp = Bitmap.createBitmap(mapView.getDrawingCache());
mapView.setDrawingCacheEnabled(false);
return bmp;
}
private void saveMapImage() {
String filename = "SCREEN_SHOT.png";
File f = new File(getExternalFilesDir(null), filename);
FileOutputStream out = new FileOutputStream(f);
Bitmap bmp = getMapImage();
bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
}
I'm loading the image from the url by using LoadImage method and storing it in the Bitmap object. Then I reduce its size. After getting the reduced image size I'm displaying it in the ImageView of my layout. Now I would like to know whether the image size was reduced or not. How can I check that?
public class ReduceImageActivity extends Activity {
String image_URL = "http://pennapps.com/biblioteka/images/C.jpg";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView bmImage = (ImageView) findViewById(R.id.imageView1);
BitmapFactory.Options bmOptions;
bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1;
Bitmap bm = LoadImage(image_URL, bmOptions);
getResizedBitmap(bm, 200, 200);
System.out.println("after resizing it"+bm);
bmImage.setImageBitmap(getResizedBitmap(bm, 200, 200));
}
private Bitmap LoadImage(String URL, BitmapFactory.Options options) {
Bitmap bitmap = null;
InputStream in = null;
try {
in = OpenHttpConnection(URL);
bitmap = BitmapFactory.decodeStream(in, null, options);
in.close();
} catch (IOException e1) {
}
return bitmap;
}
private InputStream OpenHttpConnection(String strURL) throws IOException {
InputStream inputStream = null;
URL url = new URL(strURL);
URLConnection conn = url.openConnection();
try {
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setRequestMethod("GET");
httpConn.connect();
if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
inputStream = httpConn.getInputStream();
}
} catch (Exception ex) {
}
return inputStream;
}
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
System.out.println("in getresizebitmap"+resizedBitmap.toString());
return resizedBitmap;
}
}
Use getWidth, getHeight as #barzos suggested. And keep in mind that call to getResizedBitmap(bm, 200, 200) does not change the original bm bitmap but rather produces a new one, so use it as following:
Bitmap bm = LoadImage(image_URL, bmOptions);
Bitmap resized = getResizedBitmap(bm, 200, 200);
System.out.println("after resizing [w: " + resized.getWidth() + ", h: " + resized.getHeight() + "]");
bmImage.setImageBitmap(resized);
This also eliminates one unnecessary call to getResizedBitmap saving CPU and memory resources.
after you reduce image size, you can check size of new ( reduced ) image by using ;
getWidth()
getHeight()
use -> resizedBitmap.getWidth(), resizedBitmap.getHeight()