Java Code Examples for android.graphics.Matrix#postTranslate()

The following examples show how to use android.graphics.Matrix#postTranslate() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may want to check out the right sidebar which shows the related API usage.
Example 1
Source Project: fresco   File: DefaultZoomableController.java    License: MIT License 6 votes vote down vote up
/**
 * Calculates the zoom transformation based on the current gesture.
 *
 * @param outTransform the matrix to store the result to
 * @param limitTypes whether to limit translation and/or scale.
 * @return whether or not the transform has been corrected due to limitation
 */
protected boolean calculateGestureTransform(Matrix outTransform, @LimitFlag int limitTypes) {
  TransformGestureDetector detector = mGestureDetector;
  boolean transformCorrected = false;
  outTransform.set(mPreviousTransform);
  if (mIsRotationEnabled) {
    float angle = detector.getRotation() * (float) (180 / Math.PI);
    outTransform.postRotate(angle, detector.getPivotX(), detector.getPivotY());
  }
  if (mIsScaleEnabled) {
    float scale = detector.getScale();
    outTransform.postScale(scale, scale, detector.getPivotX(), detector.getPivotY());
  }
  transformCorrected |=
      limitScale(outTransform, detector.getPivotX(), detector.getPivotY(), limitTypes);
  if (mIsTranslationEnabled) {
    outTransform.postTranslate(detector.getTranslationX(), detector.getTranslationY());
  }
  transformCorrected |= limitTranslation(outTransform, limitTypes);
  return transformCorrected;
}
 
Example 2
Source Project: fresco   File: ScalingUtils.java    License: MIT License 6 votes vote down vote up
@Override
public void getTransformImpl(
    Matrix outTransform,
    Rect parentRect,
    int childWidth,
    int childHeight,
    float focusX,
    float focusY,
    float scaleX,
    float scaleY) {
  float scale, dx, dy;
  scale = scaleY;
  dx = parentRect.left + (parentRect.width() - childWidth * scale) * 0.5f;
  dy = parentRect.top;
  outTransform.setScale(scale, scale);
  outTransform.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
}
 
Example 3
Source Project: Sky31Radio   File: MarkerDrawable.java    License: Apache License 2.0 6 votes vote down vote up
private void computePath(Rect bounds) {
    final float currentScale = mCurrentScale;
    final Path path = mPath;
    final RectF rect = mRect;
    final Matrix matrix = mMatrix;

    path.reset();
    int totalSize = Math.min(bounds.width(), bounds.height());

    float initial = mClosedStateSize;
    float destination = totalSize;
    float currentSize = initial + (destination - initial) * currentScale;

    float halfSize = currentSize / 2f;
    float inverseScale = 1f - currentScale;
    float cornerSize = halfSize * inverseScale;
    float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize};
    rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize);
    path.addRoundRect(rect, corners, Path.Direction.CCW);
    matrix.reset();
    matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize);
    matrix.postTranslate((bounds.width() - currentSize) / 2, 0);
    float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale;
    matrix.postTranslate(0, hDiff);
    path.transform(matrix);
}
 
Example 4
private void setBaseMatrix(Bitmap bitmap, Matrix matrix) {
	float viewWidth = getWidth();
	float viewHeight = getHeight();

	matrix.reset();
	float widthScale = Math.min(viewWidth / (float)bitmap.getWidth(), 1.0f);
	float heightScale = Math.min(viewHeight / (float)bitmap.getHeight(), 1.0f);
	float scale;
	if (widthScale > heightScale) {
		scale = heightScale;
	} else {
		scale = widthScale;
	}
	matrix.setScale(scale, scale);
	matrix.postTranslate(
			(viewWidth  - ((float)bitmap.getWidth()  * scale))/2F, 
			(viewHeight - ((float)bitmap.getHeight() * scale))/2F);
}
 
