Touch Event এবং Path ব্যবহার করে ম্যানুয়ালি গোলাকার এলাকা কাটা
এই উদাহরণে দেখানো হয়েছে কিভাবে ব্যবহারকারী আঙুল দিয়ে স্ক্রিনে পথ আঁকলে (free-hand drawing) সেই পথ অনুযায়ী Bitmap-এ থেকে সেই এলাকা কাটা (crop) যায়। Path, Canvas, PorterDuffXfermode ব্যবহার করা হয়েছে।
ধাপ ১: প্রজেক্ট তৈরি করুন
Android Studio-তে নতুন প্রজেক্ট শুরু করুন।
ধাপ ২: লেআউট (activity_main.xml) - খালি RelativeLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
ধাপ ৩: MainActivity.java - কাস্টম View (CutImage)
package com.example.sample;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// কাস্টম View সেট করুন
setContentView(new CutImage(this));
}
// কাস্টম View ক্লাস
static class CutImage extends View {
Bitmap bitmap;
Path path = new Path();
Paint paint = new Paint();
Paint cropPaint = new Paint();
public CutImage(Context context) {
super(context);
// ড্রয়েবল থেকে Bitmap লোড করুন
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.demo);
// ড্রইং পেইন্ট (লাল রঙের স্ট্রোক)
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5f);
// ক্রপিং পেইন্ট
cropPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// মূল bitmap আঁকুন
canvas.drawBitmap(bitmap, 0, 0, null);
// ব্যবহারকারীর আঁকা পথ আঁকুন
canvas.drawPath(path, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
path.lineTo(x, y);
cropBitmap(); // পথ পুরো হলে ক্রপ করুন
break;
}
invalidate(); // রি-ড্র চাইये
return true;
}
private void cropBitmap() {
// নতুন Bitmap তৈরি করুন (ক্রপড)
Bitmap cropped = Bitmap.createBitmap(
bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas cropCanvas = new Canvas(cropped);
// পথ অনুযায়ী আঁকুন (মাস্ক হিসেবে)
cropCanvas.drawPath(path, cropPaint);
// মূল bitmap পথের ওপর আঁকুন (SRC_IN মোডে)
cropCanvas.drawBitmap(bitmap, 0, 0, cropPaint);
// পুরানো bitmap রিসাইকেল করুন, নতুনটি সেট করুন
bitmap.recycle();
bitmap = cropped;
path.reset(); // পথ রিসেট করুন পরবর্তী ড্রইং-এর জন্য
}
}
}
কিভাবে কাজ করে
- ব্যবহারকারী স্ক্রিনে আঙুল টেনে পথ আঁকে (ACTION_MOVE)।
- আঙুল ছাড়লে (ACTION_UP)
cropBitmap()কল হয়। - একটি নতুন Canvas-এ পথ আঁকা হয় (মাস্ক) এবং
SRC_INমোডে মূল bitmap আঁকা হয়। - ফলাফল: শুধু পথের ভেতরের অংশই থাকে, বাকি ট্রান্সপেরেন্ট হয়।
সীমাবদ্ধতা
- পথ বন্ধ (closed) না হলে ফলাফল অপ্রত্যাশিত হতে পারে —
path.close()কল করা উচিত। - বড় Bitmap-এ মেমরি সমস্যা হতে পারে।
- প্রোডাকশনে
BitmapShaderবা লাইব্রেরি (যেমন uCrop, CropImage) ব্যবহার করা ভালো।
ফলাফল
অ্যাপ চালু করলে ছবি দেখাবে। আঙুল দিয়ে আঁকলে লাল লাইন দেখাবে, আঙুল তুললে সেটি গোলাকার/ফ্রি-ফর্মে কাটা হয়ে যাবে।