package cz.destil.glasquare.util;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.FileObserver;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
* Utils for manipulating with images.
*
* @author David 'Destil' Vavra (david@vavra.me)
*/
public class ImageUtils {
private static final int TARGET_WIDTH = 960; // in pixels
public static File resize(File original) {
// get info about dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(original.getAbsolutePath(), options);
int targetHeight = (int) (options.outHeight / ((double) options.outWidth / (double) TARGET_WIDTH));
options.inSampleSize = calculateInSampleSize(options);
// resize image
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(original.getAbsolutePath(), options);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, TARGET_WIDTH, targetHeight, true);
bitmap.recycle();
// save scaled image to a file
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(original);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
} catch (FileNotFoundException e) {
DebugLog.e(e);
} finally {
IO.close(outputStream);
scaledBitmap.recycle();
}
return original;
}
private static int calculateInSampleSize(BitmapFactory.Options options) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (width > TARGET_WIDTH) {
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 ((halfWidth / inSampleSize) > TARGET_WIDTH) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static void processPictureWhenReady(final Activity activity, final File picture, final OnPictureReadyListener listener) {
if (picture.exists()) {
// The picture is ready; process it.
listener.onPictureReady();
} else {
// The file does not exist yet. Before starting the file observer, you
// can update your UI to let the user know that the application is
// waiting for the picture (for example, by displaying the thumbnail
// image and a progress indicator).
final File parentDirectory = picture.getParentFile();
FileObserver observer = new FileObserver(parentDirectory.getPath()) {
// Protect against additional pending events after CLOSE_WRITE is
// handled.
private boolean isFileWritten;
@Override
public void onEvent(int event, String path) {
if (!isFileWritten) {
// For safety, make sure that the file that was created in
// the directory is actually the one that we're expecting.
File affectedFile = new File(parentDirectory, path);
isFileWritten = (event == FileObserver.CLOSE_WRITE
&& affectedFile.equals(picture));
if (isFileWritten) {
stopWatching();
// Now that the file is ready, recursively call
// processPictureWhenReady again (on the UI thread).
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
processPictureWhenReady(activity, picture, listener);
}
});
}
}
}
};
observer.startWatching();
}
}
public interface OnPictureReadyListener {
public void onPictureReady();
}
}