Example 5
Source Project: android-tv-launcher   File: Rotate3dAnimation.java    License: MIT License 6 votes vote down vote up
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    final float fromDegrees = mFromDegrees;
    float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

    final float centerX = mCenterX;
    final float centerY = mCenterY;
    final Camera camera = mCamera;

    final Matrix matrix = t.getMatrix();

    camera.save();
    if (mReverse) {
        camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
    } else {
        camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
    }
    camera.rotateY(degrees);
    camera.getMatrix(matrix);
    camera.restore();

    matrix.preTranslate(-centerX, -centerY);
    matrix.postTranslate(centerX, centerY);
}
 
Example 6
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    final float fromDegrees = mFromDegrees;
    float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

    final float centerX = mCenterX;
    final float centerY = mCenterY;
    final Camera camera = mCamera;

    final Matrix matrix = t.getMatrix();

    camera.save();
    if (mReverse) {
        camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
    } else {
        camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
    }
    camera.rotateY(degrees);
    camera.getMatrix(matrix);
    camera.restore();

    matrix.preTranslate(-centerX, -centerY);
    matrix.postTranslate(centerX, centerY);
}
 
Example 7
Source Project: sketch   File: RotateImageProcessor.java    License: Apache License 2.0 6 votes vote down vote up
public static Bitmap rotate(@NonNull Bitmap bitmap, int degrees, @NonNull BitmapPool bitmapPool) {
    Matrix matrix = new Matrix();
    matrix.setRotate(degrees);

    // 根据旋转角度计算新的图片的尺寸
    RectF newRect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
    matrix.mapRect(newRect);
    int newWidth = (int) newRect.width();
    int newHeight = (int) newRect.height();

    // 角度不能整除90°时新图片会是斜的,因此要支持透明度,这样倾斜导致露出的部分就不会是黑的
    Bitmap.Config config = bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
    if (degrees % 90 != 0 && config != Bitmap.Config.ARGB_8888) {
        config = Bitmap.Config.ARGB_8888;
    }

    Bitmap result = bitmapPool.getOrMake(newWidth, newHeight, config);

    matrix.postTranslate(-newRect.left, -newRect.top);

    final Canvas canvas = new Canvas(result);
    final Paint paint = new Paint(Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
    canvas.drawBitmap(bitmap, matrix, paint);

    return result;
}
 
Example 8
Source Project: KJFrameForAndroid   File: AnimatorProxy.java    License: Apache License 2.0 5 votes vote down vote up
private void transformMatrix(Matrix m, View view) {
    final float w = view.getWidth();
    final float h = view.getHeight();
    final boolean hasPivot = mHasPivot;
    final float pX = hasPivot ? mPivotX : w / 2f;
    final float pY = hasPivot ? mPivotY : h / 2f;

    final float rX = mRotationX;
    final float rY = mRotationY;
    final float rZ = mRotationZ;
    if ((rX != 0) || (rY != 0) || (rZ != 0)) {
        final Camera camera = mCamera;
        camera.save();
        camera.rotateX(rX);
        camera.rotateY(rY);
        camera.rotateZ(-rZ);
        camera.getMatrix(m);
        camera.restore();
        m.preTranslate(-pX, -pY);
        m.postTranslate(pX, pY);
    }

    final float sX = mScaleX;
    final float sY = mScaleY;
    if ((sX != 1.0f) || (sY != 1.0f)) {
        m.postScale(sX, sY);
        final float sPX = -(pX / w) * ((sX * w) - w);
        final float sPY = -(pY / h) * ((sY * h) - h);
        m.postTranslate(sPX, sPY);
    }

    m.postTranslate(mTranslationX, mTranslationY);
}
 
Example 9
Source Project: timecat   File: AnimatorProxy.java    License: Apache License 2.0 5 votes vote down vote up
private void transformMatrix(Matrix m, View view) {
    final float w = view.getWidth();
    final float h = view.getHeight();
    final boolean hasPivot = mHasPivot;
    final float pX = hasPivot ? mPivotX : w / 2f;
    final float pY = hasPivot ? mPivotY : h / 2f;

    final float rX = mRotationX;
    final float rY = mRotationY;
    final float rZ = mRotationZ;
    if ((rX != 0) || (rY != 0) || (rZ != 0)) {
        final Camera camera = mCamera;
        camera.save();
        camera.rotateX(rX);
        camera.rotateY(rY);
        camera.rotateZ(-rZ);
        camera.getMatrix(m);
        camera.restore();
        m.preTranslate(-pX, -pY);
        m.postTranslate(pX, pY);
    }

    final float sX = mScaleX;
    final float sY = mScaleY;
    if ((sX != 1.0f) || (sY != 1.0f)) {
        m.postScale(sX, sY);
        final float sPX = -(pX / w) * ((sX * w) - w);
        final float sPY = -(pY / h) * ((sY * h) - h);
        m.postTranslate(sPX, sPY);
    }

    m.postTranslate(mTranslationX, mTranslationY);
}
 
Example 10
Source Project: CameraButton   File: CameraButton.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Since algorithm has differences between values calculation of right/left icons
 * we have to pass some flag for identify icon side.
 */
private void drawIcon(Canvas canvas, int index, float progress, boolean isLeftIcon) {
    float centerX = canvas.getWidth() / 2f;
    float centerY = canvas.getHeight() / 2f;

    float iconWidth = calculateIconWidth(progress);
    float translation = calculateTranslation(progress);
    float scaleX = iconWidth / mIconSize;

    float matrixDx = isLeftIcon
            ? centerX - mIconSize / 2f - translation
            : centerX + mIconSize / 2f + translation - iconWidth;

    Matrix matrix = mIconMatrices[index];
    matrix.reset();
    matrix.setScale(scaleX, 1);
    matrix.postTranslate(matrixDx, centerY - mIconSize / 2f);

    mIconShaders[index].setLocalMatrix(matrix);

    Paint paint = mIconPaints[index];
    paint.setAlpha((int) (255 * (1 - progress)));

    float rectLeft = isLeftIcon
            ? centerX - mIconSize / 2f - translation
            : centerX + mIconSize / 2f + translation - iconWidth;

    float rectRight = isLeftIcon
            ? centerX - mIconSize / 2f - translation + iconWidth
            : centerX + mIconSize / 2f + translation;

    canvas.drawRect(
            rectLeft,
            centerY - mIconSize / 2f,
            rectRight,
            centerY + mIconSize / 2f,
            paint
    );
}
 
Example 11
Source Project: AndroidPDF   File: PdfPage.java    License: Apache License 2.0 5 votes vote down vote up
public Bitmap renderBitmap(int width, int height, RectF pageSliceBounds)
{
    Matrix matrix = new Matrix();
    matrix.postScale(width / getMediaBox().width(), -height / getMediaBox().height());
    matrix.postTranslate(0, height);
    matrix.postTranslate(-pageSliceBounds.left*width, -pageSliceBounds.top*height);
    matrix.postScale(1/pageSliceBounds.width(), 1/pageSliceBounds.height());
    return render(new Rect(0,0,width,height), matrix);
}
 
Example 12
Source Project: DeviceConnect-Android   File: CanvasActivity.java    License: MIT License 5 votes vote down vote up
/**
 * Sets a bitmap to ImageView.
 * @param bitmap bitmap
 * @param mode mode
 * @param x x
 * @param y y
 */
private synchronized void setImageBitmap(final Bitmap bitmap, final int mode, final int x, final int y) {
    switch (mode) {
        default:
        case WearConst.MODE_NORMAL:
            Matrix matrix = new Matrix();
            matrix.postTranslate((float) x, (float) y);
            mImageView.setImageBitmap(bitmap);
            mImageView.setScaleType(ImageView.ScaleType.MATRIX);
            mImageView.setImageMatrix(matrix);
            mImageView.setVisibility(View.VISIBLE);
            BoxInsetLayout.LayoutParams normalLayoutParam = new BoxInsetLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER, BOX_ALL);
            mFrameLayout.setLayoutParams(normalLayoutParam);
            break;
        case WearConst.MODE_SCALES:
            mImageView.setImageBitmap(bitmap);
            mImageView.setScaleType(ImageView.ScaleType.FIT_START);
            mImageView.setTranslationX(x);
            mImageView.setTranslationY(y);
            mImageView.setVisibility(View.VISIBLE);
            BoxInsetLayout.LayoutParams scaleLayoutParam = new BoxInsetLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT, Gravity.LEFT | Gravity.TOP);
            mFrameLayout.setLayoutParams(scaleLayoutParam);
            break;
        case WearConst.MODE_FILLS:
            BitmapDrawable bd = new BitmapDrawable(getResources(), bitmap);
            bd.setTileModeX(Shader.TileMode.REPEAT);
            bd.setTileModeY(Shader.TileMode.REPEAT);
            mImageView.setImageDrawable(bd);
            mImageView.setScaleType(ImageView.ScaleType.FIT_XY);
            mImageView.setTranslationX(x);
            mImageView.setTranslationY(y);
            mImageView.setVisibility(View.VISIBLE);
            BoxInsetLayout.LayoutParams fillLayoutParam = new BoxInsetLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT, Gravity.LEFT | Gravity.TOP);
            mFrameLayout.setLayoutParams(fillLayoutParam);
            break;
    }
}
 
