android - 使用 Path 对象裁剪位图

标签 android image bitmap

在我的应用程序中,我尝试从选定的用户形状裁剪位图。 我已经阅读了很多有关此问题的信息,但仍然找不到任何解决方案。 裁剪后得到的图像不是我标记的图像。

这是我的代码:

public class TestView extends ImageView implements OnTouchListener {
    private Paint paint;
    public static List<Point> points;

    Bitmap bitmapMain;

    Context mContext;

    private int leftX = 0;
    private int rightX = 0;
    private int upY = 0;
    private int downY = 0;

    public TestView(Context c) {
        super(c);

        mContext = c;
        setFocusable(true);
        setFocusableInTouchMode(true);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
        paint.setStrokeWidth(5);
        paint.setColor(Color.WHITE);

        this.setOnTouchListener(this);
        points = new ArrayList<Point>();


    }

    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        setFocusable(true);
        setFocusableInTouchMode(true);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        paint.setColor(Color.WHITE);

        this.setOnTouchListener(this);
        points = new ArrayList<Point>();

    }

    public void setBitmap(Bitmap bit)
    {
        bitmapMain = bit;
    }

    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

       // canvas.drawBitmap(bitmap, 0, 0, null);

        Path path = new Path();
        boolean first = true;

        for (int i = 0; i < points.size(); i += 2) {
            Point point = points.get(i);
            if (first) {
                first = false;
                path.moveTo(point.x, point.y);
            } else if (i < points.size() - 1) {
                Point next = points.get(i + 1);
                path.quadTo(point.x, point.y, next.x, next.y);
            } else {
                path.lineTo(point.x, point.y);
            }
        }
        canvas.drawPath(path, paint);
    }

    public boolean onTouch(View view, MotionEvent event) {


        if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_OUTSIDE || event.getAction() == MotionEvent.ACTION_CANCEL) 
        {
             return true;
        }

        int intX = (int) (event.getX());
        int intY = (int) (event.getY());

        if(event.getAction() == MotionEvent.ACTION_DOWN)
        {
            leftX = intX;
            rightX = intX;
            downY = intY;
            upY = intY;
        }

        Point point = new Point();

        point.x = intX;
        point.y = intY;

        if(intX < leftX)
            leftX =  intX;
        if(intX > rightX)
            rightX = intX;
        if(intY > downY)
            downY =  intY;
        if(intY < upY)
            upY = intY;

        points.add(point);


       invalidate();

        return true;
    }

    public void clear() 
    {       
        leftX = 0;
        rightX = 0;
        upY = 0;
        downY = 0;

        points.clear();
        paint.setColor(Color.WHITE);
        paint.setStyle(Style.STROKE);
        invalidate();
    }


    public Bitmap getImage2()
    {

    //getting the size of the new bitmap

        int newHeight = rightX - leftX;
        int newWidth = downY - upY;

        Bitmap resultingImage = Bitmap.createBitmap(newHeight, newWidth, Config.ARGB_8888);

        Canvas canvas = new Canvas(resultingImage);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        Path path = new Path();
        for (int i = 0; i < points.size() - 1; i++) {

            path.quadTo((float)points.get(i).x, (float)points.get(i).y, (float)points.get(i+1).x, (float)points.get(i+1).y);
           // path.lineTo(points.get(i).x, points.get(i).y);
        }

//closing the shape, connection last point to the first one

        path.quadTo((float)points.get(points.size()-1).x, (float)points.get(points.size()-1).y, (float)points.get(0).x, (float)points.get(0).y);

         //drawing user shape

        canvas.drawPath(path, paint);

         //getting image inside the shape

        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

        canvas.drawBitmap(bitmapMain, 0, 0, paint);

        return resultingImage;
    }



   }

我的 Activity :

public class MainActivity extends Activity implements OnClickListener {

    private TestView drawing;
     private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
     public static final int MEDIA_TYPE_IMAGE = 1;
     private static final String IMAGE_DIRECTORY_NAME = "demo pictures";
     private Uri fileUri;


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        this.requestWindowFeature(Window.FEATURE_NO_TITLE);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //drawing = (SignatureViewModed) findViewById(R.id.myTest);
        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
        findViewById(R.id.button3).setOnClickListener(this);

