com.mappn.gfan.common.util.ImageUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.mappn.gfan.common.util.ImageUtils.java

Source

/*
 * Copyright (C) 2010 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mappn.gfan.common.util;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.os.AsyncTask;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.ImageView;

import com.mappn.gfan.R;
import com.mappn.gfan.common.AndroidHttpClient;
import com.mappn.gfan.common.HttpClientFactory;
import com.mappn.gfan.common.widget.LoadingDrawable;

/**
 * ??
 * 
 * @author andrew
 * @date 2011-3-21
 * 
 */
public class ImageUtils {

    public static Bitmap getImageFromUrl(String url) {

        //        SessionManager cache = SessionManager.getInstance();

        HttpGet httpRequest = new HttpGet(url);
        HttpResponse response = null;
        AndroidHttpClient client = HttpClientFactory.get().getHttpClient();
        try {
            response = client.execute(httpRequest);
            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
                return null;
            }
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = null;
                try {
                    inputStream = entity.getContent();
                    // non-compressed images no need to be cached to the sd-card
                    BitmapFactory.Options o = new BitmapFactory.Options();
                    o.inPurgeable = true;
                    Bitmap bmp = BitmapFactory.decodeStream(new FlushedInputStream(inputStream), null, o);
                    //                    cache.saveToDisk(url, bmp);
                    return bmp;
                } finally {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    entity.consumeContent();
                }
            }
        } catch (ClientProtocolException e) {
            Log.w("ImageDownloader", "ClientProtocolException " + url);
        } catch (IOException e) {
            Log.w("ImageDownloader", "IOException " + url);
        } catch (Exception e) {
            Log.w("ImageDownloader", "other exception when download images from " + url);
        } catch (OutOfMemoryError err) {
            Log.w("ImageDownloader", "OutOfMemoryError when download images from " + url);
        } finally {
            httpRequest.abort();
        }
        return null;
    }

    private static final int TYPE_NORAML = 1;
    private static final int TYPE_IMAGE = 2;
    private static final int TYPE_SCREENSHOT = 3;
    private static final int TYPE_TOP = 4;

    static class BitmapDownloaderTask extends AsyncTask<Object, Void, Bitmap> {
        private Context context;
        private String url;
        private final WeakReference<ImageView> imageViewReference;
        private int type;
        CacheManager cache = CacheManager.getInstance();

        public BitmapDownloaderTask(ImageView imageView) {
            imageViewReference = new WeakReference<ImageView>(imageView);
        }

        @Override
        // Actual download method, run in the task thread
        protected Bitmap doInBackground(Object... params) {
            // params comes from the execute() call: params[0] is the url.
            context = (Context) params[0];
            url = (String) params[1];
            type = (Integer) params[2];

            Bitmap bmp = getImageFromUrl(url);
            if (bmp != null && type != TYPE_IMAGE && type != TYPE_SCREENSHOT) {
                cache.cacheDrawable(url, bmp);
            }
            return bmp;
        }

        @Override
        // Once the image is downloaded, associates it to the imageView
        protected void onPostExecute(Bitmap bitmap) {
            if (isCancelled()) {
                bitmap = null;
            }

            if (imageViewReference != null) {
                ImageView imageView = imageViewReference.get();
                BitmapDownloaderTask bitmapDownloaderTask = null;
                if (type == TYPE_IMAGE) {
                    bitmapDownloaderTask = getBitmapDownloaderTask2(imageView);
                } else {
                    bitmapDownloaderTask = getBitmapDownloaderTask1(imageView);
                }

                // Change bitmap only if this process is still associated with
                // it
                if (this == bitmapDownloaderTask && bitmap != null) {
                    if (type == TYPE_IMAGE) {
                        imageView.setBackgroundDrawable(null);
                        imageView.setImageBitmap(rotateImage(bitmap));
                    } else if (type == TYPE_SCREENSHOT) {
                        imageView.setImageBitmap(rotateImage(bitmap));
                    } else if (type == TYPE_TOP) {
                        BitmapDrawable background = new BitmapDrawable(bitmap);
                        StateListDrawable foreground = getMaskDrawable(context);
                        imageView.setImageDrawable(foreground);
                        imageView.setBackgroundDrawable(background);
                    } else {
                        imageView.setImageBitmap(bitmap);
                    }
                }
            }
        }
    }

    static class DownloadedDrawable1 extends BitmapDrawable {
        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference1;

        public DownloadedDrawable1(Drawable defaultBitmap, BitmapDownloaderTask bitmapDownloaderTask) {
            super(((BitmapDrawable) defaultBitmap).getBitmap());
            bitmapDownloaderTaskReference1 = new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference1.get();
        }
    }

    static class DownloadedDrawable2 extends AnimationDrawable {
        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference2;

        public DownloadedDrawable2(Drawable defaultAnimation, BitmapDownloaderTask bitmapDownloaderTask) {
            AnimationDrawable drawable = ((AnimationDrawable) defaultAnimation);
            final int frameCounter = drawable.getNumberOfFrames();
            for (int i = 0; i < frameCounter; i++) {
                super.addFrame(drawable.getFrame(i), drawable.getDuration(i));
            }
            super.setOneShot(false);
            bitmapDownloaderTaskReference2 = new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference2.get();
        }
    }

    // fetch normal task
    private static BitmapDownloaderTask getBitmapDownloaderTask1(ImageView imageView) {
        if (imageView != null) {
            Drawable drawable = imageView.getDrawable();
            if (drawable == null || !(drawable instanceof DownloadedDrawable1)) {
                return null;
            }
            DownloadedDrawable1 downloadedDrawable = (DownloadedDrawable1) drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
        return null;
    }

    // fetch animation task
    private static BitmapDownloaderTask getBitmapDownloaderTask2(ImageView imageView) {
        if (imageView != null) {
            Drawable drawable = imageView.getBackground();
            if (drawable == null || !(drawable instanceof DownloadedDrawable2)) {
                return null;
            }
            DownloadedDrawable2 downloadedDrawable = (DownloadedDrawable2) drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
        return null;
    }

    /**
     * ?ICON
     */
    public static void download(Context context, String url, ImageView imageView) {

        CacheManager cache = CacheManager.getInstance();
        if (cache.existsDrawable(url)) {
            imageView.setImageBitmap(cache.getDrawableFromCache(url));
            return;
        }

        Drawable defaultDrawable = context.getResources().getDrawable(R.drawable.loading_icon);
        if (cancelPotentialBitmapDownload(url, imageView)) {
            BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
            DownloadedDrawable1 downloadedDrawable = new DownloadedDrawable1(defaultDrawable, task);
            imageView.setImageDrawable(downloadedDrawable);
            task.execute(context, url, TYPE_NORAML);
        }
    }

    /**
     * ??
     */
    public static void downloadHomeTopDrawable(Context context, String url, ImageView imageView) {

        CacheManager cache = CacheManager.getInstance();
        if (cache.existsDrawable(url)) {
            BitmapDrawable background = new BitmapDrawable(cache.getDrawableFromCache(url));
            StateListDrawable foreground = getMaskDrawable(context);
            imageView.setImageDrawable(foreground);
            imageView.setBackgroundDrawable(background);
            return;
        }

        Drawable defaultDrawable = context.getResources().getDrawable(R.drawable.banner_loading);
        if (cancelPotentialBitmapDownload(url, imageView)) {
            BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
            DownloadedDrawable1 downloadedDrawable = new DownloadedDrawable1(defaultDrawable, task);
            imageView.setImageDrawable(downloadedDrawable);
            task.execute(context, url, TYPE_TOP);
        }
    }

    /**
     * ?
     */
    public static void downloadDeatilScreenshot(Context context, String url, ImageView imageView) {

        Drawable defaultDrawable = new BitmapDrawable();
        if (cancelPotentialBitmapDownload(url, imageView)) {
            BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
            DownloadedDrawable1 downloadedDrawable = new DownloadedDrawable1(defaultDrawable, task);
            imageView.setImageDrawable(downloadedDrawable);
            task.execute(context, url, TYPE_SCREENSHOT);
        }
    }

    /**
     * 
     */
    public static void downloadScreenShot(Context context, String url, ImageView imageView) {

        AnimationDrawable loadingDrawable = new LoadingDrawable(context);
        if (cancelPotentialImageDownload(url, imageView)) {
            BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);

            DownloadedDrawable2 downloadedDrawable = new DownloadedDrawable2(loadingDrawable, task);
            // clear the old image
            imageView.setImageDrawable(null);
            imageView.setBackgroundDrawable(downloadedDrawable);
            downloadedDrawable.start();
            task.execute(context, url, TYPE_IMAGE);
        }
    }

    private static boolean cancelPotentialBitmapDownload(String url, ImageView imageView) {
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask1(imageView);

        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                // The same URL is already being downloaded.
                return false;
            }
        }
        return true;
    }

    private static boolean cancelPotentialImageDownload(String url, ImageView imageView) {
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask2(imageView);

        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                // The same URL is already being downloaded.
                return false;
            }
        }
        return true;
    }

    /**
     * ?? 
     */
    private static StateListDrawable getMaskDrawable(Context context) {
        StateListDrawable stateDrawable = new StateListDrawable();
        int statePressed = android.R.attr.state_pressed;
        final Resources res = context.getResources();
        stateDrawable.addState(new int[] { statePressed },
                new BitmapDrawable(res, BitmapFactory.decodeResource(res, R.drawable.banner_pressed)));
        return stateDrawable;
    }

    /**
     * ???
     */
    public static Bitmap rotateImage(Bitmap bmp) {

        if (bmp == null)
            return bmp;

        int width = bmp.getWidth();
        int height = bmp.getHeight();
        float aspectRatio = ((float) height) / width;

        if (aspectRatio > 1) {
            // no need to rotate the image
            return bmp;
        }

        Matrix matrix = new Matrix();
        matrix.postRotate(90);
        Bitmap rotatedBitmap = null;
        try {
            rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix, false);
        } catch (OutOfMemoryError e) {
        }
        return rotatedBitmap;
    }

    /**
     * ??? 
     */
    public static Bitmap sacleBitmap(Context context, Bitmap bitmap) {
        // ???
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        int screenWidth = metrics.widthPixels;
        float aspectRatio = (float) screenWidth / (float) width;
        int scaledHeight = (int) (height * aspectRatio);
        Bitmap scaledBitmap = null;
        try {
            scaledBitmap = Bitmap.createScaledBitmap(bitmap, screenWidth, scaledHeight, false);
        } catch (OutOfMemoryError e) {
        }
        return scaledBitmap;
    }
}

class FlushedInputStream extends FilterInputStream {
    public FlushedInputStream(InputStream inputStream) {
        super(inputStream);
    }

    @Override
    public long skip(long n) throws IOException {
        long totalBytesSkipped = 0L;
        while (totalBytesSkipped < n) {
            long bytesSkipped = in.skip(n - totalBytesSkipped);
            if (bytesSkipped == 0L) {
                int byteRead = read();
                if (byteRead < 0) {
                    break; // we reached EOF
                } else {
                    bytesSkipped = 1; // we read one byte
                }
            }

            totalBytesSkipped += bytesSkipped;
        }
        return totalBytesSkipped;
    }
}