Example 13
Source Project: sealrtc-android   File: MarkerDrawable.java    License: MIT License 5 votes vote down vote up
private void computePath(Rect bounds) {
    final float currentScale = mCurrentScale;
    final Path path = mPath;
    final RectF rect = mRect;
    final Matrix matrix = mMatrix;

    path.reset();
    int totalSize = Math.min(bounds.width(), bounds.height());

    float initial = mClosedStateSize;
    float destination = totalSize;
    float currentSize = initial + (destination - initial) * currentScale;

    float halfSize = currentSize / 2f;
    float inverseScale = 1f - currentScale;
    float cornerSize = halfSize * inverseScale;
    float[] corners =
            new float[] {
                halfSize,
                halfSize,
                halfSize,
                halfSize,
                halfSize,
                halfSize,
                cornerSize,
                cornerSize
            };
    rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize);
    path.addRoundRect(rect, corners, Path.Direction.CCW);
    matrix.reset();
    matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize);
    matrix.postTranslate((bounds.width() - currentSize) / 2, 0);
    float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale;
    matrix.postTranslate(0, hDiff);
    path.transform(matrix);
}
 
Example 14
Source Project: ViewSupport   File: Rotate3dAnimation.java    License: Apache License 2.0 4 votes vote down vote up
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);
    final Matrix matrix = t.getMatrix();

    mCamera.save();

    // 调节深度
    if (mReverse) {
        mCamera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
    } else {
        mCamera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
    }

    // 绕轴旋转
    switch (mAxis) {
        case 1:
            mCamera.rotateX(degrees);
            break;
        case 2:
            mCamera.rotateY(degrees);
            break;
        case 3:
            mCamera.rotateZ(degrees);
            break;
    }

    mCamera.getMatrix(matrix);
    mCamera.restore();

    // 修复失真
    float[] mValues = new float[9];
    matrix.getValues(mValues);          //获取数值
    mValues[6] = mValues[6] / scale;    //数值修正
    mValues[7] = mValues[7] / scale;    //数值修正
    matrix.setValues(mValues);          //重新赋值

    // 设置中心
    matrix.preTranslate(-mCenterX, -mCenterY);
    matrix.postTranslate(mCenterX, mCenterY);
}
 
