OSDN Git Service

Implements progressive rendering
authornicolasroard <nicolasroard@google.com>
Fri, 29 Mar 2013 21:41:38 +0000 (14:41 -0700)
committernicolasroard <nicolasroard@google.com>
Sat, 30 Mar 2013 02:19:19 +0000 (19:19 -0700)
Change-Id: I32bd2072126a4fad4342f7d9ffa1cff3b5da84cf

src/com/android/gallery3d/filtershow/FilterShowActivity.java
src/com/android/gallery3d/filtershow/cache/CachingPipeline.java
src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
src/com/android/gallery3d/filtershow/cache/ImageLoader.java
src/com/android/gallery3d/filtershow/cache/RenderingRequest.java
src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
src/com/android/gallery3d/filtershow/imageshow/MasterImage.java

index 409f1e3..8bbfc55 100644 (file)
@@ -94,6 +94,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
     private String mAction = "";
     MasterImage mMasterImage = null;
 
+    private static final long LIMIT_SUPPORTS_HIGHRES = 134217728; // 128Mb
+
     public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
     public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
     public static final int MAX_BMAP_IN_INTENT = 990000;
@@ -487,7 +489,11 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
             pipeline.setOriginal(largeBitmap);
             float previewScale = (float) largeBitmap.getWidth() / (float) mImageLoader.getOriginalBounds().width();
             pipeline.setPreviewScaleFactor(previewScale);
-
+            Bitmap highresBitmap = mImageLoader.getOriginalBitmapHighres();
+            if (highresBitmap != null) {
+                float highResPreviewScale = (float) highresBitmap.getWidth() / (float) mImageLoader.getOriginalBounds().width();
+                pipeline.setHighResPreviewScaleFactor(highResPreviewScale);
+            }
             pipeline.turnOnPipeline(true);
             MasterImage.getImage().setOriginalGeometry(largeBitmap);
             mLoadBitmapTask = null;
@@ -879,6 +885,12 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
         mMasterImage.setStateAdapter(mImageStateAdapter);
         mMasterImage.setActivity(this);
         mMasterImage.setImageLoader(mImageLoader);
+
+        if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) {
+            mMasterImage.setSupportsHighRes(true);
+        } else {
+            mMasterImage.setSupportsHighRes(false);
+        }
     }
 
     // //////////////////////////////////////////////////////////////////////////////
index bc1d450..ecfdaba 100644 (file)
@@ -54,6 +54,7 @@ public class CachingPipeline {
 
     private volatile GeometryMetadata mPreviousGeometry = null;
     private volatile float mPreviewScaleFactor = 1.0f;
+    private volatile float mHighResPreviewScaleFactor = 1.0f;
     private volatile String mName = "";
 
     public CachingPipeline(FiltersManager filtersManager, String name) {
@@ -112,6 +113,7 @@ public class CachingPipeline {
             }
             mPreviousGeometry = null;
             mPreviewScaleFactor = 1.0f;
+            mHighResPreviewScaleFactor = 1.0f;
 
             destroyPixelAllocations();
         }
@@ -149,13 +151,20 @@ public class CachingPipeline {
         if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
             return "PARTIAL_RENDERING";
         }
+        if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
+            return "HIGHRES_RENDERING";
+        }
         return "UNKNOWN TYPE!";
     }
 
-    private void setupEnvironment(ImagePreset preset) {
+    private void setupEnvironment(ImagePreset preset, boolean highResPreview) {
         mEnvironment.setCachingPipeline(this);
         mEnvironment.setFiltersManager(mFiltersManager);
-        mEnvironment.setScaleFactor(mPreviewScaleFactor);
+        if (highResPreview) {
+            mEnvironment.setScaleFactor(mHighResPreviewScaleFactor);
+        } else {
+            mEnvironment.setScaleFactor(mPreviewScaleFactor);
+        }
         mEnvironment.setQuality(ImagePreset.QUALITY_PREVIEW);
         mEnvironment.setImagePreset(preset);
     }
@@ -164,7 +173,7 @@ public class CachingPipeline {
         mOriginalBitmap = bitmap;
         Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight());
         ImagePreset preset = MasterImage.getImage().getPreset();
-        setupEnvironment(preset);
+        setupEnvironment(preset, false);
         updateOriginalAllocation(preset);
     }
 
