package uni.projecte.ui;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import uni.projecte.dataLayer.dataStructures.ImageCache;
import uni.projecte.dataLayer.utils.PhotoUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.ExifInterface;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ViewSwitcher;
public class ImageLoader extends Thread {
public interface ImageLoadListener {
void handleImageLoaded(ViewSwitcher aViewSwitcher, ImageView aImageView, Bitmap aBitmap);
}
private static final String TAG = ImageLoader.class.getSimpleName();
ImageLoadListener mListener = null;
private Handler handler;
private ImageCache imageCache;
private int thMaxSize;
/**
* Image loader takes an object that extends ImageLoadListener
* @param lListener
* @param imageCache
* @param thMaxSize
*/
ImageLoader(ImageLoadListener lListener, ImageCache imageCache, int thMaxSize){
mListener = lListener;
this.imageCache=imageCache;
this.thMaxSize=thMaxSize;
}
@Override
public void run() {
try {
// preparing a looper on current thread
// the current thread is being detected implicitly
Looper.prepare();
// Looper gets attached to the current thread by default
handler = new Handler();
Looper.loop();
// Thread will start
} catch (Throwable t) {
Log.e(TAG, "ImageLoader halted due to a error: ", t);
}
}
/**
* Method stops the looper and thus the thread
*/
public synchronized void stopThread() {
// Use the handler to schedule a quit on the looper
handler.post(new Runnable() {
public void run() {
// This runs on the ImageLoader thread
Log.i(TAG, "DownloadThread loop quitting by request");
Looper.myLooper().quit();
}
});
}
/**
* Method queues the image at path to load
* Note that the actual loading takes place in the UI thread
* the ImageView and ViewSwitcher are just references for the
* UI thread.
* @param aPath - Path where the bitmap is located to load
* @param aImageView - The ImageView the UI thread will load
* @param aViewSwitcher - The ViewSwitcher that needs to display the imageview
*/
public synchronized void queueImageLoad(
final String aPath,
final ImageView aImageView,
final ViewSwitcher aViewSwitcher) {
// Wrap DownloadTask into another Runnable to track the statistics
if(handler!=null){
handler.post(new Runnable() {
public void run() {
try {
synchronized (aImageView){
// make sure this thread is the only one performing activities on this imageview
File originalImage=new File(aPath);
if(originalImage.exists()){
int maxSize;
File thumb=new File(aPath.replace("/Photos/", "/Photos/thumbs/"));
Bitmap squared=null;
if(thumb.exists()){
Log.i("Images","Loading thumbnail: "+aPath);
squared=BitmapFactory.decodeFile(aPath.replace("/Photos/", "/Photos/thumbs/"), new BitmapFactory.Options());
}
else{
Bitmap lBitmap = PhotoUtils.decodeBitmap(aPath, thMaxSize,false);
if(lBitmap==null){
Log.i("Images","Wrong file: "+aPath);
squared=createWrongImageBitmap(thMaxSize);
}
else{
Log.i("Images","Decoding size("+lBitmap.getWidth()+"[w]/"+lBitmap.getHeight()+"[h]): "+aPath);
if(lBitmap.getWidth()>lBitmap.getHeight()) maxSize=lBitmap.getHeight();
else maxSize=lBitmap.getWidth();
squared=PhotoUtils.cropBitmap(lBitmap,aPath, maxSize, maxSize);
thumb.createNewFile();
FileOutputStream out = new FileOutputStream(thumb.getAbsoluteFile());
squared.compress(Bitmap.CompressFormat.JPEG, 90, out);
lBitmap.recycle();
}
}
// Load the image here
signalUI(aViewSwitcher, aImageView, squared);
imageCache.addBitmapToMemoryCache(aPath, squared);
}
else{
Bitmap bm=createWrongImageBitmap(thMaxSize);
signalUI(aViewSwitcher, aImageView, bm);
imageCache.addBitmapToMemoryCache(aPath, bm);
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
});
}
}
private Bitmap createWrongImageBitmap(int width){
Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap bitmap = Bitmap.createBitmap(width, width,Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
paint.setColor(Color.argb(0xff, 0x88, 0xaa, 0x00));
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(1);
paint.setTextSize(14);
c.drawColor(Color.BLACK);
c.drawText("Foto incorrecta", thMaxSize/4, thMaxSize/2, paint);
return bitmap;
}
/**
* Method is called when the bitmap is loaded. The UI thread adds the bitmap to the imageview.
* @param aViewSwitcher - The ViewSwitcher that needs to display the imageview
* @param aImageView - The ImageView the UI thread will load
* @param aImage - The Bitmap that gets loaded into the ImageView
*/
public void signalUI( ViewSwitcher aViewSwitcher, ImageView aImageView, Bitmap aImage){
if(mListener != null){
// we have an object that implements ImageLoadListener
mListener.handleImageLoaded(aViewSwitcher, aImageView, aImage);
}
}
}