Example 15
private void adjustAspectRatio(int previewWidth, int previewHeight, int rotation) {
    txform.reset();

    int viewWidth = getWidth();
    int viewHeight = getHeight();
    float viewCenterX = viewWidth / 2;
    float viewCenterY = viewHeight / 2;

    float scale;
    if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
        scale = Math.max((float) (viewHeight + clipTop + clipBottom) / previewWidth, (float) (viewWidth) / previewHeight);
    } else {
        scale = Math.max((float) (viewHeight + clipTop + clipBottom) / previewHeight, (float) (viewWidth) / previewWidth);
    }

    float previewWidthScaled = previewWidth * scale;
    float previewHeightScaled = previewHeight * scale;

    float scaleX = previewHeightScaled / (viewWidth);
    float scaleY = previewWidthScaled / (viewHeight);

    txform.postScale(scaleX, scaleY, viewCenterX, viewCenterY);

    if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
        txform.postRotate(90 * (rotation - 2), viewCenterX, viewCenterY);
    } else {
        if (Surface.ROTATION_180 == rotation) {
            txform.postRotate(180, viewCenterX, viewCenterY);
        }
    }

    if (mirror) {
        txform.postScale(-1, 1, viewCenterX, viewCenterY);
    }
    if (clipTop != 0) {
        txform.postTranslate(0, -clipTop / 2);
    } else if (clipBottom != 0) {
        txform.postTranslate(0, clipBottom / 2);
    }

    textureView.setTransform(txform);

    Matrix matrix = new Matrix();
    if (cameraSession != null) {
        matrix.postRotate(cameraSession.getDisplayOrientation());
    }
    matrix.postScale(viewWidth / 2000f, viewHeight / 2000f);
    matrix.postTranslate(viewWidth / 2f, viewHeight / 2f);
    matrix.invert(this.matrix);
}
 
