下面列出了android.graphics.Matrix#setRectToRect ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public void crop() {
if (mCropBitmap != null) {
float cropWidth = mCropWindow.width() / mScaleRate;
float cropHeight = mCropWindow.height() / mScaleRate;
Rect cropRect = mCropWindow.getWindowRect(mScaleRate);
RectF dstRect = new RectF(0, 0, cropWidth, cropHeight);
Matrix cropMatrix = new Matrix();
cropMatrix.setRectToRect(new RectF(cropRect), dstRect, Matrix.ScaleToFit.FILL);
cropMatrix.preConcat(mCropBitmap.getRotateMatrix());
Bitmap cropped = Bitmap.createBitmap((int) cropWidth, (int) cropHeight, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(cropped);
canvas.drawBitmap(mCropBitmap.getBitmap(), cropMatrix, null);
replace(cropped, 0);
}
}
@NonNull
private static Matrix createShaderMatrix(@NonNull ImageView.ScaleType scaleType, int vWidth,
int vHeight, int bmWidth, int bmHeight) {
float scale, translateX = 0, translateY = 0;
if (bmWidth * vHeight > bmHeight * vWidth) {
scale = vHeight / (float) bmHeight;
translateX = (vWidth - bmWidth * scale) * 0.5f;
} else {
scale = vWidth / (float) bmWidth;
translateY = (vHeight - bmHeight * scale) * 0.5f;
}
Matrix mMatrix = new Matrix();
if (scaleType == ImageView.ScaleType.FIT_XY) {
mMatrix.setScale(vWidth / (float) bmWidth, vHeight / (float) bmHeight);
} else if (scaleType == ImageView.ScaleType.FIT_CENTER) {
RectF src = new RectF(0, 0, bmWidth, bmHeight);
RectF dist = new RectF(0, 0, vWidth, vHeight);
mMatrix.setRectToRect(src, dist, Matrix.ScaleToFit.CENTER);
} else if (scaleType == ImageView.ScaleType.CENTER_CROP) {
mMatrix.setScale(scale, scale);
mMatrix.postTranslate(translateX + 0.5f, translateY + 0.5f);
}
return mMatrix;
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(int viewWidth, int viewHeight) {
if (null == mTextureView || null == mPreviewSize) {
return;
}
int rotation = mDisplayOrientation;
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
mTextureView.setTransform(matrix);
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should not to be called until the camera preview size is determined in
* openCamera, or until the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(int viewWidth, int viewHeight) {
Activity activity = getActivity();
if (null == mTextureView || null == mPreviewSize || null == activity) {
return;
}
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
mTextureView.setTransform(matrix);
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(final int viewWidth, final int viewHeight) {
final Activity activity = getActivity();
if (null == textureView || null == previewSize || null == activity) {
return;
}
final int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
final Matrix matrix = new Matrix();
final RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
final RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
final float centerX = viewRect.centerX();
final float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
final float scale =
Math.max(
(float) viewHeight / previewSize.getHeight(),
(float) viewWidth / previewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
textureView.setTransform(matrix);
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(final int viewWidth, final int viewHeight) {
final Activity activity = getActivity();
if (null == textureView || null == previewSize || null == activity) {
return;
}
final int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
final Matrix matrix = new Matrix();
final RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
final RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
final float centerX = viewRect.centerX();
final float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
final float scale =
Math.max(
(float) viewHeight / previewSize.getHeight(),
(float) viewWidth / previewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
textureView.setTransform(matrix);
}
private Matrix cameraToPreviewTransform(boolean mirrorX, int displayOrientation,
RectF previewRect)
{
Matrix transform = new Matrix();
// Need mirror for front camera.
transform.setScale(mirrorX ? -1 : 1, 1);
// Apply a rotate transform.
// This is the value for android.hardware.Camera.setDisplayOrientation.
transform.postRotate(displayOrientation);
// Map camera driver coordinates to preview rect coordinates
Matrix fill = new Matrix();
fill.setRectToRect(CAMERA_DRIVER_RECT,
previewRect,
Matrix.ScaleToFit.FILL);
// Concat the previous transform on top of the fill behavior.
transform.setConcat(fill, transform);
return transform;
}
private Bitmap inMemoryCrop(RotateBitmap rotateBitmap, Bitmap croppedImage, Rect r,
int width, int height, int outWidth, int outHeight) {
// In-memory crop means potential OOM errors,
// but we have no choice as we can't selectively decode a bitmap with this API level
System.gc();
try {
croppedImage = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(croppedImage);
RectF dstRect = new RectF(0, 0, width, height);
Matrix m = new Matrix();
m.setRectToRect(new RectF(r), dstRect, Matrix.ScaleToFit.FILL);
m.preConcat(rotateBitmap.getRotateMatrix());
canvas.drawBitmap(rotateBitmap.getBitmap(), m, null);
} catch (OutOfMemoryError e) {
Log.e("OOM cropping image: " + e.getMessage(), e);
setResultException(e);
System.gc();
}
// Release bitmap memory as soon as possible
clearImageView();
return croppedImage;
}
public void setSignatureBitmap(Bitmap signature) {
clear();
ensureSignatureBitmap();
RectF tempSrc = new RectF();
RectF tempDst = new RectF();
int dwidth = signature.getWidth();
int dheight = signature.getHeight();
int vwidth = getWidth();
int vheight = getHeight();
// Generate the required transform.
tempSrc.set(0, 0, dwidth, dheight);
tempDst.set(0, 0, vwidth, vheight);
Matrix drawMatrix = new Matrix();
drawMatrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER);
Canvas canvas = new Canvas(mSignatureBitmap);
canvas.drawBitmap(signature, drawMatrix, null);
setIsEmpty(false);
invalidate();
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should be called after the camera preview size is determined in
* setUpCameraOutputs and also the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(int viewWidth, int viewHeight) {
Activity activity = getActivity();
if (null == mTextureView || null == mPreviewSize || null == activity) {
return;
}
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
} else if (Surface.ROTATION_180 == rotation) {
matrix.postRotate(180, centerX, centerY);
}
mTextureView.setTransform(matrix);
}
/**
* Adds a shadow to a Bitmap.
* <p>
* TODO: Make this return Drawable for our use case.
*
* @param drawable Drawable that should be used as the foreground layer
* of the shadow.
* @param dstHeight Height of the returned bitmap.
* @param dstWidth Width of the returned bitmap.
* @param color Colour of the drawn shadow.
* @param size Size of the drawn shadow.
* @param dx Shadow x direction.
* @param dy Shadow y direction.
*
* @return Bitmap with resulting shadow.
*
* @author schwiz (https://stackoverflow.com/a/24579764)
*/
private static Bitmap addShadow(final Drawable drawable, final int dstHeight, final int dstWidth, int color, int size, float dx, float dy) {
final Bitmap bm = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bm);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
final Bitmap mask = Bitmap.createBitmap(dstWidth, dstHeight, Bitmap.Config.ALPHA_8);
final Matrix scaleToFit = new Matrix();
final RectF src = new RectF(0, 0, bm.getWidth(), bm.getHeight());
final RectF dst = new RectF(0, 0, dstWidth - dx, dstHeight - dy);
scaleToFit.setRectToRect(src, dst, Matrix.ScaleToFit.FILL);
final Matrix dropShadow = new Matrix(scaleToFit);
dropShadow.postTranslate(dx, dy);
final Canvas maskCanvas = new Canvas(mask);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskCanvas.drawBitmap(bm, scaleToFit, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
maskCanvas.drawBitmap(bm, dropShadow, paint);
final BlurMaskFilter filter = new BlurMaskFilter(size, BlurMaskFilter.Blur.SOLID);
paint.reset();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setMaskFilter(filter);
paint.setFilterBitmap(true);
final Bitmap ret = Bitmap.createBitmap(dstWidth, dstHeight, Bitmap.Config.ARGB_8888);
final Canvas retCanvas = new Canvas(ret);
retCanvas.drawBitmap(mask, 0, 0, paint);
retCanvas.drawBitmap(bm, scaleToFit, null);
mask.recycle();
return ret;
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(0, 0, bounds.width(), bounds.height());
radius = Math.min(bounds.width(), bounds.height()) / 2;
strokeRadius = radius - strokeWidth / 2;
// Resize the original bitmap to fit the new bound
Matrix shaderMatrix = new Matrix();
shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
bitmapShader.setLocalMatrix(shaderMatrix);
}
@Override
protected void onResize(float width, float height) {
Matrix matrix = new Matrix();
Region shapeRegion = new Region(0, 0, (int) width, (int) height);
matrix.setRectToRect(viewportRect, new RectF(0, 0, width, height), Matrix.ScaleToFit.CENTER);
for (Layer layer : layers) {
layer.transform(matrix, shapeRegion);
}
}
private void updateScreenBitmap() {
if (!mIsRunning) {
return;
}
Activity activity = mActivityTracker.tryGetTopActivity();
if (activity == null) {
return;
}
// This stuff needs to happen in the UI thread
View rootView = activity.getWindow().getDecorView();
try {
if (mBitmap == null) {
int viewWidth = rootView.getWidth();
int viewHeight = rootView.getHeight();
float scale = Math.min((float) mRequest.maxWidth / (float) viewWidth,
(float) mRequest.maxHeight / (float) viewHeight);
int destWidth = (int) (viewWidth * scale);
int destHeight = (int) (viewHeight * scale);
mBitmap = Bitmap.createBitmap(destWidth, destHeight, Bitmap.Config.RGB_565);
mCanvas = new Canvas(mBitmap);
Matrix matrix = new Matrix();
mTempSrc.set(0, 0, viewWidth, viewHeight);
mTempDst.set(0, 0, destWidth, destHeight);
matrix.setRectToRect(mTempSrc, mTempDst, Matrix.ScaleToFit.CENTER);
mCanvas.setMatrix(matrix);
}
rootView.draw(mCanvas);
} catch (OutOfMemoryError e) {
LogUtil.w("Out of memory trying to allocate screencast Bitmap.");
}
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(0, 0, bounds.width(), bounds.height());
radius = Math.min(bounds.width(), bounds.height()) / 2;
strokeRadius = radius - strokeWidth / 2;
// Resize the original bitmap to fit the new bound
Matrix shaderMatrix = new Matrix();
shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
bitmapShader.setLocalMatrix(shaderMatrix);
}
private void updateTextureViewSize(final GifInfoHandle gifInfoHandle) {
final Matrix transform = new Matrix();
final float viewWidth = getWidth();
final float viewHeight = getHeight();
final float scaleRef;
final float scaleX = gifInfoHandle.width / viewWidth;
final float scaleY = gifInfoHandle.height / viewHeight;
RectF src = new RectF(0, 0, gifInfoHandle.width, gifInfoHandle.height);
RectF dst = new RectF(0, 0, viewWidth, viewHeight);
switch (mScaleType) {
case CENTER:
transform.setScale(scaleX, scaleY, viewWidth / 2, viewHeight / 2);
break;
case CENTER_CROP:
scaleRef = 1 / Math.min(scaleX, scaleY);
transform.setScale(scaleRef * scaleX, scaleRef * scaleY, viewWidth / 2, viewHeight / 2);
break;
case CENTER_INSIDE:
if (gifInfoHandle.width <= viewWidth && gifInfoHandle.height <= viewHeight) {
scaleRef = 1.0f;
} else {
scaleRef = Math.min(1 / scaleX, 1 / scaleY);
}
transform.setScale(scaleRef * scaleX, scaleRef * scaleY, viewWidth / 2, viewHeight / 2);
break;
case FIT_CENTER:
transform.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
transform.preScale(scaleX, scaleY);
break;
case FIT_END:
transform.setRectToRect(src, dst, Matrix.ScaleToFit.END);
transform.preScale(scaleX, scaleY);
break;
case FIT_START:
transform.setRectToRect(src, dst, Matrix.ScaleToFit.START);
transform.preScale(scaleX, scaleY);
break;
case FIT_XY:
return;
case MATRIX:
transform.set(mTransform);
transform.preScale(scaleX, scaleY);
break;
}
super.setTransform(transform);
}
protected Bitmap scaledBitmap(Bitmap bitmap, int width, int height) {
Matrix m = new Matrix();
m.setRectToRect(new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()), new RectF(0, 0, width, height), Matrix.ScaleToFit.CENTER);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
}
public static boolean setBitmapToDisplayMatrix(Matrix m, RectF imageBounds,
RectF displayBounds) {
m.reset();
return m.setRectToRect(imageBounds, displayBounds, Matrix.ScaleToFit.CENTER);
}
/**
* Build a matrix which can be used when calling setTransform() on a
* TextureView.
* TODO: write unit test when roboletric is available.
*
* @param previewViewSize The TextureView current layout size.
* @param previewStreamSize The selected preview video stream size.
* @return The matrix to transform TextureView.
*/
public Matrix toTransformMatrix(Size previewViewSize, Size previewStreamSize)
{
RectF previewViewRect =
new RectF(0.0f, 0.0f, previewViewSize.width(), previewViewSize.height());
PointF previewViewCenter = new PointF(previewViewRect.centerX(), previewViewRect.centerY());
// If natural orientation is portrait, rotate the buffer dimensions.
Size previewBufferSize = previewStreamSize;
if (mOrientationManager.getDeviceNaturalOrientation() == OrientationManager.DeviceNaturalOrientation.PORTRAIT)
{
previewBufferSize = new Size(previewStreamSize.height(), previewStreamSize.width());
}
Matrix transformMatrix = new Matrix();
// Adjust the effective preview rect to the center of the texture view.
final RectF PreviewBufferRect =
new RectF(0.0f, 0.0f, previewBufferSize.width(), previewBufferSize.height());
final PointF previewBufferCenter =
new PointF(PreviewBufferRect.centerX(), PreviewBufferRect.centerY());
final RectF centeredEffectivePreviewRect = new RectF(PreviewBufferRect);
centeredEffectivePreviewRect.offset(
previewViewCenter.x - previewBufferCenter.x,
previewViewCenter.y - previewBufferCenter.y);
// Undo ScaleToFit.FILL done by the surface
transformMatrix.setRectToRect(
previewViewRect, centeredEffectivePreviewRect, Matrix.ScaleToFit.FILL);
// Rotate buffer contents to proper orientation
int rotateDegree = mOrientationManager.getDisplayRotation().getDegrees();
transformMatrix.postRotate(
rotateDegree,
previewViewCenter.x, previewViewCenter.y);
/**
* Scale to fit view, cropping the longest dimension.
*
* surfaceTextureSize is changed with the device orientation. Since
* previewStreamSize is always in landscape. To calculate the scale
* factor, previewStreamSize needs to be rotated if in portrait.
*/
Size rotatedPreviewSize = previewStreamSize;
if (mOrientationManager.isInPortrait())
{
rotatedPreviewSize = new Size(previewStreamSize.height(), previewStreamSize.width());
}
float scale = Math.min(
(float) previewViewSize.width() / (float) rotatedPreviewSize.width(),
(float) previewViewSize.height() / (float) rotatedPreviewSize.height());
transformMatrix.postScale(scale, scale, previewViewCenter.x, previewViewCenter.y);
RectF scaledPreviewStreamRect = new RectF(
0.0f, 0.0f, previewStreamSize.width() * scale, previewStreamSize.height() * scale);
PointF scaledPreviewStreamCenter =
new PointF(scaledPreviewStreamRect.centerX(), scaledPreviewStreamRect.centerY());
transformMatrix.postTranslate(
scaledPreviewStreamCenter.x - previewViewCenter.x,
scaledPreviewStreamCenter.y - previewViewCenter.y);
return transformMatrix;
}
/**
* Draws the icon onto the canvas given the source rectangle of the bitmap and the destination
* rectangle of the canvas.
*/
protected void drawIconOnCanvas(Bitmap icon, Canvas canvas, Paint paint, RectF src, RectF dst) {
Matrix matrix = new Matrix();
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.FILL);
canvas.drawBitmap(icon, matrix, paint);
}