PDA

View Full Version : تنظیم قسمت‌هایی از یک عکس بزرگ به عنوان Button



meh_ham
چهارشنبه 13 دی 1391, 13:27 عصر
سلام
چطور می‌تونم یه عکس رو طوری درست کنم که اگه کاربر روی قسمت‌های مختلفش کلیک کنه عملیات‌های مختلفی انجام بشه؟
مثلا اگه تو یه عکس یه خونه، یه ماشین و یه درخت باشه. هر کدوم از اینها که لمس بشه عملیات خاص خودش انجام بشه.
ممنون؛

hamid_hr
چهارشنبه 13 دی 1391, 14:26 عصر
http://stackoverflow.com/questions/4111937/android-bitmap-getpixel-is-annoyingly-inaccuracte

سلام

تو ابن ادرس مثل همين كار رو كرده

پيكسلي كه كليك شده رو بهت بر ميگردونه ميتوني باهاش كار كني

Nevercom
چهارشنبه 13 دی 1391, 14:32 عصر
راه حل من اینه
فرض کنیم شما یک تصویر دارید که قسمت های مختلفش باید به به touch واکنش نشون بده. یک عکس دیگه با همون اندازه ایجاد کنید با بکگراند یک دست (مثلاً سفید)، هر قسمتی که قراره به تاچ واکنش نشون بده رو با یک رنگ خاص مشخص کنید (محدوده رو زیاد کوچک نگیرید). یعنی عکس نهایی شما یک سری نقاط رنگی روی بکگراند سفید هست.

حالا تو رویداد onTouch عکس اصلی، با getX و getY مختصات ناحیه ی لمس شده رو بدست بیارید.
بعد با متد pixelColor از کلاس Bitmap، که آرگومان x و y رو میگیره، رنگ ناحیه لمس شده در عکس دوم رو بدست بیارید. یعنی محلی که در عکس اول (عکسی که نمایش داده میشه) رو بدست میارید و پاسش میدید به متد pixelColor تا رنگ همون ناحیه در عکس دوم رو بدست بیاره
حالا با یه select Case میتونید چک کنید که اگر کد رنگ فلان بود، یه واکنشی نشون بده و ....

Drawable drawable = getResources().getDrawable(R.drawable.rigmask);
bitmap = ((BitmapDrawable) drawable).getBitmap();

الان یه رفرنس از تصویری که ماسک رنگی هست داریم

این کد رویداد onTouch هست که من در پروژه ی خودم استفاده کردم:
@Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() == R.id.imageView1 || v.getId() == R.id.image_scrollview) {

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_UP:
int cordinate_Y = (int) ((event.getY() + v.getScrollY()) / diffH);
int cordinate_X = (int) ((event.getX() + v.getScrollX()) / diffW);
if ((Math.abs((int) event.getX() - startX) > 10)
|| (Math.abs((int) event.getY() - startY) > 10)) {
break;
}
Log.d(TAG,
"UP: "
+ Integer.toString((int) Math.abs(cordinate_X)
- startX));
int pixelColor = bitmap.getPixel(cordinate_X, cordinate_Y);
if (pixelColor != -1) {
showDetails(texts[map.get(pixelColor)],
images[map.get(pixelColor)]);

}

break;

}
}

return false;
}
تو این کد تغییر اندازه ی عکسی که نمایش داده میشه و ماسک لحاظ شده تا مختصات با هم منطبق بشن.
متد pixelColor یک کد رنگ از نوع int بر میگردونه که یک عدد منفی هست. شما کافیه این کد رنگ رو با کد رنگ های مشخصی که خودتون تعیین کردید مقایسه کنید.
دقت کنید که خروجی pixelColor از جنس rrggbb یت aarrggbb نیست ! شما یا باید این عدد رو به کد رنگ به اون فرمت تبدیل کنید و یا کد رنگ سازگار با خروجی این متد، برای رنگ هایی که تعیین کردید رو بدست بیارید (برای مقایسه و انجام واکنش مناسب)

چون نیاز بود این کدرنگها بصورت یک ثابت در پروژه ایجاد بشن، نیومدم و خروجی pixelColor رو تبدیل کنم، بجاش کد رنگ سازگار با خروجی pixelColor برای هر یک از اون رنگ ها بدست آوردم (تو همین متد خروجی pixelColor رو log کردم)