Example 16
Source Project: JCropImageView   File: JCropImageView.java    License: Apache License 2.0 4 votes vote down vote up
@TargetApi(VERSION_CODES.JELLY_BEAN)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    Drawable d = getDrawable();
    if (d != null && mCropType > -1) {

        final int dw = d.getIntrinsicWidth();
        final int dh = d.getIntrinsicHeight();
        int dx = 0, dy = 0;
        int msWidth = 0, msHeight = 0;
        int theoryw = 0, theoryh = 0;
        float scalew = 0, scaleh = 0;
        float scale = 0;

        if (mCropType <= CropType.FIT_FILL) { // fit width || bestfit
            // 1. get anchor by width. constrain to drawablewidth if wrap-content
            msWidth = MeasureSpec.getSize(widthMeasureSpec); // the view width
            if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) { // wrap
                msWidth = dw < msWidth ? dw : msWidth;
            }

            // 2. compute scale and theoretical height
            scalew = (float) msWidth / dw; // scale_via_width
            theoryh = (int) (dh * scalew); // theoretical = height x scale_via_width
        }

        if (mCropType >= CropType.FIT_FILL) {// fit bestfit || height
            // 1. get anchor by height. constrain to drawableheight if wrap-content
            msHeight = MeasureSpec.getSize(heightMeasureSpec); // the view height
            if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) { // wrap
                msHeight = dh < msHeight ? dh : msHeight;
            }

            // 2. compute scale and theoretical width
            scaleh = (float) msHeight / dh; // scale_via_height
            theoryw = (int) (dw * scaleh); // theoretical = width x scale_via_height
        }

        if (scalew > scaleh) { // fit width
            scale = scalew;

            // 3. constrain by maxheight
            // if match_parent then additional constraint if viewport < maxheight
            // if wrap_content then anything works even if viewport < or >  maxheight
            int maxHeight = getMaxHeight();
            msHeight = getLayoutParams().height;
            if (msHeight >= LayoutParams.MATCH_PARENT) { // match parent
                if (msHeight == LayoutParams.MATCH_PARENT) {
                    msHeight = MeasureSpec.getSize(heightMeasureSpec);
                }
                maxHeight = msHeight < maxHeight ? msHeight : maxHeight;
            }
            msHeight = theoryh > maxHeight ? maxHeight : theoryh; // limited height

            // 4. translate
            if (mCropAlign >= CropAlign.ALIGN_CENTER) {
                // AlignTo.ALIGN_CENTER || AlignTo.ALIGN_LEFT || AlignTo.ALIGN_RIGHT
                // if you want center crop shift it up by 50% aka 0.5f
                dy = (int)( (msHeight - theoryh) * 0.5f + 0.5f ); // + 0.5f for rounding
            } else if (mCropAlign == CropAlign.ALIGN_BOTTOM) {
                // AlignTo.ALIGN_BOTTOM
                // if you want bottom crop shift it up by 100% aka 1.0f
                dy = (int)( (msHeight - theoryh) * 1.0f + 0.5f ); // + 0.5f for rounding
            }

        } else { // fit height
            scale = scaleh;

            // 3. constrain by maxwidth
            // if match_parent then additional constraint if viewport < maxwidth
            // if wrap_content then anything works even if viewport < or >  maxwidth
            int maxWidth = getMaxWidth();
            msWidth = getLayoutParams().width;
            if (msWidth >= LayoutParams.MATCH_PARENT) { // match parent or is set
                if (msWidth == LayoutParams.MATCH_PARENT) {
                    msWidth = MeasureSpec.getSize(widthMeasureSpec);
                }
                maxWidth = msWidth < maxWidth ? msWidth : maxWidth;
            }
            msWidth = theoryw > maxWidth ? maxWidth : theoryw; // limited width

            if (mCropAlign <= CropAlign.ALIGN_CENTER) {
                // AlignTo.ALIGN_CENTER || AlignTo.ALIGN_TOP || AlignTo.ALIGN_BOTTOM
                // if you want center crop shift it left by 50% aka 0.5f
                dx = (int)( (msWidth - theoryw) * 0.5f + 0.5f ); // + 0.5f for rounding
            } else if (mCropAlign == CropAlign.ALIGN_RIGHT) { //AlignTo.ALIGN_RIGHT
                // if you want right crop shift right up by 100% aka 1.0f
                dx = (int)( (msWidth - theoryw) * 1.0f + 0.5f ); // + 0.5f for rounding
            }
        }

        // this is to scale it only by width - the pivot point is at (0,0)
        // for top crop we dont need to translate it
        Matrix matrix = getImageMatrix();
        matrix.setScale(scale, scale);
        matrix.postTranslate(dx, dy);
        setImageMatrix(matrix);
        setMeasuredDimension(msWidth, msHeight);
    }
    else super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
 