        drawing = (TestView) findViewById(R.id.images);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }



    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub

        switch(arg0.getId())
        {

        case R.id.button1:
        {
            drawing.clear();
            break;
        }

        case R.id.button2:
        {
            if(isDeviceSupportCamera())
                captureImage();
            else
                Toast.makeText(this, "No camera", Toast.LENGTH_SHORT).show();
            break;
        }

        case R.id.button3:
        {
            showCutImage();
            break;
        }

        }

    }

    private boolean isDeviceSupportCamera() {
        if (getApplicationContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA)) {
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }

    private void captureImage() {

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        fileUri = getOutputMediaFileUri();

        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

        // start the image capture Intent
        startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
    }

    public Uri getOutputMediaFileUri() {
        return Uri.fromFile(getOutputMediaFile());
    }

    /**
     * returning image / video
     */
    private static File getOutputMediaFile() {

        // External sdcard location
        File mediaStorageDir = new File(
                Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                IMAGE_DIRECTORY_NAME);

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
                        + IMAGE_DIRECTORY_NAME + " directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
                Locale.getDefault()).format(new Date());
        File mediaFile;

         mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");

        return mediaFile;
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // save file url in bundle as it will be null on scren orientation
        // changes
        outState.putParcelable("file_uri", fileUri);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        // get the file url
        fileUri = savedInstanceState.getParcelable("file_uri");
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent data2) {

        Bitmap bitmap = null;

        if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {

            if (resultCode == RESULT_OK)
            {

                String filePath = fileUri.getPath();
                bitmap = decodeSampledBitmapFromPath(filePath, true);

                drawing.setBitmap(bitmap);

                drawing.setImageBitmap(bitmap);
            }

        }

            super.onActivityResult(requestCode, resultCode, data2);
        }

    public Bitmap decodeSampledBitmapFromPath(String path, boolean isFullScreen) {

        Bitmap bmp = null;
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeFile(path, options);

        if(isFullScreen)
            options.inSampleSize = calculateInSampleSize(options, getScreenWidth() , getScreenHeight());
        else
            options.inSampleSize = calculateInSampleSize(options, 200, 200);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bmp = BitmapFactory.decodeFile(path, options);

        return bmp;
        }

    public int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {

        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            if (width > height) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
             }
         }
         return inSampleSize;
        }

    @SuppressLint("NewApi")
    public int getScreenHeight()
    {
        Display display = ((WindowManager) this.getSystemService(WINDOW_SERVICE))
                .getDefaultDisplay();

        int height = 0;

        if (android.os.Build.VERSION.SDK_INT >= 13) {
            Point size = new Point();
            display.getSize(size);
            height = size.y;

        } else {
            height = display.getHeight();

        }

        return height;
    }

    @SuppressLint("NewApi")
    public int getScreenWidth()
    {
        Display display = ((WindowManager) this.getSystemService(WINDOW_SERVICE))
                .getDefaultDisplay();

        int width = 0;

        if (android.os.Build.VERSION.SDK_INT >= 13) {
            Point size = new Point();
            display.getSize(size);

            width = size.x;
        } else {

            width = display.getWidth();
        }

        return width;
    }

    public void showCutImage()
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        View prefView = View.inflate(this,R.layout.image_show, null);

        ImageView image = (ImageView) prefView.findViewById(R.id.imageView1);

        image.setImageBitmap(drawing.getImage2());

        builder.setView(prefView);

        builder.show();

    }

这是我的结果的 2 张图片。 你可以看到我得到的图片不是我标记的整个区域并且它有额外的角。

enter image description here

enter image description here

最佳答案

你应该关闭路径。 将testView的onDraw方法改成

public void onDraw(Canvas canvas) { super.onDraw(canvas);

   // canvas.drawBitmap(bitmap, 0, 0, null);

    Path path = new Path();
    boolean first = true;

    for (int i = 0; i < points.size(); i += 2) {
        Point point = points.get(i);
        if (first) {
            first = false;
            path.moveTo(point.x, point.y);
        } else if (i < points.size() - 1) {
            Point next = points.get(i + 1);
            path.quadTo(point.x, point.y, next.x, next.y);
        } else {
            path.lineTo(point.x, point.y);
        }
    }
    path.lineTo(points.get(0).x,points.get(0).y);
    canvas.drawPath(path, paint);
}

关于android - 使用 Path 对象裁剪位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21456112/

相关文章:

java - 放大位图

android - QT Necessitas - 链接 gnu-libstdc++ 时出现神秘的 ctype_base.h 错误

java - 将字符串转换为其表示的十六进制值

java - 前台服务从 MainActivity 启动操作

android - 在焦点 EditText 问题处隐藏工具栏

c# - 将图像从 C# 保存到 SQL Server 数据库

jQuery追加用img替换图像

python - 如何保存 Pymaging PNG 图像?

安卓 : How to create a bitmap with exact physical size in inches

Android createbitmap 宽度在不同设备上表现不同