HardikKubavat

CropperImageView

Aug 14th, 2016
182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.33 KB | None | 0 0
  1. public class CropperImageView extends ImageView {
  2.  
  3. private static final String TAG = "CropperImageView";
  4.  
  5. private float[] mMatrixValues = new float[9];
  6.  
  7. protected GestureDetector mGestureDetector;
  8. private GestureListener mGestureListener;
  9.  
  10. protected ScaleGestureDetector mScaleDetector;
  11. private ScaleListener mScaleListener;
  12.  
  13. private float mMinZoom;
  14. private float mMaxZoom;
  15. private float mBaseZoom;
  16.  
  17. private float mFocusX;
  18. private float mFocusY;
  19.  
  20. private boolean isMaxZoomSet = false;
  21. private boolean mFirstRender = true;
  22.  
  23. private Bitmap mBitmap;
  24. private boolean doPreScaling = false;
  25. private float mPreScale;
  26.  
  27. private boolean mAddPaddingToMakeSquare = true;
  28.  
  29. private GestureCallback mGestureCallback;
  30.  
  31. private boolean showAnimation = true;
  32. private boolean isAdjusting = false;
  33.  
  34. private int mPaintColor = Color.WHITE;
  35.  
  36. public boolean DEBUG = true;
  37.  
  38. private boolean gestureEnabled = true;
  39.  
  40. public CropperImageView(Context context) {
  41. super(context);
  42. init(context, null);
  43. }
  44.  
  45. public CropperImageView(Context context, AttributeSet attrs) {
  46. super(context, attrs);
  47. init(context, attrs);
  48. }
  49.  
  50. public CropperImageView(Context context, AttributeSet attrs, int defStyleAttr) {
  51. super(context, attrs, defStyleAttr);
  52. init(context, attrs);
  53. }
  54.  
  55. @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  56. public CropperImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
  57. super(context, attrs, defStyleAttr, defStyleRes);
  58. init(context, attrs);
  59. }
  60.  
  61. public void setDEBUG(boolean DEBUG) {
  62. this.DEBUG = DEBUG;
  63. }
  64.  
  65. private void init(Context context, AttributeSet attrs) {
  66.  
  67. if (attrs != null) {
  68. TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CropperView);
  69. mPaintColor = mTypedArray.getColor(R.styleable.CropperView_padding_color, mPaintColor);
  70. mAddPaddingToMakeSquare = mTypedArray.getBoolean(R.styleable.CropperView_add_padding_to_make_square, true);
  71. }
  72.  
  73. mGestureListener = new GestureListener();
  74. mGestureDetector = new GestureDetector(context, mGestureListener, null, true);
  75. mScaleListener = new ScaleListener();
  76. mScaleDetector = new ScaleGestureDetector(context, mScaleListener);
  77.  
  78. setScaleType(ScaleType.MATRIX);
  79. }
  80.  
  81. // Make Square
  82. @Override
  83. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  84. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  85. int orientation = getContext().getResources().getConfiguration().orientation;
  86.  
  87. if (orientation == Configuration.ORIENTATION_PORTRAIT ||
  88. orientation == Configuration.ORIENTATION_UNDEFINED) {
  89.  
  90. int width = MeasureSpec.getSize(widthMeasureSpec);
  91. int height = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
  92. setMeasuredDimension(width, height);
  93.  
  94. } else {
  95.  
  96. int height = MeasureSpec.getSize(heightMeasureSpec);
  97. int width = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
  98. setMeasuredDimension(width, height);
  99.  
  100. }
  101. }
  102.  
  103. @Override
  104. protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  105. super.onLayout(changed, left, top, right, bottom);
  106. if (DEBUG) {
  107. Log.i(TAG, "onLayout: " + changed + " [" + left + ", " + top + ", " + right + ", " + bottom + "]");
  108. }
  109.  
  110. if (changed || mFirstRender) {
  111.  
  112. if (mFirstRender) {
  113. final Drawable drawable = getDrawable();
  114. if (drawable == null) {
  115. if (DEBUG) {
  116. Log.e(TAG, "drawable is null");
  117. }
  118. return;
  119. }
  120.  
  121. mMinZoom = (float)(bottom - top) / Math.max(drawable.getIntrinsicHeight(),
  122. drawable.getIntrinsicWidth());
  123. mBaseZoom = (float)(bottom - top)/ Math.min(drawable.getIntrinsicHeight(),
  124. drawable.getIntrinsicWidth());
  125.  
  126. fitToCenter(drawable, bottom - top);
  127. mFirstRender = false;
  128.  
  129. }
  130. }
  131.  
  132. }
  133.  
  134. @Override
  135. public boolean onTouchEvent(MotionEvent event) {
  136.  
  137. if (isAdjusting) {
  138. return true;
  139. }
  140.  
  141. final int action = event.getActionMasked();
  142.  
  143. if (action == MotionEvent.ACTION_DOWN) {
  144. if (mGestureCallback != null) {
  145. mGestureCallback.onGestureStarted();
  146. }
  147. }
  148.  
  149. mScaleDetector.onTouchEvent(event);
  150.  
  151. if (!mScaleDetector.isInProgress()) {
  152. mGestureDetector.onTouchEvent(event);
  153. }
  154.  
  155. switch (event.getAction()) {
  156. case MotionEvent.ACTION_UP:
  157.  
  158. if(mGestureCallback != null) {
  159. mGestureCallback.onGestureCompleted();
  160. }
  161.  
  162. return onUp(event);
  163.  
  164. }
  165.  
  166. return true;
  167. }
  168.  
  169. @Override
  170. public void setImageBitmap(Bitmap bm) {
  171. mFirstRender = true;
  172. if (bm == null) {
  173. mBitmap = null;
  174. super.setImageBitmap(null);
  175. return;
  176. }
  177.  
  178. if (bm.getHeight() > 1280 || bm.getWidth() > 1280) {
  179. Log.w(TAG, "Bitmap size greater than 1280. This might cause memory issues");
  180. }
  181.  
  182. mBitmap = bm;
  183.  
  184. if (doPreScaling) {
  185. int max_param = Math.max(bm.getWidth(), bm.getHeight());
  186. mPreScale = (float) max_param / (float) getWidth();
  187.  
  188. Bitmap scaledBitmap = Bitmap.createScaledBitmap(bm, (int) (bm.getWidth() / mPreScale),
  189. (int) (bm.getHeight() / mPreScale), false);
  190. super.setImageBitmap(scaledBitmap);
  191. } else {
  192. mPreScale = 1f;
  193. super.setImageBitmap(bm);
  194. }
  195. requestLayout();
  196. }
  197.  
  198. public void replaceBitmap(Bitmap bitmap) {
  199. if (bitmap == null) {
  200. throw new NullPointerException("Can not replace with null bitmap");
  201. }
  202.  
  203. if (mBitmap == null) {
  204. setImageBitmap(bitmap);
  205. return;
  206. }
  207.  
  208. if (mBitmap.getWidth() != bitmap.getWidth() || mBitmap.getHeight() != bitmap.getHeight()) {
  209. Log.e(TAG, "Bitmap is of different size. Not replacing");
  210. // return;
  211. }
  212.  
  213. super.setImageBitmap(bitmap);
  214. mBitmap = bitmap;
  215. }
  216.  
  217.  
  218.  
  219. public void rotate(int rotateAngle)
  220. {
  221. Matrix matrix = getImageMatrix();
  222.  
  223.  
  224. float tx = getMatrixValue(matrix, Matrix.MTRANS_X);
  225. float ty = getMatrixValue(matrix, Matrix.MTRANS_Y);
  226.  
  227. float scaleX = getMatrixValue(matrix, Matrix.MSCALE_X);
  228. float scaleY = getMatrixValue(matrix, Matrix.MSCALE_Y);
  229.  
  230. float skewX = getMatrixValue(matrix, Matrix.MSKEW_X);
  231. float skewY = getMatrixValue(matrix, Matrix.MSKEW_Y);
  232.  
  233. //calculating the actual scale
  234. float sx = (float)Math.sqrt((scaleX*scaleX)+(skewY*skewY));
  235. float sy = (float)Math.sqrt((scaleY*scaleY)+(skewX*skewX));
  236.  
  237. //calculate the angle
  238. float rAngle = Math.round(Math.atan2(scaleX, skewX) * (180 / Math.PI));
  239.  
  240. Drawable drawable = getDrawable();
  241. if (drawable == null) {
  242.  
  243. return ;
  244. }
  245.  
  246. //calculate the actual width and height of drawable
  247. float width = sx * drawable.getIntrinsicWidth();
  248. float height = sy * drawable.getIntrinsicHeight();
  249.  
  250. //calculate the center points of drawable
  251. float cx = (width/2)+tx;
  252. float cy = (height/2)+ty;
  253.  
  254. float newX = (float)(tx*Math.cos(rotateAngle) - ty*Math.sin(rotateAngle));
  255. float newY = (float)(tx*Math.sin(rotateAngle) + ty*Math.cos(rotateAngle));
  256.  
  257.  
  258.  
  259. // float newX = (float)((tx-cx)*Math.cos(rotateAngle) - (ty-cy)*Math.sin(rotateAngle)+cx);
  260. // float newY = (float)((tx-cx)*Math.sin(rotateAngle) + (ty-cy)*Math.cos(rotateAngle)+cy);
  261.  
  262. // float x = (mPosX*(cos(angle) + sin(angle)) / mScaleFactor;
  263. // float y = (mPosY*(cos(angle) - sin(angle)) / mScaleFactor;
  264.  
  265. // float newX = (float)(((tx)*Math.cos(rotateAngle))+Math.sin(rotateAngle))/ sx ;
  266. // float newY = (float)(((ty)*Math.cos(rotateAngle))-+Math.sin(rotateAngle))/ sy ;
  267.  
  268. if (DEBUG) {
  269.  
  270. Log.e(TAG, "onUp: " + tx + " " + ty);
  271. Log.e(TAG, "scaleX: " + scaleX+" scaleY: " + scaleY);
  272. Log.e(TAG, "scaleX new : " + sx+" scaleY new: " + sy);
  273. Log.e(TAG, "Rotate Angle: " + rAngle);
  274. Log.e(TAG, "drawable size: " + drawable.getIntrinsicWidth() + " " + drawable.getIntrinsicHeight());
  275. Log.e(TAG, "Rotate Angle: " + rotateAngle);
  276. Log.e(TAG, "x center : " + (width/2)+tx + " y center " + (height/2)+ty);
  277. }
  278.  
  279.  
  280.  
  281.  
  282. //works well on first time only
  283. // matrix.postTranslate(-cx , -cy);
  284. // matrix.postRotate(rotateAngle);
  285. // matrix.postTranslate(cx , cy);
  286.  
  287. // work same as uper combination
  288. matrix.postRotate(rotateAngle, cx , cy);
  289.  
  290.  
  291. // what should i have to do for rotate every time without change the position of bitmap..?
  292.  
  293. setImageMatrix(matrix);
  294.  
  295. invalidate();
  296.  
  297. }
  298.  
  299.  
  300.  
  301. public void setColorMatrixFilter(ColorMatrixColorFilter matrixfilter) {
  302.  
  303. setColorFilter(matrixfilter);
  304. }
  305.  
  306.  
  307.  
  308. public void flip(String flipmode)
  309. {
  310. Matrix matrix = getImageMatrix();
  311.  
  312. float tx = getMatrixValue(matrix, Matrix.MTRANS_X);
  313. float ty = getMatrixValue(matrix, Matrix.MTRANS_Y);
  314.  
  315. float scaleX = getMatrixValue(matrix, Matrix.MSCALE_X);
  316. float scaleY = getMatrixValue(matrix, Matrix.MSCALE_Y);
  317.  
  318. Drawable drawable = getDrawable();
  319. if (drawable == null) {
  320.  
  321. return ;
  322. }
  323.  
  324. float width = scaleX * drawable.getIntrinsicWidth();
  325. float height = scaleY * drawable.getIntrinsicHeight();
  326.  
  327. float skewX = getMatrixValue(matrix, Matrix.MSKEW_X);
  328. float rAngle = Math.round(Math.atan2(scaleX, skewX) * (180 / Math.PI));
  329.  
  330. if (DEBUG) {
  331.  
  332. Log.e(TAG, "onUp: " + tx + " " + ty);
  333. Log.e(TAG, "scaleX: " + scaleX+" scaleY: " + scaleY);
  334. Log.e(TAG, "drawable size: " + drawable.getIntrinsicWidth() + " " + drawable.getIntrinsicHeight());
  335. Log.e(TAG, "Rotate Angle: " + rAngle);
  336. Log.e(TAG, "x center : " + (width/2)+tx + " y center " + (height/2)+ty);
  337. }
  338.  
  339. if (flipmode == "ORIENTATION_FLIP_HORIZONTAL") {
  340.  
  341. matrix.postScale(-1.0f, 1.0f, (width / 2) + tx, (height / 2) + ty);
  342.  
  343. } else if (flipmode == "ORIENTATION_FLIP_VERTICAL") {
  344.  
  345.  
  346. matrix.postScale(1.0f, -1.0f, (width / 2) + tx, (height / 2) + ty);
  347.  
  348. }
  349.  
  350.  
  351. setImageMatrix(matrix);
  352. invalidate();
  353.  
  354. }
  355.  
  356. private void cropToCenter(Drawable drawable, int frameDimen) {
  357.  
  358. if (drawable == null) {
  359. if (DEBUG) {
  360. Log.e(TAG, "Drawable is null. I can't fit anything");
  361. }
  362. return;
  363. }
  364.  
  365. if (frameDimen == 0) {
  366. if (DEBUG) {
  367. Log.e(TAG, "Frame Dimension is 0. I'm quite boggled by it.");
  368. }
  369. return;
  370. }
  371.  
  372. int width = drawable.getIntrinsicWidth();
  373. int height = drawable.getIntrinsicHeight();
  374. if (DEBUG) {
  375. Log.i(TAG, "drawable size: (" + width + " ," + height + ")");
  376. }
  377.  
  378. int min_dimen = Math.min(width, height);
  379. float scaleFactor = (float)min_dimen/(float)frameDimen;
  380.  
  381. Matrix matrix = new Matrix();
  382. matrix.setScale(1f / scaleFactor, 1f / scaleFactor);
  383. matrix.postTranslate((frameDimen - width / scaleFactor) / 2,
  384. (frameDimen - height / scaleFactor) / 2);
  385. setImageMatrix(matrix);
  386. }
  387.  
  388. private void fitToCenter(Drawable drawable, int frameDimen) {
  389.  
  390. if (drawable == null) {
  391. if (DEBUG) {
  392. Log.e(TAG, "Drawable is null. I can't fit anything");
  393. }
  394. return;
  395. }
  396.  
  397. if (frameDimen == 0) {
  398. if (DEBUG) {
  399. Log.e(TAG, "Frame Dimension is 0. I'm quite boggled by it.");
  400. }
  401. return;
  402. }
  403.  
  404. int width = drawable.getIntrinsicWidth();
  405. int height = drawable.getIntrinsicHeight();
  406. if (DEBUG) {
  407. Log.i(TAG, "drawable size: (" + width + " ," + height + ")");
  408. }
  409.  
  410. int min_dimen = Math.max(width, height);
  411. float scaleFactor = (float)min_dimen/(float)frameDimen;
  412.  
  413. Matrix matrix = new Matrix();
  414. matrix.setScale(1f / scaleFactor, 1f / scaleFactor);
  415. matrix.postTranslate((frameDimen - width / scaleFactor) / 2,
  416. (frameDimen - height / scaleFactor) / 2);
  417. setImageMatrix(matrix);
  418. }
  419.  
  420. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  421.  
  422. Matrix matrix = getImageMatrix();
  423. matrix.postTranslate(-distanceX, -distanceY);
  424. setImageMatrix(matrix);
  425.  
  426. invalidate();
  427. return true;
  428. }
  429.  
  430. private boolean onUp(MotionEvent event) {
  431.  
  432. Drawable drawable = getDrawable();
  433. if (drawable == null) {
  434. return false;
  435. }
  436.  
  437. // If over scrolled, return back to the place.
  438. Matrix matrix = getImageMatrix();
  439. float tx = getMatrixValue(matrix, Matrix.MTRANS_X);
  440. float ty = getMatrixValue(matrix, Matrix.MTRANS_Y);
  441. float scaleX = getMatrixValue(matrix, Matrix.MSCALE_X);
  442. float scaleY = getMatrixValue(matrix, Matrix.MSCALE_Y);
  443.  
  444. if (DEBUG) {
  445. Log.i(TAG, "onUp: " + tx + " " + ty);
  446. Log.i(TAG, "scale: " + scaleX);
  447. Log.i(TAG, "min, max, base zoom: " + mMinZoom + ", " + mMaxZoom + ", " + mBaseZoom);
  448. Log.i(TAG, "imageview size: " + getWidth() + " " + getHeight());
  449. Log.i(TAG, "drawable size: " + drawable.getIntrinsicWidth() + " " + drawable.getIntrinsicHeight());
  450. Log.i(TAG, "scaled drawable size: " + scaleX * drawable.getIntrinsicWidth() + " " + scaleY * drawable.getIntrinsicHeight());
  451. }
  452.  
  453. if (scaleX <= mMinZoom) {
  454. if (DEBUG) {
  455. Log.i(TAG, "set scale: " + mMinZoom);
  456. }
  457.  
  458. float xx = getWidth()/2 - mMinZoom * drawable.getIntrinsicWidth()/2;
  459. float yy = getHeight()/2 - mMinZoom * drawable.getIntrinsicHeight()/2;
  460.  
  461. if (showAnimation()) {
  462.  
  463. // animateAdjustmentWithScale(tx, xx, ty, yy, scaleX, mMinZoom);
  464.  
  465. } else {
  466. matrix.reset();
  467. matrix.setScale(mMinZoom, mMinZoom);
  468. matrix.postTranslate(xx, yy);
  469. setImageMatrix(matrix);
  470. invalidate();
  471. if (DEBUG) {
  472. Log.i(TAG, "scale after invalidate: " + getScale(matrix));
  473. }
  474. }
  475. return true;
  476. } else if (scaleX < mBaseZoom) {
  477.  
  478. // align to center for the smaller dimension
  479. int h = drawable.getIntrinsicHeight();
  480. int w = drawable.getIntrinsicWidth();
  481.  
  482. float xTranslate;
  483. float yTranslate;
  484.  
  485. if(h <= w) {
  486. yTranslate = getHeight()/2 - scaleX * h/2;
  487.  
  488. if (tx >= 0) {
  489. xTranslate = 0;
  490. } else {
  491. float xDiff = getWidth() - (scaleX) * drawable.getIntrinsicWidth();
  492. if (tx < xDiff) {
  493. xTranslate = xDiff;
  494. } else {
  495. xTranslate = tx;
  496. }
  497. }
  498.  
  499. } else {
  500. xTranslate = getWidth()/2 - scaleX * w/2;
  501.  
  502. if(ty >= 0) {
  503. yTranslate = 0;
  504. } else {
  505. float yDiff = getHeight() - (scaleY) * drawable.getIntrinsicHeight();
  506. if (ty < yDiff) {
  507. yTranslate = yDiff;
  508. } else {
  509. yTranslate = ty;
  510. }
  511. }
  512. }
  513.  
  514. if (showAnimation()) {
  515. matrix.reset();
  516. matrix.postScale(scaleX, scaleX);
  517. matrix.postTranslate(tx, ty);
  518. setImageMatrix(matrix);
  519.  
  520. // animateAdjustment(xTranslate - tx, yTranslate - ty);
  521.  
  522. } else {
  523. matrix.reset();
  524. matrix.postScale(scaleX, scaleX);
  525. matrix.postTranslate(xTranslate, yTranslate);
  526. setImageMatrix(matrix);
  527. invalidate();
  528. }
  529.  
  530. return true;
  531.  
  532. } else if (isMaxZoomSet && scaleX > mMaxZoom) {
  533.  
  534. if(DEBUG) {
  535. Log.i(TAG, "set to max zoom");
  536. Log.i(TAG, "isMaxZoomSet: " + isMaxZoomSet);
  537. }
  538.  
  539. if (showAnimation()) {
  540. // animateOverMaxZoomAdjustment();
  541. // adjustToSides();
  542. } else {
  543. matrix.postScale(mMaxZoom / scaleX, mMaxZoom / scaleX, mFocusX, mFocusY);
  544. setImageMatrix(matrix);
  545. invalidate();
  546. adjustToSides();
  547. }
  548. return true;
  549. }
  550.  
  551. if (DEBUG) {
  552. Log.i(TAG, "adjust to sides");
  553. }
  554. adjustToSides();
  555. return true;
  556. }
  557.  
  558. private boolean adjustToSides() {
  559. boolean changeRequired = false;
  560.  
  561. Drawable drawable = getDrawable();
  562. if (drawable == null) {
  563. return changeRequired;
  564. }
  565.  
  566. Matrix matrix = getImageMatrix();
  567.  
  568. float sx = getMatrixValue(matrix, Matrix.MTRANS_X);
  569. float sy = getMatrixValue(matrix, Matrix.MTRANS_Y);
  570. float tx = getMatrixValue(matrix, Matrix.MTRANS_X);
  571. float ty = getMatrixValue(matrix, Matrix.MTRANS_Y);
  572. float scaleX = getMatrixValue(matrix, Matrix.MSCALE_X);
  573. float scaleY = getMatrixValue(matrix, Matrix.MSCALE_Y);
  574.  
  575. if (tx > 0) {
  576. tx = -tx;
  577. changeRequired = true;
  578. } else {
  579.  
  580. // check if scrolled to left
  581. float xDiff = getWidth() - (scaleX) * drawable.getIntrinsicWidth();
  582. if (tx < xDiff) {
  583. tx = xDiff - tx;
  584. changeRequired = true;
  585. } else {
  586. tx = 0;
  587. }
  588. }
  589.  
  590. if (ty > 0) {
  591. ty = -ty;
  592. changeRequired = true;
  593. } else {
  594.  
  595. // check if scrolled to top
  596. float yDiff = getHeight() - (scaleY) * drawable.getIntrinsicHeight();
  597. if (ty < yDiff) {
  598. ty = yDiff - ty;
  599. changeRequired = true;
  600. } else {
  601. ty = 0;
  602. }
  603. }
  604.  
  605. if (changeRequired) {
  606.  
  607. if (showAnimation()) {
  608. // animateAdjustment(tx, ty);
  609. } else {
  610. matrix.postTranslate(tx, ty);
  611. setImageMatrix(matrix);
  612. invalidate();
  613. }
  614. }
  615.  
  616. return changeRequired;
  617. }
  618.  
  619. private float getMatrixValue(Matrix matrix, int whichValue) {
  620. matrix.getValues(mMatrixValues);
  621. return mMatrixValues[whichValue];
  622. }
  623.  
  624. private float getScale(Matrix matrix) {
  625. return getMatrixValue(matrix, Matrix.MSCALE_X);
  626. }
  627.  
  628. public boolean isDoPreScaling() {
  629. return doPreScaling;
  630. }
  631.  
  632. public void setDoPreScaling(boolean doPreScaling) {
  633. this.doPreScaling = doPreScaling;
  634. }
  635.  
  636. public float getMaxZoom() {
  637. return mMaxZoom;
  638. }
  639.  
  640. public void setMaxZoom(float mMaxZoom) {
  641.  
  642. if (mMaxZoom <= 0) {
  643. Log.e(TAG, "Max zoom must be greater than 0");
  644. return;
  645. }
  646.  
  647. this.mMaxZoom = mMaxZoom;
  648. isMaxZoomSet = true;
  649. }
  650.  
  651. public float getMinZoom() {
  652. return mMinZoom;
  653. }
  654.  
  655. public void setMinZoom(float mMInZoom) {
  656. if (mMInZoom <= 0) {
  657. Log.e(TAG, "Min zoom must be greater than 0");
  658. return;
  659. }
  660.  
  661. this.mMinZoom = mMInZoom;
  662. }
  663.  
  664. public void cropToCenter() {
  665. Drawable drawable = getDrawable();
  666. if (drawable != null) {
  667. cropToCenter(drawable, getWidth());
  668. }
  669. }
  670.  
  671. public void fitToCenter() {
  672. Drawable drawable = getDrawable();
  673. if (drawable != null) {
  674. fitToCenter(drawable, getWidth());
  675. }
  676. }
  677.  
  678. public Bitmap getCroppedBitmap() {
  679. if (mBitmap == null) {
  680. Log.e(TAG, "original image is not available");
  681. return null;
  682. }
  683.  
  684. Matrix matrix = getImageMatrix();
  685.  
  686. if (doPreScaling) {
  687. matrix.postScale(1/mPreScale, 1/mPreScale);
  688. }
  689.  
  690. float xTrans = getMatrixValue(matrix, Matrix.MTRANS_X);
  691. float yTrans = getMatrixValue(matrix, Matrix.MTRANS_Y);
  692. float scale = getMatrixValue(matrix, Matrix.MSCALE_X);
  693.  
  694. if (DEBUG) {
  695. Log.i(TAG, "xTrans: " + xTrans + ", yTrans: " + yTrans + " , scale: " + scale);
  696. }
  697.  
  698. Bitmap bitmap;
  699. if (DEBUG) {
  700. Log.i(TAG, "old bitmap: " + mBitmap.getWidth() + " " + mBitmap.getHeight());
  701. }
  702.  
  703. if (xTrans > 0 && yTrans > 0 && scale <= mMinZoom) {
  704. // No scale/crop required.
  705. // Add padding if not square
  706. if (mAddPaddingToMakeSquare) {
  707. return LibBitmapUtils.addPadding(mBitmap, mPaintColor);
  708. } else {
  709. return mBitmap;
  710. }
  711.  
  712. } else {
  713.  
  714. float cropY = - yTrans / scale;
  715. float Y = getHeight() / scale;
  716. float cropX = -xTrans / scale;
  717. float X = getWidth() / scale;
  718.  
  719. if (DEBUG) {
  720. Log.i(TAG, "cropY: " + cropY);
  721. Log.i(TAG, "Y: " + Y);
  722. Log.i(TAG, "cropX: " + cropX);
  723. Log.i(TAG, "X: " + X);
  724. }
  725.  
  726. if (cropY + Y > mBitmap.getHeight()) {
  727. cropY = mBitmap.getHeight() - Y;
  728. if (DEBUG) {
  729. Log.i(TAG, "readjust cropY to: " + cropY);
  730. }
  731. } else if (cropY < 0) {
  732. cropY = 0;
  733. if (DEBUG) {
  734. Log.i(TAG, "readjust cropY to: " + cropY);
  735. }
  736. }
  737.  
  738. if (cropX + X > mBitmap.getWidth()) {
  739. cropX = mBitmap.getWidth() - X;
  740. if (DEBUG) {
  741. Log.i(TAG, "readjust cropX to: " + cropX);
  742. }
  743. } else if (cropX < 0) {
  744. cropX = 0;
  745. if (DEBUG) {
  746. Log.i(TAG, "readjust cropX to: " + cropX);
  747. }
  748. }
  749.  
  750. if (mBitmap.getHeight() > mBitmap.getWidth()) {
  751. // Height is greater than width.
  752. if (xTrans >= 0) {
  753. // Image is zoomed. Crop from height and add padding to make square
  754. bitmap = Bitmap.createBitmap(mBitmap, 0, (int)cropY, mBitmap.getWidth(), (int)Y,
  755. null, true);
  756.  
  757. if (mAddPaddingToMakeSquare) {
  758. bitmap = LibBitmapUtils.addPadding(bitmap, mPaintColor);
  759. }
  760.  
  761. } else {
  762. // Crop from width and height both
  763. bitmap = Bitmap.createBitmap(mBitmap, (int) cropX, (int)cropY, (int)X, (int)Y,
  764. null, true);
  765. }
  766. } else {
  767. if (yTrans >= 0) {
  768. // Image is zoomed. Crop from width and add padding to make square
  769. bitmap = Bitmap.createBitmap(mBitmap, (int)cropX, 0, (int)X, mBitmap.getHeight(),
  770. null, true);
  771.  
  772. if (mAddPaddingToMakeSquare) {
  773. bitmap = LibBitmapUtils.addPadding(bitmap, mPaintColor);
  774. }
  775.  
  776. } else {
  777. // Crop from width and height both.
  778. bitmap = Bitmap.createBitmap(mBitmap, (int) cropX, (int)cropY, (int)X, (int)Y,
  779. null, true);
  780.  
  781. }
  782.  
  783. if (DEBUG) {
  784. Log.i(TAG, "width should be: " + mBitmap.getWidth());
  785. Log.i(TAG, "crop bitmap: " + bitmap.getWidth() + " " + bitmap.getHeight());
  786. }
  787. }
  788. }
  789.  
  790. return bitmap;
  791. }
  792.  
  793. public boolean showAnimation() {
  794. return showAnimation;
  795. }
  796.  
  797. public void setShowAnimation(boolean showAnimation) {
  798. this.showAnimation = showAnimation;
  799. }
  800.  
  801. public int getPaddingColor() {
  802. return mPaintColor;
  803. }
  804.  
  805. public void setPaddingColor(int mPaintColor) {
  806. this.mPaintColor = mPaintColor;
  807. }
  808.  
  809. public boolean isMakeSquare() {
  810. return mAddPaddingToMakeSquare;
  811. }
  812.  
  813. public void setMakeSquare(boolean mAddPaddingToMakeSquare) {
  814. this.mAddPaddingToMakeSquare = mAddPaddingToMakeSquare;
  815. }
  816.  
  817. public boolean isGestureEnabled() {
  818. return gestureEnabled;
  819. }
  820.  
  821. public void setGestureEnabled(boolean gestureEnabled) {
  822. this.gestureEnabled = gestureEnabled;
  823. }
  824.  
  825. public void release() {
  826. setImageBitmap(null);
  827. if (mBitmap != null) {
  828. mBitmap.recycle();
  829. }
  830. }
  831.  
  832. // Scroll and Gesture Listeners
  833. private class GestureListener extends GestureDetector.SimpleOnGestureListener {
  834. @Override
  835. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  836. if (!gestureEnabled) {
  837. return false;
  838. }
  839.  
  840. if (e1 == null || e2 == null) {
  841. return false;
  842. }
  843. if (e1.getPointerCount() > 1 || e2.getPointerCount() > 1) {
  844. return false;
  845. }
  846.  
  847. CropperImageView.this.onScroll(e1, e2, distanceX, distanceY);
  848. return false;
  849. }
  850.  
  851. }
  852.  
  853. private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
  854. protected boolean mScaled = false;
  855.  
  856. @Override
  857. public boolean onScale(ScaleGestureDetector detector) {
  858. if (!gestureEnabled) {
  859. return false;
  860. }
  861.  
  862. Matrix matrix = getImageMatrix();
  863. // This does the trick!
  864. mFocusX = detector.getFocusX();
  865. mFocusY = detector.getFocusY();
  866.  
  867. matrix.postScale(detector.getScaleFactor(), detector.getScaleFactor(),
  868. detector.getFocusX(), detector.getFocusY());
  869.  
  870. setImageMatrix(matrix);
  871. invalidate();
  872. return true;
  873. }
  874. }
  875.  
  876. public void setGestureCallback(GestureCallback mGestureCallback) {
  877. this.mGestureCallback = mGestureCallback;
  878. }
  879.  
  880. public interface GestureCallback {
  881. void onGestureStarted();
  882. void onGestureCompleted();
  883. }
  884.  
  885. }
Add Comment
Please, Sign In to add comment