Example 17
Source Project: ml   File: ImageUtils.java    License: Apache License 2.0 4 votes vote down vote up
/**
 * Returns a transformation matrix from one reference frame into another.
 * Handles cropping (if maintaining aspect ratio is desired) and rotation.
 *
 * @param srcWidth Width of source frame.
 * @param srcHeight Height of source frame.
 * @param dstWidth Width of destination frame.
 * @param dstHeight Height of destination frame.
 * @param applyRotation Amount of rotation to apply from one frame to another.
 *  Must be a multiple of 90.
 * @param maintainAspectRatio If true, will ensure that scaling in x and y remains constant,
 * cropping the image if necessary.
 * @return The transformation fulfilling the desired requirements.
 */
public static Matrix getTransformationMatrix(
        final int srcWidth,
        final int srcHeight,
        final int dstWidth,
        final int dstHeight,
        final int applyRotation,
        final boolean maintainAspectRatio) {
    final Matrix matrix = new Matrix();

    if (applyRotation != 0) {
        if (applyRotation % 90 != 0) {
            Logger.debug("Rotation of %d % 90 != 0", applyRotation);
        }

        // Translate so center of image is at origin.
        matrix.postTranslate(-srcWidth / 2.0f, -srcHeight / 2.0f);

        // Rotate around origin.
        matrix.postRotate(applyRotation);
    }

    // Account for the already applied rotation, if any, and then determine how
    // much scaling is needed for each axis.
    final boolean transpose = (Math.abs(applyRotation) + 90) % 180 == 0;

    final int inWidth = transpose ? srcHeight : srcWidth;
    final int inHeight = transpose ? srcWidth : srcHeight;

    // Apply scaling if necessary.
    if (inWidth != dstWidth || inHeight != dstHeight) {
        final float scaleFactorX = dstWidth / (float) inWidth;
        final float scaleFactorY = dstHeight / (float) inHeight;

        if (maintainAspectRatio) {
            // Scale by minimum factor so that dst is filled completely while
            // maintaining the aspect ratio. Some image may fall off the edge.
            final float scaleFactor = Math.max(scaleFactorX, scaleFactorY);
            matrix.postScale(scaleFactor, scaleFactor);
        } else {
            // Scale exactly to fill dst from src.
            matrix.postScale(scaleFactorX, scaleFactorY);
        }
    }

    if (applyRotation != 0) {
        // Translate back from origin centered reference to destination frame.
        matrix.postTranslate(dstWidth / 2.0f, dstHeight / 2.0f);
    }

    return matrix;
}
 
