Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c1b4c64 authored by Ruben Brunk's avatar Ruben Brunk
Browse files

Refactoring ImageLoader.

- Moves state (history, loadlisteners, bitmaps, etc.)
  from ImageLoader to MasterImage.
- Makes ImageLoader into a utility class.

Change-Id: I7a8a988c61848694a86a4b2919bf8f30bfd2be8c
parent 860dfcfa
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ public class EditorPlaceHolder {
    private FrameLayout mContainer = null;
    private HashMap<Integer, Editor> mEditors = new HashMap<Integer, Editor>();
    private Vector<ImageShow> mOldViews = new Vector<ImageShow>();
    private ImageLoader mImageLoader = null;

    public EditorPlaceHolder(FilterShowActivity activity) {
        mActivity = activity;
@@ -47,7 +46,7 @@ public class EditorPlaceHolder {

        try {
            editor.createEditor(mActivity, mContainer);
            editor.setImageLoader(mImageLoader);
            editor.getImageShow().bindAsImageLoadListener();
            mContainer.setVisibility(View.VISIBLE);
            mContainer.removeAllViews();
            View eview = editor.getTopLevelView();
@@ -81,10 +80,6 @@ public class EditorPlaceHolder {
        }
    }

    public void setImageLoader(ImageLoader imageLoader) {
        mImageLoader = imageLoader;
    }

    public Editor getEditor(int editorId) {
        return mEditors.get(editorId);
    }
+31 −20
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -27,6 +28,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
@@ -111,7 +113,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL

    public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
    public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
    private ImageLoader mImageLoader = null;
    private ImageShow mImageShow = null;

    private View mSaveButton = null;
@@ -251,7 +252,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL

        mEditorPlaceHolder.hide();

        mImageShow.setImageLoader(mImageLoader);
        mImageShow.bindAsImageLoadListener();

        fillFx();
        fillBorders();
@@ -262,7 +263,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    }

    public void setupStatePanel() {
        mImageLoader.setHistoryManager(mMasterImage.getHistory());
        MasterImage.getImage().setHistoryManager(mMasterImage.getHistory());
    }

    private void fillFilters() {
@@ -330,7 +331,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
        EditorManager.addEditors(mEditorPlaceHolder);
        mEditorPlaceHolder.setOldViews(mImageViews);
        mEditorPlaceHolder.setImageLoader(mImageLoader);

    }

    private void fillEditors() {
@@ -498,16 +499,29 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    private class LoadHighresBitmapTask extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected Boolean doInBackground(Void... params) {
            mImageLoader.loadHighResBitmap();
            MasterImage master = MasterImage.getImage();
            Rect originalBounds = master.getOriginalBounds();
            if (master.supportsHighRes()) {
                int highresPreviewSize = master.getOriginalBitmapLarge().getWidth() * 2;
                if (highresPreviewSize > originalBounds.width()) {
                    highresPreviewSize = originalBounds.width();
                }
                Bitmap originalHires = ImageLoader.loadOrientedScaledBitmap(master,
                        master.getActivity(), master.getUri(), highresPreviewSize, false,
                        master.getOrientation());
                master.setOriginalBitmapHighres(originalHires);
                master.warnListeners();
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            Bitmap highresBitmap = mImageLoader.getOriginalBitmapHighres();
            Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres();
            if (highresBitmap != null) {
                FilteringPipeline pipeline = FilteringPipeline.getPipeline();
                float highResPreviewScale = (float) highresBitmap.getWidth() / (float) mImageLoader.getOriginalBounds().width();
                float highResPreviewScale = (float) highresBitmap.getWidth()
                        / (float) MasterImage.getImage().getOriginalBounds().width();
                pipeline.setHighResPreviewScaleFactor(highResPreviewScale);
            }
        }
@@ -522,10 +536,10 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL

        @Override
        protected Boolean doInBackground(Uri... params) {
            if (!mImageLoader.loadBitmap(params[0], mBitmapSize)) {
            if (!MasterImage.getImage().loadBitmap(params[0], mBitmapSize)) {
                return false;
            }
            publishProgress(mImageLoader.queryLightCycle360());
            publishProgress(ImageLoader.queryLightCycle360(MasterImage.getImage().getActivity()));
            return true;
        }

@@ -560,10 +574,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
            final View imageShow = findViewById(R.id.imageShow);
            imageShow.setVisibility(View.VISIBLE);

            Bitmap largeBitmap = mImageLoader.getOriginalBitmapLarge();
            Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge();
            FilteringPipeline pipeline = FilteringPipeline.getPipeline();
            pipeline.setOriginal(largeBitmap);
            float previewScale = (float) largeBitmap.getWidth() / (float) mImageLoader.getOriginalBounds().width();
            float previewScale = (float) largeBitmap.getWidth()
                    / (float) MasterImage.getImage().getOriginalBounds().width();
            pipeline.setPreviewScaleFactor(previewScale);
            if (!mShowingTinyPlanet) {
                mCategoryFiltersAdapter.removeTinyPlanet();
@@ -698,7 +713,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setType(SharedImageProvider.MIME_TYPE);
        mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri());
        mSharedOutputFile = SaveCopyTask.getNewFile(this, MasterImage.getImage().getUri());
        Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
                Uri.encode(mSharedOutputFile.getAbsolutePath()));
        intent.putExtra(Intent.EXTRA_STREAM, uri);
@@ -752,16 +767,16 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        }
        FiltersManager.setResources(getResources());
        if (!mLoading) {
            Bitmap largeBitmap = mImageLoader.getOriginalBitmapLarge();
            Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge();
            FilteringPipeline pipeline = FilteringPipeline.getPipeline();
            pipeline.setOriginal(largeBitmap);
            float previewScale = (float) largeBitmap.getWidth() /
                    (float) mImageLoader.getOriginalBounds().width();
                    (float) MasterImage.getImage().getOriginalBounds().width();
            pipeline.setPreviewScaleFactor(previewScale);
            Bitmap highresBitmap = mImageLoader.getOriginalBitmapHighres();
            Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres();
            if (highresBitmap != null) {
                float highResPreviewScale = (float) highresBitmap.getWidth() /
                        (float) mImageLoader.getOriginalBounds().width();
                        (float) MasterImage.getImage().getOriginalBounds().width();
                pipeline.setHighResPreviewScaleFactor(highResPreviewScale);
            }
            pipeline.turnOnPipeline(true);
@@ -847,8 +862,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    public void setDefaultPreset() {
        // Default preset (original)
        ImagePreset preset = new ImagePreset(); // empty
        preset.setImageLoader(mImageLoader);

        mMasterImage.setPreset(preset, preset.getLastRepresentation(), true);
    }

@@ -905,7 +918,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
    }

    public void setupMasterImage() {
        mImageLoader = new ImageLoader(this, getApplicationContext());

        HistoryManager historyManager = new HistoryManager();
        StateAdapter imageStateAdapter = new StateAdapter(this, 0);
@@ -914,7 +926,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
        mMasterImage.setHistoryManager(historyManager);
        mMasterImage.setStateAdapter(imageStateAdapter);
        mMasterImage.setActivity(this);
        mMasterImage.setImageLoader(mImageLoader);

        if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) {
            mMasterImage.setSupportsHighRes(true);
+39 −168
Original line number Diff line number Diff line
@@ -32,12 +32,9 @@ import android.util.Log;

import com.adobe.xmp.XMPException;
import com.adobe.xmp.XMPMeta;
import com.android.gallery3d.R;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.history.HistoryManager;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import com.android.gallery3d.filtershow.tools.SaveCopyTask;
@@ -47,24 +44,10 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import java.util.concurrent.locks.ReentrantLock;


// TODO: this class has waaaay to much bitmap copying.  Cleanup.
public class ImageLoader {
public final class ImageLoader {

    private static final String LOGTAG = "ImageLoader";
    private final Vector<ImageShow> mListeners = new Vector<ImageShow>();
    private Bitmap mOriginalBitmapSmall = null;
    private Bitmap mOriginalBitmapLarge = null;
    private Bitmap mOriginalBitmapHighres = null;
    private Bitmap mBackgroundBitmap = null;

    private int mOrientation = 0;
    private HistoryManager mHistoryManager = null;

    private FilterShowActivity mActivity = null;

    public static final String JPEG_MIME_TYPE = "image/jpeg";

@@ -81,65 +64,11 @@ public class ImageLoader {
    public static final int ORI_TRANSVERSE = ExifInterface.Orientation.LEFT_BOTTOM;

    private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5;
    private Context mContext = null;
    private Uri mUri = null;

    private Rect mOriginalBounds = null;
    private static int mZoomOrientation = ORI_NORMAL;

    static final int MAX_BITMAP_DIM = 900;
    static final int SMALL_BITMAP_DIM = 160;

    private ReentrantLock mLoadingLock = new ReentrantLock();

    public ImageLoader(FilterShowActivity activity, Context context) {
        mActivity = activity;
        mContext = context;
    }

    public static int getZoomOrientation() {
        return mZoomOrientation;
    }
    public static final int MAX_BITMAP_DIM = 900;
    public static final int SMALL_BITMAP_DIM = 160;

    public FilterShowActivity getActivity() {
        return mActivity;
    }

    public void loadHighResBitmap() {
        if (MasterImage.getImage().supportsHighRes()) {
            int highresPreviewSize = mOriginalBitmapLarge.getWidth() * 2;
            if (highresPreviewSize > mOriginalBounds.width()) {
                highresPreviewSize = mOriginalBounds.width();
            }
            mOriginalBitmapHighres = loadScaledBitmap(mUri, highresPreviewSize, false);
            if (mOrientation > 1 && mOriginalBitmapHighres != null) {
                mOriginalBitmapHighres = rotateToPortrait(mOriginalBitmapHighres, mOrientation);
            }
            warnListeners();
        }
    }

    public boolean loadBitmap(Uri uri, int size) {
        mLoadingLock.lock();
        mUri = uri;
        mOrientation = getOrientation(mContext, uri);
        mOriginalBitmapLarge = loadScaledBitmap(uri, size);
        if (mOriginalBitmapLarge == null) {
            mLoadingLock.unlock();
            return false;
        }
        updateBitmaps();
        mLoadingLock.unlock();
        return true;
    }

    public Uri getUri() {
        return mUri;
    }

    public Rect getOriginalBounds() {
        return mOriginalBounds;
    }
    private ImageLoader() {}

    public static int getOrientation(Context context, Uri uri) {
        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
@@ -149,7 +78,6 @@ public class ImageLoader {
            }
            String path = uri.getPath();
            int orientation = -1;
            InputStream is = null;
            ExifInterface exif = new ExifInterface();
            try {
                exif.readExif(path);
@@ -194,22 +122,11 @@ public class ImageLoader {
        }
    }

    private void updateBitmaps() {
        if (mOrientation > 1) {
            mOriginalBitmapLarge = rotateToPortrait(mOriginalBitmapLarge, mOrientation);
        }
        int sw = SMALL_BITMAP_DIM;
        int sh = (int) (sw * (float) mOriginalBitmapLarge.getHeight() / (float) mOriginalBitmapLarge.getWidth());
        mOriginalBitmapSmall = Bitmap.createScaledBitmap(mOriginalBitmapLarge, sw, sh, true);
        mZoomOrientation = mOrientation;
        warnListeners();
    }

    public Bitmap decodeImage(int id, BitmapFactory.Options options) {
        return BitmapFactory.decodeResource(mContext.getResources(), id, options);
    public static Bitmap decodeImage(Context context, int id, BitmapFactory.Options options) {
        return BitmapFactory.decodeResource(context.getResources(), id, options);
    }

    public static Bitmap rotateToPortrait(Bitmap bitmap, int ori) {
    public static Bitmap orientBitmap(Bitmap bitmap, int ori) {
        Matrix matrix = new Matrix();
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
@@ -254,10 +171,11 @@ public class ImageLoader {
                bitmap.getHeight(), matrix, true);
    }

    private Bitmap loadRegionBitmap(Uri uri, BitmapFactory.Options options, Rect bounds) {
    private static Bitmap loadRegionBitmap(Context context, Uri uri, BitmapFactory.Options options,
            Rect bounds) {
        InputStream is = null;
        try {
            is = mContext.getContentResolver().openInputStream(uri);
            is = context.getContentResolver().openInputStream(uri);
            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
            Rect r = new Rect(0, 0, decoder.getWidth(), decoder.getHeight());
            // return null if bounds are not entirely within the bitmap
@@ -275,14 +193,20 @@ public class ImageLoader {
        return null;
    }

    private Bitmap loadScaledBitmap(Uri uri, int size) {
        return loadScaledBitmap(uri, size, true);
    public static Bitmap loadOrientedScaledBitmap(MasterImage master, Context context, Uri uri,
            int size, boolean enforceSize, int orientation) {
        Bitmap bmap = loadScaledBitmap(master, context, uri, size, enforceSize);
        if (bmap != null) {
            bmap = orientBitmap(bmap, orientation);
        }
        return bmap;
    }

    private Bitmap loadScaledBitmap(Uri uri, int size, boolean enforceSize) {
    public static Bitmap loadScaledBitmap(MasterImage master, Context context, Uri uri, int size,
            boolean enforceSize) {
        InputStream is = null;
        try {
            is = mContext.getContentResolver().openInputStream(uri);
            is = context.getContentResolver().openInputStream(uri);
            Log.v(LOGTAG, "loading uri " + uri.getPath() + " input stream: "
                    + is);
            BitmapFactory.Options o = new BitmapFactory.Options();
@@ -292,7 +216,7 @@ public class ImageLoader {
            int width_tmp = o.outWidth;
            int height_tmp = o.outHeight;

            mOriginalBounds = new Rect(0, 0, width_tmp, height_tmp);
            master.setOriginalBounds(new Rect(0, 0, width_tmp, height_tmp));

            int scale = 1;
            while (true) {
@@ -317,7 +241,7 @@ public class ImageLoader {
            o2.inMutable = true;

            Utils.closeSilently(is);
            is = mContext.getContentResolver().openInputStream(uri);
            is = context.getContentResolver().openInputStream(uri);
            return BitmapFactory.decodeStream(is, null, o2);
        } catch (FileNotFoundException e) {
            Log.e(LOGTAG, "FileNotFoundException: " + uri);
@@ -329,53 +253,8 @@ public class ImageLoader {
        return null;
    }

    public Bitmap getBackgroundBitmap(Resources resources) {
        if (mBackgroundBitmap == null) {
            mBackgroundBitmap = BitmapFactory.decodeResource(resources,
                    R.drawable.filtershow_background);
        }
        return mBackgroundBitmap;

    }

    public Bitmap getOriginalBitmapSmall() {
        return mOriginalBitmapSmall;
    }

    public Bitmap getOriginalBitmapLarge() {
        return mOriginalBitmapLarge;
    }

    public Bitmap getOriginalBitmapHighres() {
        return mOriginalBitmapHighres;
    }

    public void addListener(ImageShow imageShow) {
        mLoadingLock.lock();
        if (!mListeners.contains(imageShow)) {
            mListeners.add(imageShow);
        }
        mLoadingLock.unlock();
    }

    private void warnListeners() {
        mActivity.runOnUiThread(mWarnListenersRunnable);
    }

    private Runnable mWarnListenersRunnable = new Runnable() {

        @Override
        public void run() {
            for (int i = 0; i < mListeners.size(); i++) {
                ImageShow imageShow = mListeners.elementAt(i);
                imageShow.imageLoaded();
            }
            MasterImage.getImage().invalidatePreview();
        }
    };

    public Bitmap getScaleOneImageForPreset(Rect bounds, Rect destination) {
        mLoadingLock.lock();
    public static Bitmap getScaleOneImageForPreset(Context context, Uri uri, Rect bounds,
            Rect destination) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inMutable = true;
        if (destination != null) {
@@ -389,15 +268,15 @@ public class ImageLoader {
                options.inSampleSize = sampleSize;
            }
        }
        Bitmap bmp = loadRegionBitmap(mUri, options, bounds);
        mLoadingLock.unlock();
        Bitmap bmp = loadRegionBitmap(context, uri, options, bounds);
        return bmp;
    }

    public void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity,
    public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity,
            File destination) {
        Uri selectedImageUri = filterShowActivity.getSelectedImageUri();
        new SaveCopyTask(mContext, mUri, selectedImageUri, destination,
        new SaveCopyTask(filterShowActivity, MasterImage.getImage().getUri(), selectedImageUri,
                destination,
                new SaveCopyTask.Callback() {

                    @Override
@@ -424,7 +303,7 @@ public class ImageLoader {
            return null;
        }
        int orientation = ImageLoader.getOrientation(context, sourceUri);
        bitmap = ImageLoader.rotateToPortrait(bitmap, orientation);
        bitmap = ImageLoader.orientBitmap(bitmap, orientation);
        return bitmap;
    }

@@ -503,17 +382,10 @@ public class ImageLoader {
        return bmap;
    }

    public void setHistoryManager(HistoryManager historyManager) {
        mHistoryManager = historyManager;
    }

    public HistoryManager getHistory() {
        return mHistoryManager;
    }

    public XMPMeta getXmpObject() {
    public static XMPMeta getXmpObject(Context context) {
        try {
            InputStream is = mContext.getContentResolver().openInputStream(getUri());
            InputStream is = context.getContentResolver().openInputStream(
                    MasterImage.getImage().getUri());
            return XmpUtilHelper.extractXMPMeta(is);
        } catch (FileNotFoundException e) {
            return null;
@@ -525,15 +397,14 @@ public class ImageLoader {
     *
     * @return true if it is a light Cycle image that is full 360
     */
    public boolean queryLightCycle360() {
    public static boolean queryLightCycle360(Context context) {
        InputStream is = null;
        try {
            is = mContext.getContentResolver().openInputStream(getUri());
            is = context.getContentResolver().openInputStream(MasterImage.getImage().getUri());
            XMPMeta meta = XmpUtilHelper.extractXMPMeta(is);
            if (meta == null) {
                return false;
            }
            String name = meta.getPacketHeader();
            String namespace = "http://ns.google.com/photos/1.0/panorama/";
            String cropWidthName = "GPano:CroppedAreaImageWidthPixels";
            String fullWidthName = "GPano:FullPanoWidthPixels";
+0 −4
Original line number Diff line number Diff line
@@ -188,10 +188,6 @@ public class Editor implements OnSeekBarChangeListener, SwapButton.SwapButtonLis
        return mImageShow;
    }

    public void setImageLoader(ImageLoader imageLoader) {
        mImageShow.setImageLoader(imageLoader);
    }

    public void setVisibility(int visible) {
        mView.setVisibility(visible);
    }
+1 −2
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.widget.PopupMenu;
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.crop.CropExtras;
import com.android.gallery3d.filtershow.imageshow.ImageCrop;
import com.android.gallery3d.filtershow.imageshow.MasterImage;

public class EditorCrop extends Editor implements EditorInfo {
    public static final int ID = R.id.editorCrop;
@@ -53,7 +52,7 @@ public class EditorCrop extends Editor implements EditorInfo {
            mImageCrop = new ImageCrop(context);
        }
        mView = mImageShow = mImageCrop;
        mImageCrop.setImageLoader(MasterImage.getImage().getImageLoader());
        mImageCrop.bindAsImageLoadListener();
        mImageCrop.setEditor(this);
        mImageCrop.syncLocalToMasterGeometry();
        mImageCrop.setCropActionFlag(mCropActionFlag);
Loading