meh_ham
چهارشنبه 13 دی 1391, 15:41 عصر
راه حل من اینه
فرض کنیم شما یک تصویر دارید که قسمت های مختلفش باید به به touch واکنش نشون بده. یک عکس دیگه با همون اندازه ایجاد کنید با بکگراند یک دست (مثلاً سفید)، هر قسمتی که قراره به تاچ واکنش نشون بده رو با یک رنگ خاص مشخص کنید (محدوده رو زیاد کوچک نگیرید). یعنی عکس نهایی شما یک سری نقاط رنگی روی بکگراند سفید هست.

حالا تو رویداد onTouch عکس اصلی، با getX و getY مختصات ناحیه ی لمس شده رو بدست بیارید.
بعد با متد pixelColor از کلاس Bitmap، که آرگومان x و y رو میگیره، رنگ ناحیه لمس شده در عکس دوم رو بدست بیارید. یعنی محلی که در عکس اول (عکسی که نمایش داده میشه) رو بدست میارید و پاسش میدید به متد pixelColor تا رنگ همون ناحیه در عکس دوم رو بدست بیاره
حالا با یه select Case میتونید چک کنید که اگر کد رنگ فلان بود، یه واکنشی نشون بده و ....

Drawable drawable = getResources().getDrawable(R.drawable.rigmask);
bitmap = ((BitmapDrawable) drawable).getBitmap();

الان یه رفرنس از تصویری که ماسک رنگی هست داریم

این کد رویداد onTouch هست که من در پروژه ی خودم استفاده کردم:
@Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() == R.id.imageView1 || v.getId() == R.id.image_scrollview) {

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_UP:
int cordinate_Y = (int) ((event.getY() + v.getScrollY()) / diffH);
int cordinate_X = (int) ((event.getX() + v.getScrollX()) / diffW);
if ((Math.abs((int) event.getX() - startX) > 10)
|| (Math.abs((int) event.getY() - startY) > 10)) {
break;
}
Log.d(TAG,
"UP: "
+ Integer.toString((int) Math.abs(cordinate_X)
- startX));
int pixelColor = bitmap.getPixel(cordinate_X, cordinate_Y);
if (pixelColor != -1) {
showDetails(texts[map.get(pixelColor)],
images[map.get(pixelColor)]);

}

break;

}
}

return false;
}
تو این کد تغییر اندازه ی عکسی که نمایش داده میشه و ماسک لحاظ شده تا مختصات با هم منطبق بشن.
متد pixelColor یک کد رنگ از نوع int بر میگردونه که یک عدد منفی هست. شما کافیه این کد رنگ رو با کد رنگ های مشخصی که خودتون تعیین کردید مقایسه کنید.
دقت کنید که خروجی pixelColor از جنس rrggbb یت aarrggbb نیست ! شما یا باید این عدد رو به کد رنگ به اون فرمت تبدیل کنید و یا کد رنگ سازگار با خروجی این متد، برای رنگ هایی که تعیین کردید رو بدست بیارید (برای مقایسه و انجام واکنش مناسب)

چون نیاز بود این کدرنگها بصورت یک ثابت در پروژه ایجاد بشن، نیومدم و خروجی pixelColor رو تبدیل کنم، بجاش کد رنگ سازگار با خروجی pixelColor برای هر یک از اون رنگ ها بدست آوردم (تو همین متد خروجی pixelColor رو log کردم)

Nevercom عزیز

راه حل خیلی قشنگی بود. فقط اگه ممکنه در مورد کدنویسی‌ش یه مقدار بیشتر توضیح بده.
ممنون.

Nevercom
چهارشنبه 13 دی 1391, 18:04 عصر
خب این کدی که من گذاشتم رو از پروژه ی خودم کپی کردم، اما کلیت کار این هست.

دیگه کدهای مربوط به دسترسی به ImageView و تنظیم onTouchListener رو نزاشتم، چون احتمالاً خودتون با این موارد آشنا هستید.

