/**
** Copyright (c) 2010 Ushahidi Inc
** All rights reserved
** Contact: team@ushahidi.com
** Website: http://www.ushahidi.com
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: http://www.gnu.org/licenses/lgpl.html.
**
**
** If you have questions regarding the use of this file, please contact
** Ushahidi developers at team@ushahidi.com.
**
**/
package com.ushahidi.android.app.util;
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Environment;
/**
* An Image Utility class
*
*/
public class ImageManager {
// folder to save fetched photos.
public static final String PHOTO = "/fetched";
public static final String PENDING = "/pending";
private static final int IO_BUFFER_SIZE = 512;
private static BitmapFactory.Options getBitmapFactoryOptions(
Context context, String fileName) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileName, options);
return options;
}
public static Drawable getDrawables(Context context, String fileName) {
String file = getPhotoPath(context) + fileName;
final BitmapFactory.Options options = getBitmapFactoryOptions(context,
file);
Bitmap scaled = PhotoUtils.scaleBitmap(options, file);
return new BitmapDrawable(context.getResources(), scaled);
}
public static Bitmap getBitmaps(Context context, String fileName) {
String file = getPhotoPath(context) + fileName;
final BitmapFactory.Options options = getBitmapFactoryOptions(context,
file);
// scale image
return PhotoUtils
.scaleBitmap(options, file);
}
public static Drawable getDrawables(Context context, String fileName,
int width) {
String file = getPhotoPath(context) + fileName;
final BitmapFactory.Options options = getBitmapFactoryOptions(context,
file);
// scale image
Bitmap scaled = PhotoUtils.scaleBitmapByWidth(options, width,file);
return new BitmapDrawable(context.getResources(), scaled);
}
public static Bitmap getBitmaps(Context context, String fileName, int width) {
String file = getPhotoPath(context) + fileName;
final BitmapFactory.Options options = getBitmapFactoryOptions(context,
file);
return PhotoUtils.scaleBitmapByWidth(options, width,file);
}
public static Drawable getPendingDrawables(Context context, String fileName) {
String file = getPhotoPath(context, fileName);
final BitmapFactory.Options options = getBitmapFactoryOptions(context,
file);
// scale image
Bitmap scaled = PhotoUtils.scaleBitmap(options, file);
return new BitmapDrawable(context.getResources(), scaled);
}
public static Drawable getPendingDrawables(Context context,
String fileName, int width) {
String file = getPhotoPath(context, fileName);
final BitmapFactory.Options options = getBitmapFactoryOptions(context,
file);
// scale image
Bitmap scaled = PhotoUtils.scaleBitmapByWidth(options, width, file);
return new BitmapDrawable(context.getResources(), scaled);
}
public static Drawable getThumbnails(Context context, String fileName) {
// get image
Bitmap original = BitmapFactory.decodeFile(getPhotoPath(context)
+ fileName);
if (original != null) {
// scale image
Bitmap scaled = PhotoUtils.scaleThumbnail(original);
return new BitmapDrawable(context.getResources(), scaled);
}
return null;
}
public static Bitmap getBitmapThumbnails(Context context, String fileName) {
// get image
Bitmap original = BitmapFactory.decodeFile(getPhotoPath(context)
+ fileName);
if (original != null) {
// scale image
return PhotoUtils.scaleThumbnail(original);
}
return null;
}
private static byte[] fetchImage(String address)
throws MalformedURLException, IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(new URL(address).openStream(),
IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, 4 * 1024);
copy(in, out);
out.flush();
return dataStream.toByteArray();
} catch (IOException e) {
// android.util.Log.e("IO", "Could not load buddy icon: " + this,
// e);
} finally {
closeStream(in);
closeStream(out);
}
return null;
}
/**
* Copy the content of the input stream into the output stream, using a
* temporary byte array buffer whose size is defined by
* {@link #IO_BUFFER_SIZE}.
*
* @param in
* The input stream to copy from.
* @param out
* The output stream to copy to.
* @throws IOException
* If any error occurs during the copy.
*/
private static void copy(InputStream in, OutputStream out)
throws IOException {
byte[] b = new byte[4 * 1024];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
}
/**
* Closes the specified stream.
*
* @param stream
* The stream to close.
*/
private static void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
android.util.Log.e("IO", "Could not close stream", e);
}
}
}
public static void downloadImage(String imageUrl, String filename,
Context context) {
try {
byte[] imageData = fetchImage(imageUrl);
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
imageData.length);
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 75, byteArray);
bitmap.recycle();
// create photos directory
writeImage(byteArray.toByteArray(), filename, getPhotoPath(context));
byteArray.flush();
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void writeImage(byte[] data, String filename, String path) {
deleteImage(filename, path);
if (data != null) {
FileOutputStream fOut;
try {
fOut = new FileOutputStream(new File(path, filename), false);
fOut.write(data);
fOut.flush();
fOut.close();
} catch (final FileNotFoundException e) {
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
}
}
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
public static String getSavedPhotoPath(Context context, String folder) {
// create photo directory if it doesn't exist
File path = new File(Environment.getExternalStorageDirectory(),
String.format("%s%s%s", context.getPackageName(), "/", folder));
if (!path.exists()) {
// create path if it doesn't exist
if (createDirectory(context)) {
return path.getAbsolutePath() + "/";
}
}
return path.getAbsolutePath() + "/";
}
public static String getPhotoPath(Context context) {
return getSavedPhotoPath(context, PHOTO);
}
public static String getPhotoPath(Context context, String pathfileName) {
File path = new File(Environment.getExternalStorageDirectory(),
String.format("%s%s%s", context.getPackageName(), "/",
pathfileName));
if (!path.exists()) {
return null;
}
return path.getAbsolutePath();
}
public static String getPendingPhotoPath(Context context) {
return getSavedPhotoPath(context, PENDING);
}
public static boolean deletePendingPhoto(Context context, String fileName) {
return deleteImage(getSavedPhotoPath(context, fileName));
}
public static boolean deleteImage(String path) {
File f = new File(path);
if (f.exists()) {
f.delete();
return true;
}
return false;
}
public static boolean deleteImage(String filename, String path) {
File f = new File(path, filename);
if (f.exists()) {
f.delete();
return true;
}
return false;
}
// make sure external storage is available
private static boolean isExternalStoragePresent() {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
return (mExternalStorageAvailable) && (mExternalStorageWriteable);
}
private static boolean createDirectory(Context context) {
if (isExternalStoragePresent()) {
File file = new File(Environment.getExternalStorageDirectory(),
context.getPackageName() + PHOTO);
if (!file.exists()) {
if (!file.mkdirs()) {
return false;
}
}
}
return true;
}
public static void deleteImages(Context context) {
if (isExternalStoragePresent()) {
File path = new File(Environment.getExternalStorageDirectory(),
context.getPackageName() + PHOTO);
deleteFiles(path);
}
}
public static void deletePendingImages(Context context) {
if (isExternalStoragePresent()) {
File path = new File(Environment.getExternalStorageDirectory(),
context.getPackageName() + PENDING);
deleteFiles(path);
}
}
private static boolean deleteFiles(File path) {
if (path.exists()) {
File[] files = path.listFiles();
if (files == null) {
return false;
}
// go through the folder and delete its content
for (int i = 0; i < files.length; i++) {
files[i].delete();
}
}
return true;
}
public static void movePendingPhotos(Context context) {
File[] pendingPhotos = PhotoUtils.getPendingPhotos(context);
if (pendingPhotos != null && pendingPhotos.length > 0) {
for (File file : pendingPhotos) {
if (file.exists()) {
// move file
if (file.renameTo(new File(getPhotoPath(context)
+ file.getName()))) {
// delete after a successful move
file.delete();
}
}
}
}
}
}