Example 18
Source Project: PinchImageView   File: PinchImageView.java    License: MIT License 4 votes vote down vote up
/**
 * 双击后放大或者缩小
 *
 * 将图片缩放比例缩放到nextScale指定的值.
 * 但nextScale值不能大于最大缩放值不能小于fit center情况下的缩放值.
 * 将双击的点尽量移动到控件中心.
 *
 * @param x 双击的点
 * @param y 双击的点
 *
 * @see #calculateNextScale(float, float)
 * @see #getMaxScale()
 */
private void doubleTap(float x, float y) {
    if (!isReady()) {
        return;
    }
    //获取第一层变换矩阵
    Matrix innerMatrix = MathUtils.matrixTake();
    getInnerMatrix(innerMatrix);
    //当前总的缩放比例
    float innerScale = MathUtils.getMatrixScale(innerMatrix)[0];
    float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
    float currentScale = innerScale * outerScale;
    //控件大小
    float displayWidth = getWidth();
    float displayHeight = getHeight();
    //最大放大大小
    float maxScale = getMaxScale();
    //接下来要放大的大小
    float nextScale = calculateNextScale(innerScale, outerScale);
    //如果接下来放大大于最大值或者小于fit center值,则取边界
    if (nextScale > maxScale) {
        nextScale = maxScale;
    }
    if (nextScale < innerScale) {
        nextScale = innerScale;
    }
    //开始计算缩放动画的结果矩阵
    Matrix animEnd = MathUtils.matrixTake(mOuterMatrix);
    //计算还需缩放的倍数
    animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y);
    //将放大点移动到控件中心
    animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y);
    //得到放大之后的图片方框
    Matrix testMatrix = MathUtils.matrixTake(innerMatrix);
    testMatrix.postConcat(animEnd);
    RectF testBound = MathUtils.rectFTake(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
    testMatrix.mapRect(testBound);
    //修正位置
    float postX = 0;
    float postY = 0;
    if (testBound.right - testBound.left < displayWidth) {
        postX = displayWidth / 2f - (testBound.right + testBound.left) / 2f;
    } else if (testBound.left > 0) {
        postX = -testBound.left;
    } else if (testBound.right < displayWidth) {
        postX = displayWidth - testBound.right;
    }
    if (testBound.bottom - testBound.top < displayHeight) {
        postY = displayHeight / 2f - (testBound.bottom + testBound.top) / 2f;
    } else if (testBound.top > 0) {
        postY = -testBound.top;
    } else if (testBound.bottom < displayHeight) {
        postY = displayHeight - testBound.bottom;
    }
    //应用修正位置
    animEnd.postTranslate(postX, postY);
    //清理当前可能正在执行的动画
    cancelAllAnimator();
    //启动矩阵动画
    mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd);
    mScaleAnimator.start();
    //清理临时变量
    MathUtils.rectFGiven(testBound);
    MathUtils.matrixGiven(testMatrix);
    MathUtils.matrixGiven(animEnd);
    MathUtils.matrixGiven(innerMatrix);
}
 
Example 19
public static Matrix getTransformationMatrix(final int srcWidth, final int srcHeight,
                                             final int dstWidth, final int dstHeight,
                                             final int applyRotation, final boolean maintainAspectRatio) {
    final Matrix matrix = new Matrix();

    if (applyRotation != 0) {
        // Translate so center of image is at origin.
        matrix.postTranslate(-srcWidth / 2.0f, -srcHeight / 2.0f);

        // Rotate around origin.
        matrix.postRotate(applyRotation);
    }

    // Account for the already applied rotation, if any, and then determine how
    // much scaling is needed for each axis.
    final boolean transpose = (Math.abs(applyRotation) + 90) % 180 == 0;

    final int inWidth = transpose ? srcHeight : srcWidth;
    final int inHeight = transpose ? srcWidth : srcHeight;

    // Apply scaling if necessary.
    if (inWidth != dstWidth || inHeight != dstHeight) {
        final float scaleFactorX = dstWidth / (float) inWidth;
        final float scaleFactorY = dstHeight / (float) inHeight;

        if (maintainAspectRatio) {
            // Scale by minimum factor so that dst is filled completely while
            // maintaining the aspect ratio. Some image may fall off the edge.
            final float scaleFactor = Math.max(scaleFactorX, scaleFactorY);
            matrix.postScale(scaleFactor, scaleFactor);
        } else {
            // Scale exactly to fill dst from src.
            matrix.postScale(scaleFactorX, scaleFactorY);
        }
    }

    if (applyRotation != 0) {
        // Translate back from origin centered reference to destination frame.
        matrix.postTranslate(dstWidth / 2.0f, dstHeight / 2.0f);
    }

    return matrix;
}
 