من تو عکسم 25 تا نقطه ی حساس داشتم و از این روش استفاده کردم.
فرض کنیم عکسی که به کاربر نمایش داده میشه image هست و عکس رنگی mask
چون image به احتمال زیاد بنا به اندازه ی صفحه ریسایز میشه، نیاز هست که تغییر اندازه ی اون نسبت به تصویر mask محاسبه بشه تا مختصاتی که بدست میاریم دقیق باشه
عکس من در ScrollView نمایش داده میشد بنابر این مقدار Scroll شده هم در نظر گرفتم و نتیجه رو بر متغیری بنام diffH و diffW تقسیم کردم، که برای این هست که مختصات کلیک\لمس شده رو به اشل mask ببریم

قسمت مهمی از کد رو فراموش کردم بزارم، این کدهای متد onCreate هست:
sv = (ScrollView) findViewById(R.id.image_scrollview);
sv.setOnTouchListener(this);
final ImageView iv = (ImageView) findViewById(R.id.imageView1);

Drawable drawable = getResources().getDrawable(R.drawable.rigmask);
bitmap = ((BitmapDrawable) drawable).getBitmap();

final float maskW = bitmap.getWidth();
final float maskH = bitmap.getHeight();

ViewTreeObserver vto = iv.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
finalHeight = iv.getMeasuredHeight();
finalWidth = iv.getMeasuredWidth();
diffW = finalWidth / maskW;
diffH = finalHeight / maskH;
return true;
}
});
نکته ی مهمش اینه که اگه تو onCreate سعی کنید اندازه ی ImageView رو بدست بیارید، ممکنه مقدار 0 برگرده چون هنوز عملیات Draw به اتمام نرسیده.
برای همین محاسبات رو در متد onPreDraw انجام میدیم تا اطمینان حاصل کنیم که محاسبات درست انجام میشه

بقیه ی کد هم که مشخصه و توضیح دادم، مهم اینه که مقدار برگشتی pixelColor رو با ثابت هایی که از قبل تعیین کردید مقایسه کنید و بر اساس اون اکشنی رو انجام بدید.

سوالی داشتید در خدمتم

endexample
شنبه 07 بهمن 1391, 22:26 عصر
دوست عزیز مطلب جالبیه اما باید به این نکته هم دقت کرد که در سایز های نمایش مختلف با توجه به این که تغییرات متفاوتی در تصویر و مختصات کلیک داریم که عملا ثابت نیستند به چه صورت می خاین این مشکل رو حل کنید یهنی من نتونستم این رو برطرف کنم من می خواستم تصاویر و تم های خاص خودم رو پیاده سازی کنم ام امکان نداشت

meh_ham
یک شنبه 08 بهمن 1391, 00:07 صبح
دوست عزیز مطلب جالبیه اما باید به این نکته هم دقت کرد که در سایز های نمایش مختلف با توجه به این که تغییرات متفاوتی در تصویر و مختصات کلیک داریم که عملا ثابت نیستند به چه صورت می خاین این مشکل رو حل کنید یهنی من نتونستم این رو برطرف کنم من می خواستم تصاویر و تم های خاص خودم رو پیاده سازی کنم ام امکان نداشت


چرا؟
برا من که توی همه‌ی سایزها و ورژن‌ها درست کار می‌کنه. در واقع قسمت بزرگی از این کد برای حل همین مشکله!

این در واقع تمام کد هستش:


img.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {


if(event.getAction() == MotionEvent.ACTION_DOWN ) {

final float maskW = bm_color.getWidth();
final float maskH = bm_color.getHeight();

float diffW=1;
float diffH=1;
float finalHeight=1;
float finalWidth=1;

finalHeight = img.getMeasuredHeight();
finalWidth = img.getMeasuredWidth();
diffW = finalWidth / maskW;
diffH = finalHeight / maskH;

int cordinate_X = (int) ((event.getX()+ v.getScrollX()) / diffW );
int cordinate_Y = (int) ((event.getY()+ v.getScrollY()) / diffH );
int pixelColor = bm_color.getPixel(cordinate_X , cordinate_Y); //Get the pixel at coordinates



if(pixelColor == -1 ) // white color
{
// DO ANY THING
}

}

return true;


}

}); // end of ontouch



اگه سوالی هست بپرسید.