@@ -210,7 +219,8 @@ public class CachingPipeline {
             if (getRenderScriptContext() == null) {
                 return;
             }
-            if ((request.getType() != RenderingRequest.PARTIAL_RENDERING
+            if (((request.getType() != RenderingRequest.PARTIAL_RENDERING
+                    && request.getType() != RenderingRequest.HIGHRES_RENDERING)
                     && request.getBitmap() == null)
                     || request.getImagePreset() == null) {
                 return;
@@ -222,7 +232,8 @@ public class CachingPipeline {
 
             Bitmap bitmap = request.getBitmap();
             ImagePreset preset = request.getImagePreset();
-            setupEnvironment(preset);
+            setupEnvironment(preset,
+                    request.getType() != RenderingRequest.HIGHRES_RENDERING);
             mFiltersManager.freeFilterResources(preset);
 
             if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
@@ -239,6 +250,12 @@ public class CachingPipeline {
                 }
             }
 
+            if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
+                ImageLoader loader = MasterImage.getImage().getImageLoader();
+                bitmap = loader.getOriginalBitmapHighres();
+                bitmap = preset.applyGeometry(bitmap, mEnvironment);
+            }
+
             if (request.getType() == RenderingRequest.FULL_RENDERING
                     || request.getType() == RenderingRequest.GEOMETRY_RENDERING
                     || request.getType() == RenderingRequest.FILTERS_RENDERING) {
@@ -261,7 +278,8 @@ public class CachingPipeline {
             if (request.getType() == RenderingRequest.FULL_RENDERING
                     || request.getType() == RenderingRequest.FILTERS_RENDERING
                     || request.getType() == RenderingRequest.ICON_RENDERING
-                    || request.getType() == RenderingRequest.PARTIAL_RENDERING) {
+                    || request.getType() == RenderingRequest.PARTIAL_RENDERING
+                    || request.getType() == RenderingRequest.HIGHRES_RENDERING) {
                 Bitmap bmp = preset.apply(bitmap, mEnvironment);
                 request.setBitmap(bmp);
                 mFiltersManager.freeFilterResources(preset);
@@ -274,7 +292,7 @@ public class CachingPipeline {
             if (getRenderScriptContext() == null) {
                 return bitmap;
             }
-            setupEnvironment(preset);
+            setupEnvironment(preset, false);
             mEnvironment.setQuality(ImagePreset.QUALITY_FINAL);
             mEnvironment.setScaleFactor(1.0f);
             mFiltersManager.freeFilterResources(preset);
@@ -289,7 +307,7 @@ public class CachingPipeline {
             if (getRenderScriptContext() == null) {
                 return bitmap;
             }
-            setupEnvironment(preset);
+            setupEnvironment(preset, false);
             mEnvironment.setQuality(ImagePreset.QUALITY_PREVIEW);
             mFiltersManager.freeFilterResources(preset);
             bitmap = preset.applyGeometry(bitmap, mEnvironment);
@@ -309,7 +327,7 @@ public class CachingPipeline {
 
             String thread = Thread.currentThread().getName();
             long time = System.currentTimeMillis();
-            setupEnvironment(preset);
+            setupEnvironment(preset, false);
             mFiltersManager.freeFilterResources(preset);
 
             Bitmap resizedOriginalBitmap = mResizedOriginalBitmap;
@@ -346,11 +364,14 @@ public class CachingPipeline {
         return buffer.checkRepaintNeeded();
     }
 
-
     public void setPreviewScaleFactor(float previewScaleFactor) {
         mPreviewScaleFactor = previewScaleFactor;
     }
 
+    public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
+        mHighResPreviewScaleFactor = highResPreviewScaleFactor;
+    }
+
     public synchronized boolean isInitialized() {
         return getRenderScriptContext() != null && mOriginalBitmap != null;
     }
index 1ba6e95..ce66b5b 100644 (file)
@@ -47,9 +47,23 @@ public class FilteringPipeline implements Handler.Callback {
     private final static int COMPUTE_PRESET = 2;
     private final static int COMPUTE_RENDERING_REQUEST = 3;
     private final static int COMPUTE_PARTIAL_RENDERING_REQUEST = 4;
+    private final static int COMPUTE_HIGHRES_RENDERING_REQUEST = 5;
 
     private volatile boolean mHasUnhandledPreviewRequest = false;
 
+    private String getType(int value) {
+        if (value == COMPUTE_RENDERING_REQUEST) {
+            return "COMPUTE_RENDERING_REQUEST";
+        }
+        if (value == COMPUTE_PARTIAL_RENDERING_REQUEST) {
+            return "COMPUTE_PARTIAL_RENDERING_REQUEST";
+        }
+        if (value == COMPUTE_HIGHRES_RENDERING_REQUEST) {
+            return "COMPUTE_HIGHRES_RENDERING_REQUEST";
+        }
+        return "UNKNOWN TYPE";
+    }
+
     private Handler mProcessingHandler = null;
     private final Handler mUIHandler = new Handler() {
         @Override
@@ -89,12 +103,19 @@ public class FilteringPipeline implements Handler.Callback {
                 break;
             }
             case COMPUTE_RENDERING_REQUEST:
-            case COMPUTE_PARTIAL_RENDERING_REQUEST: {
-                if (msg.what == COMPUTE_PARTIAL_RENDERING_REQUEST) {
-                    if (mProcessingHandler.hasMessages(COMPUTE_PARTIAL_RENDERING_REQUEST)) {
+            case COMPUTE_PARTIAL_RENDERING_REQUEST:
+            case COMPUTE_HIGHRES_RENDERING_REQUEST: {
+                if (msg.what == COMPUTE_PARTIAL_RENDERING_REQUEST
+                        || msg.what == COMPUTE_HIGHRES_RENDERING_REQUEST) {
+                    if (mProcessingHandler.hasMessages(msg.what)) {
                         return false;
                     }
                 }
+
+                if (DEBUG) {
+                    Log.v(LOGTAG, "Compute Request: " + getType(msg.what));
+                }
+
                 RenderingRequest request = (RenderingRequest) msg.obj;
                 mAccessoryPipeline.render(request);
                 Message uimsg = mUIHandler.obtainMessage(NEW_RENDERING_REQUEST);
@@ -140,9 +161,13 @@ public class FilteringPipeline implements Handler.Callback {
         if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
             type = COMPUTE_PARTIAL_RENDERING_REQUEST;
         }
+        if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
+            type = COMPUTE_HIGHRES_RENDERING_REQUEST;
+        }
         Message msg = mProcessingHandler.obtainMessage(type);
         msg.obj = request;
-        if (type == COMPUTE_PARTIAL_RENDERING_REQUEST) {
+        if (type == COMPUTE_PARTIAL_RENDERING_REQUEST
+                || type == COMPUTE_HIGHRES_RENDERING_REQUEST) {
             mProcessingHandler.sendMessageDelayed(msg, HIRES_DELAY);
         } else {
             mProcessingHandler.sendMessage(msg);
@@ -174,6 +199,11 @@ public class FilteringPipeline implements Handler.Callback {
         mPreviewPipeline.setPreviewScaleFactor(previewScaleFactor);
     }
 
+    public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) {
+        mAccessoryPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
+        mPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScaleFactor);
+    }
+
     public static synchronized void reset() {
         sPipeline.mAccessoryPipeline.reset();
         sPipeline.mPreviewPipeline.reset();
index a6a0bcf..b4e98e1 100644 (file)
@@ -42,6 +42,7 @@ import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.HistoryAdapter;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.imageshow.ImageShow;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.presets.ImagePreset;
 import com.android.gallery3d.filtershow.tools.BitmapTask;
 import com.android.gallery3d.filtershow.tools.SaveCopyTask;
@@ -67,6 +68,7 @@ public class 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 final ZoomCache mZoomCache = new ZoomCache();
@@ -97,6 +99,8 @@ public class ImageLoader {
     private Rect mOriginalBounds = null;
     private static int mZoomOrientation = ORI_NORMAL;
 
+    static final int MAX_BITMAP_DIM = 900;
+
     private ReentrantLock mLoadingLock = new ReentrantLock();
 
     public ImageLoader(FilterShowActivity activity, Context context) {
@@ -127,6 +131,13 @@ public class ImageLoader {
             mLoadingLock.unlock();
             return false;
         }
+        if (MasterImage.getImage().supportsHighRes()) {
+            int highresPreviewSize = mOriginalBitmapLarge.getWidth() * 2;
+            if (highresPreviewSize > mOriginalBounds.width()) {
+                highresPreviewSize = mOriginalBounds.width();
+            }
+            mOriginalBitmapHighres = loadScaledBitmap(uri, highresPreviewSize, false);
+        }
         updateBitmaps();
         mLoadingLock.unlock();
         return true;
@@ -197,6 +208,9 @@ public class ImageLoader {
         if (mOrientation > 1) {
             mOriginalBitmapSmall = rotateToPortrait(mOriginalBitmapSmall, mOrientation);
             mOriginalBitmapLarge = rotateToPortrait(mOriginalBitmapLarge, mOrientation);
+            if (mOriginalBitmapHighres != null) {
+                mOriginalBitmapHighres = rotateToPortrait(mOriginalBitmapHighres, mOrientation);
+            }
         }
         mZoomOrientation = mOrientation;
         warnListeners();
@@ -272,9 +286,11 @@ public class ImageLoader {
         return null;
     }
 
-    static final int MAX_BITMAP_DIM = 900;
-
     private Bitmap loadScaledBitmap(Uri uri, int size) {
+        return loadScaledBitmap(uri, size, true);
+    }
+
+    private Bitmap loadScaledBitmap(Uri uri, int size, boolean enforceSize) {
         InputStream is = null;
         try {
             is = mContext.getContentResolver().openInputStream(uri);
@@ -291,7 +307,12 @@ public class ImageLoader {
 
             int scale = 1;
             while (true) {
-                if (width_tmp <= MAX_BITMAP_DIM && height_tmp <= MAX_BITMAP_DIM) {
+                if (width_tmp <= 2 || height_tmp <= 2) {
+                    break;
+                }
+                if (!enforceSize
+                        || (width_tmp <= MAX_BITMAP_DIM
+                        && height_tmp <= MAX_BITMAP_DIM)) {
                     if (width_tmp / 2 < size || height_tmp / 2 < size) {
                         break;
                     }
@@ -336,6 +357,10 @@ public class ImageLoader {
         return mOriginalBitmapLarge;
     }
 
+    public Bitmap getOriginalBitmapHighres() {
+        return mOriginalBitmapHighres;
+    }
+
     public void addListener(ImageShow imageShow) {
         mLoadingLock.lock();
         if (!mListeners.contains(imageShow)) {
index 138abb0..8e7c3e1 100644 (file)
@@ -39,6 +39,7 @@ public class RenderingRequest {
     public static final int GEOMETRY_RENDERING = 2;
     public static final int ICON_RENDERING = 3;
     public static final int PARTIAL_RENDERING = 4;
+    public static final int HIGHRES_RENDERING = 5;
     private static final Bitmap.Config mConfig = Bitmap.Config.ARGB_8888;
 
     public static void post(Bitmap source, ImagePreset preset, int type, RenderingRequestCaller caller) {
@@ -47,8 +48,10 @@ public class RenderingRequest {
 
     public static void post(Bitmap source, ImagePreset preset, int type,
                             RenderingRequestCaller caller, Rect bounds, Rect destination) {
-        if ((type != PARTIAL_RENDERING && source == null) || preset == null || caller == null) {
-            Log.v(LOGTAG, "something null: source: " + source + " or preset: " + preset + " or caller: " + caller);
+        if (((type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) && source == null)
+                || preset == null || caller == null) {
+            Log.v(LOGTAG, "something null: source: " + source
+                    + " or preset: " + preset + " or caller: " + caller);
             return;
         }
         RenderingRequest request = new RenderingRequest();
@@ -59,7 +62,7 @@ public class RenderingRequest {
             CachingPipeline pipeline = new CachingPipeline(
                     FiltersManager.getManager(), "Icon");
             bitmap = pipeline.renderGeometryIcon(source, preset);
-        } else if (type != PARTIAL_RENDERING) {
+        } else if (type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) {
             bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), mConfig);
         }
 
index 38dc177..1ab9e54 100644 (file)
@@ -323,7 +323,11 @@ public class ImageShow extends View implements OnGestureListener,
         canvas.scale(scaleFactor, scaleFactor, cx, cy);
         canvas.translate(translation.x, translation.y);
         drawBackground(canvas);
-        drawImage(canvas, getFilteredImage());
+        drawImage(canvas, getFilteredImage(), true);
+        Bitmap highresPreview = MasterImage.getImage().getHighresImage();
+        if (highresPreview != null) {
+            drawImage(canvas, highresPreview, false);
+        }
         canvas.restore();
 
         if (showTitle() && getImagePreset() != null) {
@@ -374,7 +378,7 @@ public class ImageShow extends View implements OnGestureListener,
         return MasterImage.getImage().getFilteredImage();
     }
 
-    public void drawImage(Canvas canvas, Bitmap image) {
+    public void drawImage(Canvas canvas, Bitmap image, boolean updateBounds) {
         if (image != null) {
             Rect s = new Rect(0, 0, image.getWidth(),
                     image.getHeight());
@@ -389,7 +393,9 @@ public class ImageShow extends View implements OnGestureListener,
 
             Rect d = new Rect((int) tx, (int) ty, (int) (w + tx),
                     (int) (h + ty));
-            mImageBounds = d;
+            if (updateBounds) {
+                mImageBounds = d;
+            }
             canvas.drawBitmap(image, s, d, mPaint);
         }
     }
@@ -420,7 +426,7 @@ public class ImageShow extends View implements OnGestureListener,
             Rect d = new Rect(mImageBounds.left, mImageBounds.top,
                     mImageBounds.left + px, mImageBounds.top + py);
             canvas.clipRect(d);
-            drawImage(canvas, image);
+            drawImage(canvas, image, false);
             Paint paint = new Paint();
             paint.setColor(Color.BLACK);
             paint.setStrokeWidth(3);
index 993f5d5..c4d5a06 100644 (file)
@@ -19,15 +19,12 @@ package com.android.gallery3d.filtershow.imageshow;
 import android.graphics.*;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Log;
 
-import android.util.Log;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.HistoryAdapter;
 import com.android.gallery3d.filtershow.ImageStateAdapter;
 import com.android.gallery3d.filtershow.cache.*;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
 import com.android.gallery3d.filtershow.presets.ImagePreset;
 
@@ -42,6 +39,8 @@ public class MasterImage implements RenderingRequestCaller {
     private static int sIconSeedSize = 128;
     private static float sHistoryPreviewSize = 128.0f;
 
+    private boolean mSupportsHighRes = false;
+
     private ImageFilter mCurrentFilter = null;
     private ImagePreset mPreset = null;
     private ImagePreset mGeometryOnlyPreset = null;
@@ -52,6 +51,7 @@ public class MasterImage implements RenderingRequestCaller {
     private Bitmap mGeometryOnlyBitmap = null;
     private Bitmap mFiltersOnlyBitmap = null;
     private Bitmap mPartialBitmap = null;
+    private Bitmap mHighresBitmap = null;
 
     private ImageLoader mLoader = null;
     private HistoryAdapter mHistory = null;
@@ -96,6 +96,10 @@ public class MasterImage implements RenderingRequestCaller {
         return sMasterImage;
     }
 
+    public void setSupportsHighRes(boolean value) {
+        mSupportsHighRes = value;
+    }
+
     public static void setIconSeedSize(int iconSeedSize) {
         sIconSeedSize = iconSeedSize;
     }
@@ -253,6 +257,10 @@ public class MasterImage implements RenderingRequestCaller {
         return mPartialBitmap;
     }
 
+    public Bitmap getHighresImage() {
+        return mHighresBitmap;
+    }
+
     public void notifyObservers() {
         for (ImageShow observer : mObservers) {
             observer.invalidate();
@@ -283,7 +291,6 @@ public class MasterImage implements RenderingRequestCaller {
             }
         }
         invalidatePreview();
-        needsUpdateFullResPreview();
         mActivity.enableSave(hasModifications());
     }
 
@@ -307,17 +314,27 @@ public class MasterImage implements RenderingRequestCaller {
         }
     }
 
+    public void invalidateHighresPreview() {
+        if (mHighresBitmap != null) {
+            mHighresBitmap = null;
+            notifyObservers();
+        }
+    }
+
     public void invalidatePreview() {
         mFilteredPreview.invalidate();
         invalidatePartialPreview();
-        needsUpdateFullResPreview();
+        invalidateHighresPreview();
+        needsUpdatePartialPreview();
+        needsUpdateHighResPreview();
         FilteringPipeline.getPipeline().updatePreviewBuffer();
     }
 
     public void setImageShowSize(int w, int h) {
         if (mImageShowSize.x != w || mImageShowSize.y != h) {
             mImageShowSize.set(w, h);
-            needsUpdateFullResPreview();
+            needsUpdatePartialPreview();
+            needsUpdateHighResPreview();
         }
     }
 
@@ -345,7 +362,15 @@ public class MasterImage implements RenderingRequestCaller {
         return invert;
     }
 
-    public void needsUpdateFullResPreview() {
+    public void needsUpdateHighResPreview() {
+        if (!mSupportsHighRes) {
+            return;
+        }
+        RenderingRequest.post(null, mPreset, RenderingRequest.HIGHRES_RENDERING, this);
+        invalidateHighresPreview();
+    }
+
+    public void needsUpdatePartialPreview() {
         if (!mPreset.canDoPartialRendering()) {
             invalidatePartialPreview();
             return;
@@ -376,6 +401,11 @@ public class MasterImage implements RenderingRequestCaller {
             mPartialBitmap = request.getBitmap();
             notifyObservers();
         }
+        if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
+            mHighresBitmap = request.getBitmap();
+            notifyObservers();
+        }
+
         if (request.getType() == RenderingRequest.ICON_RENDERING) {
             // History preview images
             ImagePreset preset = request.getOriginalImagePreset();
@@ -426,7 +456,7 @@ public class MasterImage implements RenderingRequestCaller {
     public void setTranslation(Point translation) {
         mTranslation.x = translation.x;
         mTranslation.y = translation.y;
-        needsUpdateFullResPreview();
+        needsUpdatePartialPreview();
     }
 
     public Point getOriginalTranslation() {
@@ -441,7 +471,7 @@ public class MasterImage implements RenderingRequestCaller {
     public void resetTranslation() {
         mTranslation.x = 0;
         mTranslation.y = 0;
-        needsUpdateFullResPreview();
+        needsUpdatePartialPreview();
     }
 
     public Bitmap getThumbnailBitmap() {
@@ -455,4 +485,8 @@ public class MasterImage implements RenderingRequestCaller {
     public void setMaxScaleFactor(float maxScaleFactor) {
         mMaxScaleFactor = maxScaleFactor;
     }
+
+    public boolean supportsHighRes() {
+        return mSupportsHighRes;
+    }
 }