Android 如何缩放图像
我有一个自定义组件,它基本上在画布上绘制位图,以便与用户交互 现在我想添加放大功能,以便用户可以放大并更好地查看细节 问题是,当我放大位图时,我经常达到内存限制,并出现“内存不足”错误 这是因为我试图放大位图 我尝试过Android 如何缩放图像,android,Android,我有一个自定义组件,它基本上在画布上绘制位图,以便与用户交互 现在我想添加放大功能,以便用户可以放大并更好地查看细节 问题是,当我放大位图时,我经常达到内存限制,并出现“内存不足”错误 这是因为我试图放大位图 我尝试过createBitmap(位图源代码,int x,int y,int width,int height,矩阵m,布尔过滤器)使用适当的矩阵Matrix.postScale(2,2) 请就如何在不耗尽内存的情况下实现“放大”提供任何建议? 如果我使用这段代码(唯一的区别是我用TRY-
createBitmap(位图源代码,int x,int y,int width,int height,矩阵m,布尔过滤器)
使用适当的矩阵Matrix.postScale(2,2)代码>
请就如何在不耗尽内存的情况下实现“放大”提供任何建议?
如果我使用这段代码(唯一的区别是我用TRY-CATCH包围了它),它不会耗尽内存
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(2, 2);
Bitmap bm2=null;
try {
bm2=Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, false);
} catch (Exception e){Toast.makeText(MainActivity.this, "Image is too large, out of memory", Toast.LENGTH_LONG).show();
return;
}
//bm.recycle();
myView.setimage(bm2);
为什么它现在可以工作?创建此自定义ImageView
,并将其添加到“活动”:
public class TouchImageView extends ImageView {
Matrix matrix = new Matrix();
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
float redundantXSpace, redundantYSpace;
float width, height;
static final int CLICK = 3;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;
ScaleGestureDetector mScaleDetector;
Context context;
public TouchImageView(Context context) {
super(context);
sharedConstructing(context);
}
public TouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
sharedConstructing(context);
}
private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
if (scaleWidth < width) {
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
} else if (scaleHeight < height) {
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
} else {
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true; // indicate event was handled
}
});
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
if (bm != null) {
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
}
}
public void setMaxZoom(float x) {
maxScale = x;
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale) {
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale / origScale;
}
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1) {
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (Math.round(origWidth * saveScale) < width) {
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
} else {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
}
}
}
} else {
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
}
}
return true;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
// Fit to screen.
float scale;
float scaleX = (float) width / (float) bmWidth;
float scaleY = (float) height / (float) bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;
// Center the image
redundantYSpace = (float) height - (scale * (float) bmHeight);
redundantXSpace = (float) width - (scale * (float) bmWidth);
redundantYSpace /= (float) 2;
redundantXSpace /= (float) 2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
}
}
公共类TouchImageView扩展了ImageView{
矩阵=新矩阵();
//我们可能处于这三种状态之一
静态最终int NONE=0;
静态最终整数阻力=1;
静态最终整数缩放=2;
int模式=无;
//记住一些关于缩放的事情
PointF last=新的PointF();
PointF start=新的PointF();
浮动最小刻度=1f;
浮点最大刻度=3f;
浮动[]m;
浮点redundantXSpace,redundantYSpace;
浮动宽度、高度;
静态最终int CLICK=3;
浮动存储比例=1f;
右浮动、底部、起始宽度、起始高度、bmWidth、bmHeight、bmHeight;
scalegestruedetector mScaleDetector;
语境;
公共TouchImageView(上下文){
超级(上下文);
共享构造(上下文);
}
公共TouchImageView(上下文、属性集属性){
超级(上下文,attrs);
共享构造(上下文);
}
私有void共享构造(上下文){
super.setClickable(true);
this.context=上下文;
mScaleDetector=新的scalegestruedetector(上下文,新的ScaleListener());
矩阵.setTranslate(1f,1f);
m=新浮点数[9];
setImageMatrix(矩阵);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(新的OnTouchListener(){
@凌驾
公共布尔onTouch(视图v,运动事件){
mScaleDetector.onTouchEvent(事件);
矩阵值(m);
float x=m[矩阵MTRANS_x];
浮点y=m[矩阵MTRANS_y];
PointF curr=新的PointF(event.getX(),event.getY());
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
set(event.getX(),event.getY());
开始。设置(最后);
模式=拖动;
打破
case MotionEvent.ACTION\u移动:
如果(模式==拖动){
浮动deltaX=当前x-最后x;
浮动三角洲=当前y-最后y;
float scaleWidth=Math.round(origWidth*saveScale);
float scalehHeight=数学圆整(origHeight*saveScale);
if(标度宽度<宽度){
deltaX=0;
如果(y+deltaY>0)
deltaY=-y;
否则如果(y+deltaY<-底部)
三角洲=-(y+底部);
}else if(刻度高度<高度){
deltaY=0;
如果(x+deltaX>0)
deltaX=-x;
否则如果(x+deltaX<-右)
deltaX=-(x+右侧);
}否则{
如果(x+deltaX>0)
deltaX=-x;
否则如果(x+deltaX<-右)
deltaX=-(x+右侧);
如果(y+deltaY>0)
deltaY=-y;
否则如果(y+deltaY<-底部)
三角洲=-(y+底部);
}
矩阵。后翻译(deltaX、deltaY);
最后一组(当前x、当前y);
}
打破
case MotionEvent.ACTION\u UP:
模式=无;
intxdiff=(int)Math.abs(curr.x-start.x);
int yDiff=(int)Math.abs(curr.y-start.y);
if(xDiff最大比例){
zoomableImageView.setImageBitmap( bitmap );