图像的自定义裁剪无法正常工作
Posted
技术标签:
【中文标题】图像的自定义裁剪无法正常工作【英文标题】:Custom Cropping of image is not working correctly 【发布时间】:2013-07-10 06:25:11 【问题描述】:我正在使用以下代码在 android 中执行图像裁剪。
但是我得到了错误的结果。我得到了非常缩放的图片,我认为我的代码有问题
代码:
package net.londatiga.android;
import java.io.ByteArrayOutputStream;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
public class CropView extends ImageView
Paint paint = new Paint();
private int initial_size = 300;
private static Point leftTop, rightBottom, center, previous;
private static final int DRAG= 0;
private static final int LEFT= 1;
private static final int TOP= 2;
private static final int RIGHT= 3;
private static final int BOTTOM= 4;
private int imageScaledWidth,imageScaledHeight;
// Adding parent class constructors
public CropView(Context context)
super(context);
initCropView();
public CropView(Context context, AttributeSet attrs)
super(context, attrs, 0);
initCropView();
public CropView(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
initCropView();
@Override
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
if(leftTop.equals(0, 0))
resetPoints();
canvas.drawRect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, paint);
@Override
public boolean onTouchEvent(MotionEvent event)
int eventaction = event.getAction();
switch (eventaction)
case MotionEvent.ACTION_DOWN:
previous.set((int)event.getX(), (int)event.getY());
break;
case MotionEvent.ACTION_MOVE:
if(isActionInsideRectangle(event.getX(), event.getY()))
adjustRectangle((int)event.getX(), (int)event.getY());
invalidate(); // redraw rectangle
previous.set((int)event.getX(), (int)event.getY());
break;
case MotionEvent.ACTION_UP:
previous = new Point();
break;
return true;
private void initCropView()
paint.setColor(Color.YELLOW);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(5);
leftTop = new Point();
rightBottom = new Point();
center = new Point();
previous = new Point();
public void resetPoints()
center.set(getWidth()/2, getHeight()/2);
leftTop.set((getWidth()-initial_size)/2,(getHeight()-initial_size)/2);
rightBottom.set(leftTop.x+initial_size, leftTop.y+initial_size);
private static boolean isActionInsideRectangle(float x, float y)
int buffer = 10;
return (x>=(leftTop.x-buffer)&&x<=(rightBottom.x+buffer)&& y>=(leftTop.y-buffer)&&y<=(rightBottom.y+buffer))?true:false;
private boolean isInImageRange(PointF point)
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Calculate the scaled dimensions
imageScaledWidth = Math.round(getDrawable().getIntrinsicWidth() * f[Matrix.MSCALE_X]);
imageScaledHeight = Math.round(getDrawable().getIntrinsicHeight() * f[Matrix.MSCALE_Y]);
return (point.x>=(center.x-(imageScaledWidth/2))&&point.x<=(center.x+(imageScaledWidth/2))&&point.y>=(center.y-(imageScaledHeight/2))&&point.y<=(center.y+(imageScaledHeight/2)))?true:false;
private void adjustRectangle(int x, int y)
int movement;
switch(getAffectedSide(x,y))
case LEFT:
movement = x-leftTop.x;
if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movement)))
leftTop.set(leftTop.x+movement,leftTop.y+movement);
break;
case TOP:
movement = y-leftTop.y;
if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movement)))
leftTop.set(leftTop.x+movement,leftTop.y+movement);
break;
case RIGHT:
movement = x-rightBottom.x;
if(isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movement)))
rightBottom.set(rightBottom.x+movement,rightBottom.y+movement);
break;
case BOTTOM:
movement = y-rightBottom.y;
if(isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movement)))
rightBottom.set(rightBottom.x+movement,rightBottom.y+movement);
break;
case DRAG:
movement = x-previous.x;
int movementY = y-previous.y;
if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movementY)) && isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movementY)))
leftTop.set(leftTop.x+movement,leftTop.y+movementY);
rightBottom.set(rightBottom.x+movement,rightBottom.y+movementY);
break;
private static int getAffectedSide(float x, float y)
int buffer = 10;
if(x>=(leftTop.x-buffer)&&x<=(leftTop.x+buffer))
return LEFT;
else if(y>=(leftTop.y-buffer)&&y<=(leftTop.y+buffer))
return TOP;
else if(x>=(rightBottom.x-buffer)&&x<=(rightBottom.x+buffer))
return RIGHT;
else if(y>=(rightBottom.y-buffer)&&y<=(rightBottom.y+buffer))
return BOTTOM;
else
return DRAG;
public byte[] getCroppedImage()
BitmapDrawable drawable = (BitmapDrawable)getDrawable();
float x = leftTop.x-center.x+(drawable.getBitmap().getWidth()/2);
float y = leftTop.y-center.y+(drawable.getBitmap().getHeight()/2);
Bitmap cropped = Bitmap.createBitmap(drawable.getBitmap(),(int)x,(int)y,(int)rightBottom.x-(int)leftTop.x,(int)rightBottom.y-(int)leftTop.y);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
cropped.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
我尝试裁剪的图像是
预期的图像是矩形框中的内容,但我得到了非常放大的图像
结果图像
我该如何解决这个问题,我尝试通过更改一些代码但没有找到任何结果。
另一个问题是,通过使用这个矩形框,我只能裁剪矩形形状的图像,是否有可能以任何我想要的形状裁剪图像。
我在其中一个应用程序(文档扫描仪跟踪版本)中观察到这一点,用户可以在其中使用相同的矩形框以一些不规则形状裁剪图像。
我怎样才能达到这个结果?
请推荐
谢谢
【问题讨论】:
第三方库也在那里。您可以使用它来节省时间。 你能告诉我吗 我卡在了中间,是否需要发送所有数据,如 aspectx、aspecty 和其他所有数据 不..你没有。它会自动采取。您可以离开实施。但我自己已经成功地实现了这一点。而且我当时坚持了3天。 :) 你看到我说的那个应用了吗? 【参考方案1】:我已经实现了 Android Crop Image 库。这对我很有帮助。它具有以下特点。
-
双指缩放以裁剪图像的极小部分
可在图像上调整大小的矩形
高效的图像裁剪结果返回到您的活动中
轮换设施
编辑
对于结果,
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (data != null) if (data.getParcelableExtra("data") != null)
Bitmap bitmap = data.getParcelableExtra("data");
再编辑一次
在CropImage
文件中搜索private void handleFace(FaceDetector.Face f)
方法。在HighlightView hv = new HighlightView(mImageView);
这一行之后的方法中加入以下代码。
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD)
mImageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
同样在private void makeDefault()
方法中添加上述代码。
private void makeDefault()
HighlightView hv = new HighlightView(mImageView);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD)
mImageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//rest of code
由于某些加速原因,这是必要的。如果您在“GINGERBREAD”和“View.LAYOUT_TYPE_SOFTWARE”中遇到任何错误,请将您的 API 版本更改为 4.0 及更高版本。
确保您有如下活动注册,
<activity
android:name="com.android.camera.CropImage"
android:hardwareAccelerated="false" />
注意
此示例应用程序的布局很脏。你需要自己说清楚。这是库项目,因此请从项目属性中删除“is library”以运行该示例代码。
【讨论】:
MenuHelper 类无法识别,mLeft,mContext,mRight 变量无法识别 @ChintanRathod ,赞成 我如何在我的项目中使用这个库。我已经将它包含在我的项目中。请提供教程链接或逐步告诉我谢谢你 no laucher activity found 错误,我是否需要在清单中添加任何其他内容 很明显,亲爱的。你需要注册Activity。以上是关于图像的自定义裁剪无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章