Example 20
Source Project: LLApp   File: PinchImageView.java    License: Apache License 2.0 4 votes vote down vote up
/**
 * 当缩放操作结束动画
 *
 * 如果图片超过边界,找到最近的位置动画恢复.
 * 如果图片缩放尺寸超过最大值或者最小值,找到最近的值动画恢复.
 */
private void scaleEnd() {
    if (!isReady()) {
        return;
    }
    //是否修正了位置
    boolean change = false;
    //获取图片整体的变换矩阵
    Matrix currentMatrix = MathUtils.matrixTake();
    getCurrentImageMatrix(currentMatrix);
    //整体缩放比例
    float currentScale = MathUtils.getMatrixScale(currentMatrix)[0];
    //第二层缩放比例
    float outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0];
    //控件大小
    float displayWidth = getWidth();
    float displayHeight = getHeight();
    //最大缩放比例
    float maxScale = getMaxScale();
    //比例修正
    float scalePost = 1f;
    //位置修正
    float postX = 0;
    float postY = 0;
    //如果整体缩放比例大于最大比例,进行缩放修正
    if (currentScale > maxScale) {
        scalePost = maxScale / currentScale;
    }
    //如果缩放修正后整体导致第二层缩放小于1(就是图片比fit center状态还小),重新修正缩放
    if (outerScale * scalePost < 1f) {
        scalePost = 1f / outerScale;
    }
    //如果缩放修正不为1,说明进行了修正
    if (scalePost != 1f) {
        change = true;
    }
    //尝试根据缩放点进行缩放修正
    Matrix testMatrix = MathUtils.matrixTake(currentMatrix);
    testMatrix.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y);
    RectF testBound = MathUtils.rectFTake(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
    //获取缩放修正后的图片方框
    testMatrix.mapRect(testBound);
    //检测缩放修正后位置有无超出,如果超出进行位置修正
    if (testBound.right - testBound.left < displayWidth) {
        postX = displayWidth / 2f - (testBound.right + testBound.left) / 2f;
    } else if (testBound.left > 0) {
        postX = -testBound.left;
    } else if (testBound.right < displayWidth) {
        postX = displayWidth - testBound.right;
    }
    if (testBound.bottom - testBound.top < displayHeight) {
        postY = displayHeight / 2f - (testBound.bottom + testBound.top) / 2f;
    } else if (testBound.top > 0) {
        postY = -testBound.top;
    } else if (testBound.bottom < displayHeight) {
        postY = displayHeight - testBound.bottom;
    }
    //如果位置修正不为0,说明进行了修正
    if (postX != 0 || postY != 0) {
        change = true;
    }
    //只有有执行修正才执行动画
    if (change) {
        //计算结束矩阵
        Matrix animEnd = MathUtils.matrixTake(mOuterMatrix);
        animEnd.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y);
        animEnd.postTranslate(postX, postY);
        //清理当前可能正在执行的动画
        cancelAllAnimator();
        //启动矩阵动画
        mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd);
        mScaleAnimator.start();
        //清理临时变量
        MathUtils.matrixGiven(animEnd);
    }
    //清理临时变量
    MathUtils.rectFGiven(testBound);
    MathUtils.matrixGiven(testMatrix);
    MathUtils.matrixGiven(currentMatrix);
}