1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.gallery3d.filtershow.imageshow; 18 19 import android.animation.Animator; 20 import android.animation.ValueAnimator; 21 import android.graphics.Bitmap; 22 import android.graphics.Canvas; 23 import android.graphics.Matrix; 24 import android.graphics.Point; 25 import android.graphics.Rect; 26 import android.graphics.RectF; 27 import android.net.Uri; 28 29 import com.android.gallery3d.exif.ExifTag; 30 import com.android.gallery3d.filtershow.FilterShowActivity; 31 import com.android.gallery3d.filtershow.cache.BitmapCache; 32 import com.android.gallery3d.filtershow.cache.ImageLoader; 33 import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation; 34 import com.android.gallery3d.filtershow.filters.FilterRepresentation; 35 import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation; 36 import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; 37 import com.android.gallery3d.filtershow.filters.ImageFilter; 38 import com.android.gallery3d.filtershow.history.HistoryItem; 39 import com.android.gallery3d.filtershow.history.HistoryManager; 40 import com.android.gallery3d.filtershow.pipeline.Buffer; 41 import com.android.gallery3d.filtershow.pipeline.ImagePreset; 42 import com.android.gallery3d.filtershow.pipeline.RenderingRequest; 43 import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; 44 import com.android.gallery3d.filtershow.pipeline.SharedBuffer; 45 import com.android.gallery3d.filtershow.pipeline.SharedPreset; 46 import com.android.gallery3d.filtershow.state.StateAdapter; 47 48 import java.util.List; 49 import java.util.Vector; 50 51 public class MasterImage implements RenderingRequestCaller { 52 53 private static final String LOGTAG = "MasterImage"; 54 private boolean DEBUG = false; 55 private static final boolean DISABLEZOOM = false; 56 public static final int SMALL_BITMAP_DIM = 160; 57 public static final int MAX_BITMAP_DIM = 900; 58 private static MasterImage sMasterImage = null; 59 60 private boolean mSupportsHighRes = false; 61 62 private ImageFilter mCurrentFilter = null; 63 private ImagePreset mPreset = null; 64 private ImagePreset mLoadedPreset = null; 65 private ImagePreset mGeometryOnlyPreset = null; 66 private ImagePreset mFiltersOnlyPreset = null; 67 68 private SharedBuffer mPreviewBuffer = new SharedBuffer(); 69 private SharedPreset mPreviewPreset = new SharedPreset(); 70 71 private Bitmap mOriginalBitmapSmall = null; 72 private Bitmap mOriginalBitmapLarge = null; 73 private Bitmap mOriginalBitmapHighres = null; 74 private Bitmap mTemporaryThumbnail = null; 75 private int mOrientation; 76 private Rect mOriginalBounds; 77 private final Vector<ImageShow> mLoadListeners = new Vector<ImageShow>(); 78 private Uri mUri = null; 79 private int mZoomOrientation = ImageLoader.ORI_NORMAL; 80 81 private Bitmap mGeometryOnlyBitmap = null; 82 private Bitmap mFiltersOnlyBitmap = null; 83 private Bitmap mPartialBitmap = null; 84 private Bitmap mHighresBitmap = null; 85 private Bitmap mPreviousImage = null; 86 private int mShadowMargin = 15; // not scaled, fixed in the asset 87 private Rect mPartialBounds = new Rect(); 88 89 private ValueAnimator mAnimator = null; 90 private float mMaskScale = 1; 91 private boolean mOnGoingNewLookAnimation = false; 92 private float mAnimRotationValue = 0; 93 private float mCurrentAnimRotationStartValue = 0; 94 private float mAnimFraction = 0; 95 private int mCurrentLookAnimation = 0; 96 public static final int CIRCLE_ANIMATION = 1; 97 public static final int ROTATE_ANIMATION = 2; 98 public static final int MIRROR_ANIMATION = 3; 99 100 private HistoryManager mHistory = null; 101 private StateAdapter mState = null; 102 103 private FilterShowActivity mActivity = null; 104 105 private Vector<ImageShow> mObservers = new Vector<ImageShow>(); 106 private FilterRepresentation mCurrentFilterRepresentation; 107 108 private float mScaleFactor = 1.0f; 109 private float mMaxScaleFactor = 3.0f; // TODO: base this on the current view / image 110 private Point mTranslation = new Point(); 111 private Point mOriginalTranslation = new Point(); 112 113 private Point mImageShowSize = new Point(); 114 115 private boolean mShowsOriginal; 116 private List<ExifTag> mEXIF; 117 private BitmapCache mBitmapCache = new BitmapCache(); 118 MasterImage()119 private MasterImage() { 120 } 121 122 // TODO: remove singleton setMaster(MasterImage master)123 public static void setMaster(MasterImage master) { 124 sMasterImage = master; 125 } 126 getImage()127 public static MasterImage getImage() { 128 if (sMasterImage == null) { 129 sMasterImage = new MasterImage(); 130 } 131 return sMasterImage; 132 } 133 getOriginalBitmapSmall()134 public Bitmap getOriginalBitmapSmall() { 135 return mOriginalBitmapSmall; 136 } 137 getOriginalBitmapLarge()138 public Bitmap getOriginalBitmapLarge() { 139 return mOriginalBitmapLarge; 140 } 141 getOriginalBitmapHighres()142 public Bitmap getOriginalBitmapHighres() { 143 if (mOriginalBitmapHighres == null) { 144 return mOriginalBitmapLarge; 145 } 146 return mOriginalBitmapHighres; 147 } 148 setOriginalBitmapHighres(Bitmap mOriginalBitmapHighres)149 public void setOriginalBitmapHighres(Bitmap mOriginalBitmapHighres) { 150 this.mOriginalBitmapHighres = mOriginalBitmapHighres; 151 } 152 getOrientation()153 public int getOrientation() { 154 return mOrientation; 155 } 156 getOriginalBounds()157 public Rect getOriginalBounds() { 158 return mOriginalBounds; 159 } 160 setOriginalBounds(Rect r)161 public void setOriginalBounds(Rect r) { 162 mOriginalBounds = r; 163 } 164 getUri()165 public Uri getUri() { 166 return mUri; 167 } 168 setUri(Uri uri)169 public void setUri(Uri uri) { 170 mUri = uri; 171 } 172 getZoomOrientation()173 public int getZoomOrientation() { 174 return mZoomOrientation; 175 } 176 addListener(ImageShow imageShow)177 public void addListener(ImageShow imageShow) { 178 if (!mLoadListeners.contains(imageShow)) { 179 mLoadListeners.add(imageShow); 180 } 181 } 182 warnListeners()183 public void warnListeners() { 184 mActivity.runOnUiThread(mWarnListenersRunnable); 185 } 186 187 private Runnable mWarnListenersRunnable = new Runnable() { 188 @Override 189 public void run() { 190 for (int i = 0; i < mLoadListeners.size(); i++) { 191 ImageShow imageShow = mLoadListeners.elementAt(i); 192 imageShow.imageLoaded(); 193 } 194 invalidatePreview(); 195 } 196 }; 197 loadBitmap(Uri uri, int size)198 public boolean loadBitmap(Uri uri, int size) { 199 setUri(uri); 200 mEXIF = ImageLoader.getExif(getActivity(), uri); 201 mOrientation = ImageLoader.getMetadataOrientation(mActivity, uri); 202 Rect originalBounds = new Rect(); 203 mOriginalBitmapLarge = ImageLoader.loadOrientedConstrainedBitmap(uri, mActivity, 204 Math.min(MAX_BITMAP_DIM, size), 205 mOrientation, originalBounds); 206 setOriginalBounds(originalBounds); 207 if (mOriginalBitmapLarge == null) { 208 return false; 209 } 210 int sw = SMALL_BITMAP_DIM; 211 int sh = (int) (sw * (float) mOriginalBitmapLarge.getHeight() / mOriginalBitmapLarge 212 .getWidth()); 213 mOriginalBitmapSmall = Bitmap.createScaledBitmap(mOriginalBitmapLarge, sw, sh, true); 214 mZoomOrientation = mOrientation; 215 warnListeners(); 216 return true; 217 } 218 setSupportsHighRes(boolean value)219 public void setSupportsHighRes(boolean value) { 220 mSupportsHighRes = value; 221 } 222 addObserver(ImageShow observer)223 public void addObserver(ImageShow observer) { 224 if (mObservers.contains(observer)) { 225 return; 226 } 227 mObservers.add(observer); 228 } 229 removeObserver(ImageShow observer)230 public void removeObserver(ImageShow observer) { 231 mObservers.remove(observer); 232 } 233 setActivity(FilterShowActivity activity)234 public void setActivity(FilterShowActivity activity) { 235 mActivity = activity; 236 } 237 getActivity()238 public FilterShowActivity getActivity() { 239 return mActivity; 240 } 241 getPreset()242 public synchronized ImagePreset getPreset() { 243 return mPreset; 244 } 245 getGeometryPreset()246 public synchronized ImagePreset getGeometryPreset() { 247 return mGeometryOnlyPreset; 248 } 249 getFiltersOnlyPreset()250 public synchronized ImagePreset getFiltersOnlyPreset() { 251 return mFiltersOnlyPreset; 252 } 253 setPreset(ImagePreset preset, FilterRepresentation change, boolean addToHistory)254 public synchronized void setPreset(ImagePreset preset, 255 FilterRepresentation change, 256 boolean addToHistory) { 257 if (DEBUG) { 258 preset.showFilters(); 259 } 260 mPreset = preset; 261 mPreset.fillImageStateAdapter(mState); 262 if (addToHistory) { 263 HistoryItem historyItem = new HistoryItem(mPreset, change); 264 mHistory.addHistoryItem(historyItem); 265 } 266 updatePresets(true); 267 resetGeometryImages(false); 268 mActivity.updateCategories(); 269 } 270 onHistoryItemClick(int position)271 public void onHistoryItemClick(int position) { 272 HistoryItem historyItem = mHistory.getItem(position); 273 // We need a copy from the history 274 ImagePreset newPreset = new ImagePreset(historyItem.getImagePreset()); 275 // don't need to add it to the history 276 setPreset(newPreset, historyItem.getFilterRepresentation(), false); 277 mHistory.setCurrentPreset(position); 278 } 279 getHistory()280 public HistoryManager getHistory() { 281 return mHistory; 282 } 283 getState()284 public StateAdapter getState() { 285 return mState; 286 } 287 setHistoryManager(HistoryManager adapter)288 public void setHistoryManager(HistoryManager adapter) { 289 mHistory = adapter; 290 } 291 setStateAdapter(StateAdapter adapter)292 public void setStateAdapter(StateAdapter adapter) { 293 mState = adapter; 294 } 295 setCurrentFilter(ImageFilter filter)296 public void setCurrentFilter(ImageFilter filter) { 297 mCurrentFilter = filter; 298 } 299 getCurrentFilter()300 public ImageFilter getCurrentFilter() { 301 return mCurrentFilter; 302 } 303 hasModifications()304 public synchronized boolean hasModifications() { 305 // TODO: We need to have a better same effects check to see if two 306 // presets are functionally the same. Right now, we are relying on a 307 // stricter check as equals(). 308 ImagePreset loadedPreset = getLoadedPreset(); 309 if (mPreset == null) { 310 if (loadedPreset == null) { 311 return false; 312 } else { 313 return loadedPreset.hasModifications(); 314 } 315 } else { 316 if (loadedPreset == null) { 317 return mPreset.hasModifications(); 318 } else { 319 return !mPreset.equals(loadedPreset); 320 } 321 } 322 } 323 getPreviewBuffer()324 public SharedBuffer getPreviewBuffer() { 325 return mPreviewBuffer; 326 } 327 getPreviewPreset()328 public SharedPreset getPreviewPreset() { 329 return mPreviewPreset; 330 } 331 getFilteredImage()332 public Bitmap getFilteredImage() { 333 mPreviewBuffer.swapConsumerIfNeeded(); // get latest bitmap 334 Buffer consumer = mPreviewBuffer.getConsumer(); 335 if (consumer != null) { 336 return consumer.getBitmap(); 337 } 338 return null; 339 } 340 getFiltersOnlyImage()341 public Bitmap getFiltersOnlyImage() { 342 return mFiltersOnlyBitmap; 343 } 344 getGeometryOnlyImage()345 public Bitmap getGeometryOnlyImage() { 346 return mGeometryOnlyBitmap; 347 } 348 getPartialImage()349 public Bitmap getPartialImage() { 350 return mPartialBitmap; 351 } 352 getPartialBounds()353 public Rect getPartialBounds() { 354 return mPartialBounds; 355 } 356 getHighresImage()357 public Bitmap getHighresImage() { 358 if (mHighresBitmap == null) { 359 return getFilteredImage(); 360 } 361 return mHighresBitmap; 362 } 363 getPreviousImage()364 public Bitmap getPreviousImage() { 365 return mPreviousImage; 366 } 367 getCurrentPreset()368 public ImagePreset getCurrentPreset() { 369 return getPreviewBuffer().getConsumer().getPreset(); 370 } 371 getMaskScale()372 public float getMaskScale() { 373 return mMaskScale; 374 } 375 setMaskScale(float scale)376 public void setMaskScale(float scale) { 377 mMaskScale = scale; 378 notifyObservers(); 379 } 380 getAnimRotationValue()381 public float getAnimRotationValue() { 382 return mAnimRotationValue; 383 } 384 setAnimRotation(float rotation)385 public void setAnimRotation(float rotation) { 386 mAnimRotationValue = mCurrentAnimRotationStartValue + rotation; 387 notifyObservers(); 388 } 389 setAnimFraction(float fraction)390 public void setAnimFraction(float fraction) { 391 mAnimFraction = fraction; 392 } 393 getAnimFraction()394 public float getAnimFraction() { 395 return mAnimFraction; 396 } 397 onGoingNewLookAnimation()398 public boolean onGoingNewLookAnimation() { 399 return mOnGoingNewLookAnimation; 400 } 401 getCurrentLookAnimation()402 public int getCurrentLookAnimation() { 403 return mCurrentLookAnimation; 404 } 405 resetAnimBitmap()406 public void resetAnimBitmap() { 407 mBitmapCache.cache(mPreviousImage); 408 mPreviousImage = null; 409 } 410 onNewLook(FilterRepresentation newRepresentation)411 public void onNewLook(FilterRepresentation newRepresentation) { 412 if (getFilteredImage() == null) { 413 return; 414 } 415 if (mAnimator != null) { 416 mAnimator.cancel(); 417 if (mCurrentLookAnimation == ROTATE_ANIMATION) { 418 mCurrentAnimRotationStartValue += 90; 419 } 420 } else { 421 resetAnimBitmap(); 422 mPreviousImage = mBitmapCache.getBitmapCopy(getFilteredImage(), BitmapCache.NEW_LOOK); 423 } 424 if (newRepresentation instanceof FilterUserPresetRepresentation) { 425 mCurrentLookAnimation = CIRCLE_ANIMATION; 426 mAnimator = ValueAnimator.ofFloat(0, 1); 427 mAnimator.setDuration(650); 428 } 429 if (newRepresentation instanceof FilterRotateRepresentation) { 430 mCurrentLookAnimation = ROTATE_ANIMATION; 431 mAnimator = ValueAnimator.ofFloat(0, 90); 432 mAnimator.setDuration(500); 433 } 434 if (newRepresentation instanceof FilterMirrorRepresentation) { 435 mCurrentLookAnimation = MIRROR_ANIMATION; 436 mAnimator = ValueAnimator.ofFloat(1, 0, -1); 437 mAnimator.setDuration(500); 438 } 439 mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 440 @Override 441 public void onAnimationUpdate(ValueAnimator animation) { 442 if (mCurrentLookAnimation == CIRCLE_ANIMATION) { 443 setMaskScale((Float) animation.getAnimatedValue()); 444 } else if (mCurrentLookAnimation == ROTATE_ANIMATION 445 || mCurrentLookAnimation == MIRROR_ANIMATION) { 446 setAnimRotation((Float) animation.getAnimatedValue()); 447 setAnimFraction(animation.getAnimatedFraction()); 448 } 449 } 450 }); 451 mAnimator.addListener(new Animator.AnimatorListener() { 452 @Override 453 public void onAnimationStart(Animator animation) { 454 mOnGoingNewLookAnimation = true; 455 } 456 457 @Override 458 public void onAnimationEnd(Animator animation) { 459 mOnGoingNewLookAnimation = false; 460 mCurrentAnimRotationStartValue = 0; 461 mAnimator = null; 462 notifyObservers(); 463 } 464 465 @Override 466 public void onAnimationCancel(Animator animation) { 467 468 } 469 470 @Override 471 public void onAnimationRepeat(Animator animation) { 472 473 } 474 }); 475 mAnimator.start(); 476 notifyObservers(); 477 } 478 notifyObservers()479 public void notifyObservers() { 480 for (ImageShow observer : mObservers) { 481 observer.invalidate(); 482 } 483 } 484 resetGeometryImages(boolean force)485 public void resetGeometryImages(boolean force) { 486 if (mPreset == null) { 487 return; 488 } 489 ImagePreset newPresetGeometryOnly = new ImagePreset(mPreset); 490 newPresetGeometryOnly.setDoApplyFilters(false); 491 newPresetGeometryOnly.setDoApplyGeometry(true); 492 if (force || mGeometryOnlyPreset == null 493 || !newPresetGeometryOnly.equals(mGeometryOnlyPreset)) { 494 mGeometryOnlyPreset = newPresetGeometryOnly; 495 RenderingRequest.post(mActivity, null, 496 mGeometryOnlyPreset, RenderingRequest.GEOMETRY_RENDERING, this); 497 } 498 ImagePreset newPresetFiltersOnly = new ImagePreset(mPreset); 499 newPresetFiltersOnly.setDoApplyFilters(true); 500 newPresetFiltersOnly.setDoApplyGeometry(false); 501 if (force || mFiltersOnlyPreset == null 502 || !newPresetFiltersOnly.same(mFiltersOnlyPreset)) { 503 mFiltersOnlyPreset = newPresetFiltersOnly; 504 RenderingRequest.post(mActivity, null, 505 mFiltersOnlyPreset, RenderingRequest.FILTERS_RENDERING, this); 506 } 507 } 508 updatePresets(boolean force)509 public void updatePresets(boolean force) { 510 invalidatePreview(); 511 } 512 getCurrentFilterRepresentation()513 public FilterRepresentation getCurrentFilterRepresentation() { 514 return mCurrentFilterRepresentation; 515 } 516 setCurrentFilterRepresentation(FilterRepresentation currentFilterRepresentation)517 public void setCurrentFilterRepresentation(FilterRepresentation currentFilterRepresentation) { 518 mCurrentFilterRepresentation = currentFilterRepresentation; 519 } 520 invalidateFiltersOnly()521 public void invalidateFiltersOnly() { 522 mFiltersOnlyPreset = null; 523 invalidatePreview(); 524 } 525 invalidatePartialPreview()526 public void invalidatePartialPreview() { 527 if (mPartialBitmap != null) { 528 mBitmapCache.cache(mPartialBitmap); 529 mPartialBitmap = null; 530 notifyObservers(); 531 } 532 } 533 invalidateHighresPreview()534 public void invalidateHighresPreview() { 535 if (mHighresBitmap != null) { 536 mBitmapCache.cache(mHighresBitmap); 537 mHighresBitmap = null; 538 notifyObservers(); 539 } 540 } 541 invalidatePreview()542 public void invalidatePreview() { 543 if (mPreset == null) { 544 return; 545 } 546 547 mPreviewPreset.enqueuePreset(mPreset); 548 mPreviewBuffer.invalidate(); 549 invalidatePartialPreview(); 550 invalidateHighresPreview(); 551 needsUpdatePartialPreview(); 552 needsUpdateHighResPreview(); 553 mActivity.getProcessingService().updatePreviewBuffer(); 554 } 555 setImageShowSize(int w, int h)556 public void setImageShowSize(int w, int h) { 557 if (mImageShowSize.x != w || mImageShowSize.y != h) { 558 mImageShowSize.set(w, h); 559 float maxWidth = mOriginalBounds.width() / (float) w; 560 float maxHeight = mOriginalBounds.height() / (float) h; 561 mMaxScaleFactor = Math.max(3.f, Math.max(maxWidth, maxHeight)); 562 needsUpdatePartialPreview(); 563 needsUpdateHighResPreview(); 564 } 565 } 566 originalImageToScreen()567 public Matrix originalImageToScreen() { 568 return computeImageToScreen(null, 0, true); 569 } 570 computeImageToScreen(Bitmap bitmapToDraw, float rotate, boolean applyGeometry)571 public Matrix computeImageToScreen(Bitmap bitmapToDraw, 572 float rotate, 573 boolean applyGeometry) { 574 if (getOriginalBounds() == null 575 || mImageShowSize.x == 0 576 || mImageShowSize.y == 0) { 577 return null; 578 } 579 580 Matrix m = null; 581 float scale = 1f; 582 float translateX = 0; 583 float translateY = 0; 584 585 if (applyGeometry) { 586 GeometryMathUtils.GeometryHolder holder = GeometryMathUtils.unpackGeometry( 587 mPreset.getGeometryFilters()); 588 m = GeometryMathUtils.getCropSelectionToScreenMatrix(null, holder, 589 getOriginalBounds().width(), getOriginalBounds().height(), 590 mImageShowSize.x, mImageShowSize.y); 591 } else if (bitmapToDraw != null) { 592 m = new Matrix(); 593 RectF size = new RectF(0, 0, 594 bitmapToDraw.getWidth(), 595 bitmapToDraw.getHeight()); 596 scale = mImageShowSize.x / size.width(); 597 if (size.width() < size.height()) { 598 scale = mImageShowSize.y / size.height(); 599 } 600 translateX = (mImageShowSize.x - (size.width() * scale)) / 2.0f; 601 translateY = (mImageShowSize.y - (size.height() * scale)) / 2.0f; 602 } else { 603 return null; 604 } 605 606 Point translation = getTranslation(); 607 m.postScale(scale, scale); 608 m.postRotate(rotate, mImageShowSize.x / 2.0f, mImageShowSize.y / 2.0f); 609 m.postTranslate(translateX, translateY); 610 m.postTranslate(mShadowMargin, mShadowMargin); 611 m.postScale(getScaleFactor(), getScaleFactor(), 612 mImageShowSize.x / 2.0f, 613 mImageShowSize.y / 2.0f); 614 m.postTranslate(translation.x * getScaleFactor(), 615 translation.y * getScaleFactor()); 616 return m; 617 } 618 getImageToScreenMatrix(boolean reflectRotation)619 private Matrix getImageToScreenMatrix(boolean reflectRotation) { 620 if (getOriginalBounds() == null || mImageShowSize.x == 0 || mImageShowSize.y == 0) { 621 return new Matrix(); 622 } 623 Matrix m = GeometryMathUtils.getImageToScreenMatrix(mPreset.getGeometryFilters(), 624 reflectRotation, getOriginalBounds(), mImageShowSize.x, mImageShowSize.y); 625 if (m == null) { 626 m = new Matrix(); 627 m.reset(); 628 return m; 629 } 630 Point translate = getTranslation(); 631 float scaleFactor = getScaleFactor(); 632 m.postTranslate(translate.x, translate.y); 633 m.postScale(scaleFactor, scaleFactor, mImageShowSize.x / 2.0f, mImageShowSize.y / 2.0f); 634 return m; 635 } 636 getScreenToImageMatrix(boolean reflectRotation)637 private Matrix getScreenToImageMatrix(boolean reflectRotation) { 638 Matrix m = getImageToScreenMatrix(reflectRotation); 639 Matrix invert = new Matrix(); 640 m.invert(invert); 641 return invert; 642 } 643 needsUpdateHighResPreview()644 public void needsUpdateHighResPreview() { 645 if (!mSupportsHighRes) { 646 return; 647 } 648 if (mActivity.getProcessingService() == null) { 649 return; 650 } 651 if (mPreset == null) { 652 return; 653 } 654 mActivity.getProcessingService().postHighresRenderingRequest(mPreset, 655 getScaleFactor(), this); 656 invalidateHighresPreview(); 657 } 658 needsUpdatePartialPreview()659 public void needsUpdatePartialPreview() { 660 if (mPreset == null) { 661 return; 662 } 663 if (!mPreset.canDoPartialRendering()) { 664 invalidatePartialPreview(); 665 return; 666 } 667 Matrix originalToScreen = MasterImage.getImage().originalImageToScreen(); 668 if (originalToScreen == null) { 669 return; 670 } 671 Matrix screenToOriginal = new Matrix(); 672 originalToScreen.invert(screenToOriginal); 673 RectF bounds = new RectF(0, 0, 674 mImageShowSize.x + 2 * mShadowMargin, 675 mImageShowSize.y + 2 * mShadowMargin); 676 screenToOriginal.mapRect(bounds); 677 Rect rBounds = new Rect(); 678 bounds.roundOut(rBounds); 679 680 mActivity.getProcessingService().postFullresRenderingRequest(mPreset, 681 getScaleFactor(), rBounds, 682 new Rect(0, 0, mImageShowSize.x, mImageShowSize.y), this); 683 invalidatePartialPreview(); 684 } 685 686 @Override available(RenderingRequest request)687 public void available(RenderingRequest request) { 688 if (request.getBitmap() == null) { 689 return; 690 } 691 692 boolean needsCheckModification = false; 693 if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) { 694 mBitmapCache.cache(mGeometryOnlyBitmap); 695 mGeometryOnlyBitmap = request.getBitmap(); 696 needsCheckModification = true; 697 } 698 if (request.getType() == RenderingRequest.FILTERS_RENDERING) { 699 mBitmapCache.cache(mFiltersOnlyBitmap); 700 mFiltersOnlyBitmap = request.getBitmap(); 701 notifyObservers(); 702 needsCheckModification = true; 703 } 704 if (request.getType() == RenderingRequest.PARTIAL_RENDERING 705 && request.getScaleFactor() == getScaleFactor()) { 706 mBitmapCache.cache(mPartialBitmap); 707 mPartialBitmap = request.getBitmap(); 708 mPartialBounds.set(request.getBounds()); 709 notifyObservers(); 710 needsCheckModification = true; 711 } 712 if (request.getType() == RenderingRequest.HIGHRES_RENDERING) { 713 mBitmapCache.cache(mHighresBitmap); 714 mHighresBitmap = request.getBitmap(); 715 notifyObservers(); 716 needsCheckModification = true; 717 } 718 if (needsCheckModification) { 719 mActivity.enableSave(hasModifications()); 720 } 721 } 722 reset()723 public static void reset() { 724 sMasterImage = null; 725 } 726 getScaleFactor()727 public float getScaleFactor() { 728 return mScaleFactor; 729 } 730 setScaleFactor(float scaleFactor)731 public void setScaleFactor(float scaleFactor) { 732 if (DISABLEZOOM) { 733 return; 734 } 735 if (scaleFactor == mScaleFactor) { 736 return; 737 } 738 mScaleFactor = scaleFactor; 739 invalidatePartialPreview(); 740 } 741 getTranslation()742 public Point getTranslation() { 743 return mTranslation; 744 } 745 setTranslation(Point translation)746 public void setTranslation(Point translation) { 747 if (DISABLEZOOM) { 748 mTranslation.x = 0; 749 mTranslation.y = 0; 750 return; 751 } 752 mTranslation.x = translation.x; 753 mTranslation.y = translation.y; 754 needsUpdatePartialPreview(); 755 } 756 getOriginalTranslation()757 public Point getOriginalTranslation() { 758 return mOriginalTranslation; 759 } 760 setOriginalTranslation(Point originalTranslation)761 public void setOriginalTranslation(Point originalTranslation) { 762 if (DISABLEZOOM) { 763 return; 764 } 765 mOriginalTranslation.x = originalTranslation.x; 766 mOriginalTranslation.y = originalTranslation.y; 767 } 768 resetTranslation()769 public void resetTranslation() { 770 mTranslation.x = 0; 771 mTranslation.y = 0; 772 needsUpdatePartialPreview(); 773 } 774 getTemporaryThumbnailBitmap()775 public Bitmap getTemporaryThumbnailBitmap() { 776 if (mTemporaryThumbnail == null 777 && getOriginalBitmapSmall() != null) { 778 mTemporaryThumbnail = getOriginalBitmapSmall().copy(Bitmap.Config.ARGB_8888, true); 779 Canvas canvas = new Canvas(mTemporaryThumbnail); 780 canvas.drawARGB(200, 80, 80, 80); 781 } 782 return mTemporaryThumbnail; 783 } 784 getThumbnailBitmap()785 public Bitmap getThumbnailBitmap() { 786 return getOriginalBitmapSmall(); 787 } 788 getLargeThumbnailBitmap()789 public Bitmap getLargeThumbnailBitmap() { 790 return getOriginalBitmapLarge(); 791 } 792 getMaxScaleFactor()793 public float getMaxScaleFactor() { 794 if (DISABLEZOOM) { 795 return 1; 796 } 797 return mMaxScaleFactor; 798 } 799 setMaxScaleFactor(float maxScaleFactor)800 public void setMaxScaleFactor(float maxScaleFactor) { 801 mMaxScaleFactor = maxScaleFactor; 802 } 803 supportsHighRes()804 public boolean supportsHighRes() { 805 return mSupportsHighRes; 806 } 807 setShowsOriginal(boolean value)808 public void setShowsOriginal(boolean value) { 809 mShowsOriginal = value; 810 notifyObservers(); 811 } 812 showsOriginal()813 public boolean showsOriginal() { 814 return mShowsOriginal; 815 } 816 setLoadedPreset(ImagePreset preset)817 public void setLoadedPreset(ImagePreset preset) { 818 mLoadedPreset = preset; 819 } 820 getLoadedPreset()821 public ImagePreset getLoadedPreset() { 822 return mLoadedPreset; 823 } 824 getEXIF()825 public List<ExifTag> getEXIF() { 826 return mEXIF; 827 } 828 getBitmapCache()829 public BitmapCache getBitmapCache() { 830 return mBitmapCache; 831 } 832 hasTinyPlanet()833 public boolean hasTinyPlanet() { 834 return mPreset.contains(FilterRepresentation.TYPE_TINYPLANET); 835 } 836 } 837