PDA

View Full Version : سوال: رنگ امیزی در پینت



سیامک علیزاده
پنج شنبه 27 فروردین 1394, 01:30 صبح
دوستان سلام برای رنگ امیزی در پینت با تابع بازگشتی به مشکل خوردم.میشه کمک کنین؟چجوری باید بنویسم؟

Javad_raouf
پنج شنبه 27 فروردین 1394, 17:26 عصر
اگه منظورت الگوریتم سطل رنگه که یادش بخیر پروژه کلاسیم بود:لبخند:
داخل فرمت یک PictureBox بزار و خاصیت SizeModeشو بزار روی AutoSize
اینم کد های مورد نیازت:
Bitmap bmp;

private void Form1_Load(object sender, EventArgs e)
{
Image imgOrginal = Image.FromFile("C:\\Example.bmp");
bmp = new Bitmap(imgOrginal);
pictureBox1.Image = bmp;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
ChangeColor(e.X, e.Y, Color.Pink);
pictureBox1.Refresh();
}


int changeColorConter = 0;
private int ChangeColor(int x, int y, Color newColor)
{
if (bmp.GetPixel(x, y).ToArgb() == newColor.ToArgb())
return 0;
changeColorConter = 0;
_ChangeColor(x, y, newColor);
return changeColorConter;


}
private void _ChangeColor(int x, int y, Color newColor)
{
int rgb = bmp.GetPixel(x, y).ToArgb();
bmp.SetPixel(x, y, newColor);
changeColorConter++;
////چهار جهت اصلی


if (y > 0 && bmp.GetPixel(x, y - 1).ToArgb() == rgb)//شمال
_ChangeColor(x, y - 1, newColor);
if (x > 0 && bmp.GetPixel(x - 1, y).ToArgb() == rgb)//غرب
_ChangeColor(x - 1, y, newColor);
if (x < bmp.Width && bmp.GetPixel(x + 1, y).ToArgb() == rgb)//شرق
_ChangeColor(x + 1, y, newColor);
if (y < bmp.Height && bmp.GetPixel(x, y + 1).ToArgb() == rgb)//جنوب
_ChangeColor(x, y + 1, newColor);


////چهار جهت فرعی


if (x > 0 && y > 0 && bmp.GetPixel(x - 1, y - 1).ToArgb() == rgb)//شمال غرب
_ChangeColor(x - 1, y - 1, newColor);
if (x < bmp.Width && y > 0 && bmp.GetPixel(x + 1, y - 1).ToArgb() == rgb)//شمال شرق
_ChangeColor(x + 1, y - 1, newColor);
if (y < bmp.Height && x > 0 && bmp.GetPixel(x - 1, y + 1).ToArgb() == rgb)//جنوب غرب
_ChangeColor(x - 1, y + 1, newColor);
if (y < bmp.Height && x < bmp.Width && bmp.GetPixel(x + 1, y + 1).ToArgb() == rgb)//جنوب شرق
_ChangeColor(x + 1, y + 1, newColor);
}
البته الگوریتم سطل رنگ به صورت بازگشتی خیلی بده چون اگر محدوده ای که می خوای رنگ کنی از خیلی کوچیک یکم بزرگتر باشه Stack Over Flow میده

سیامک علیزاده
جمعه 28 فروردین 1394, 14:04 عصر
سلام دوست عزیز همون طور که خودت گفتی تو این الگوریتم به مشکل استک اورفلو بر می خورم.نمیدونم چه کنم

Javad_raouf
شنبه 29 فروردین 1394, 09:22 صبح
این الگوریتم غیر بازگشتی:
Bitmap bmp;

private void Form1_Load(object sender, EventArgs e)
{
Image imgOrginal = Image.FromFile("C:\\Example.bmp");
bmp = new Bitmap(imgOrginal);
pictureBox1.Image = bmp;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
ChangeColor(e.X, e.Y, Color.Pink);
pictureBox1.Refresh();
}


private void ChangeColor(int X, int Y, Color newColor)
{
int rgb = bmp.GetPixel(X, Y).ToArgb();
if (rgb == newColor.ToArgb())
return;
List<Point> AllPoint = new List<Point>();
AllPoint.Add(new Point(X, Y));
for (int i = 0; i < AllPoint.Count; i++)
{
Point pnt = AllPoint[i];
if (i % 500 == 499)
{
////این دو خط تاثیری در برنامه ندارد و فقط قبل از اتمام تابع نتیجه جاری را به ما نشان می دهد
//Application.DoEvents();
//pictureBox1.Refresh();


////با این تیکه کد ما الگوریتم غیر بازگشتی رو با بازگشتی تلفیق کردیم تا سرعت بالاتر رود
//if (rgb == bmp.GetPixel(pnt.X, pnt.Y).ToArgb())
//{
// ChangeColor(pnt.X, pnt.Y, newColor);
// continue;
//}
}
bmp.SetPixel(pnt.X, pnt.Y, newColor);
////چهار جهت اصلی
if (pnt.Y > 0 && bmp.GetPixel(pnt.X, pnt.Y - 1).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X, pnt.Y - 1)))//شمال
AllPoint.Add(new Point(pnt.X, pnt.Y - 1));
if (pnt.X > 0 && bmp.GetPixel(pnt.X - 1, pnt.Y).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X - 1, pnt.Y)))//غرب
AllPoint.Add(new Point(pnt.X - 1, pnt.Y));
if (pnt.X < bmp.Width - 1 && bmp.GetPixel(pnt.X + 1, pnt.Y).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X + 1, pnt.Y)))//شرق
AllPoint.Add(new Point(pnt.X + 1, pnt.Y));
if (pnt.Y < bmp.Height - 1 && bmp.GetPixel(pnt.X, pnt.Y + 1).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X, pnt.Y + 1)))//جنوب
AllPoint.Add(new Point(pnt.X, pnt.Y + 1));


////چهار جهت فرعی


if (pnt.X > 0 && pnt.Y > 0 && bmp.GetPixel(pnt.X - 1, pnt.Y - 1).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X - 1, pnt.Y - 1)))//شمال غرب
AllPoint.Add(new Point(pnt.X - 1, pnt.Y - 1));
if (pnt.X < bmp.Width - 1 && pnt.Y > 0 && bmp.GetPixel(pnt.X + 1, pnt.Y - 1).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X + 1, pnt.Y - 1)))//شمال شرق
AllPoint.Add(new Point(pnt.X + 1, pnt.Y - 1));
if (pnt.Y < bmp.Height - 1 && pnt.X > 0 && bmp.GetPixel(pnt.X - 1, pnt.Y + 1).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X - 1, pnt.Y + 1)))//جنوب غرب
AllPoint.Add(new Point(pnt.X - 1, pnt.Y + 1));
if (pnt.Y < bmp.Height - 1 && pnt.X < bmp.Width - 1 && bmp.GetPixel(pnt.X + 1, pnt.Y + 1).ToArgb() == rgb && !AllPoint.Contains(new Point(pnt.X + 1, pnt.Y + 1)))//جنوب شرق
AllPoint.Add(new Point(pnt.X + 1, pnt.Y + 1));
}
}

با این کد به هیچ عنوان مشکل OverFlow نمی خوری ولی باز هم اگر سطح رنگ آمیزیت بیشتر از یک حدی باشه سیستم هنگ می کنه و مدت زمان زیادی رو باید منتظر باشی
خط 29 و خط 30 یعنی این تیکه کد:
//Application.DoEvents();

//pictureBox1.Refresh();
رو از حالت کامنت اگر در بیاری سیستم دیگه هنگ نمی کنه بلکه در حین رنگ آمیزی هر تیکه رو که رنگ کرد بهت نشون میده و تو در حین رنگ آمیزی می بینی چه اتفاقی داره میفته
ولی بازم رنگ آمیزی سطوح بزرگ خیلی کند پیش میرن:متفکر:

اگر این تیکه کد رو همونطور که گفتم از حالت کامنت برداری مثل من متوجه خواهی شده که ابتدای کار رنگ آمیزی با سرعت بالایی شروع می شود ولی کم کم از سرعت آن کاسته می شود علتش رو دقیقا نفهمیدم چرا:متفکر:

ولی یه ایده ای به ذهنم رسید که خط 34 تا 38 حاصل این ایده است
یعنی این تیکه کد:
//if (rgb == bmp.GetPixel(pnt.X, pnt.Y).ToArgb())
//{
// ChangeColor(pnt.X, pnt.Y, newColor);
// continue;
//}
این تیکه کد رو که از حالت کامنت در بیاری الگوریتمت میشه تلفیقی از بازگشتی و غیر بازگشتی:چشمک:
از اونجایی که ابتدای حلقه For سرعت الگوریتم بالا است و بعد از گذشت مدتی سرعت کاهش چشم گیری می کنه من با این تیکه کد کاری کردم که هر 500 پیکسل تابع به صورت بازگشتی خودش رو فراخونی کنه تا دوباره سرعت زیاد بشه
وقتی تست کردم دیدم واقعا سرعت خیلی رفت بالا:شیطان:
خودت می تونی تست کنی خیلی جالبه

Javad_raouf
شنبه 29 فروردین 1394, 09:26 صبح
از اساتید فروم درخواست می کنم علت این پدیده رو اگر می دونن توضیح بدن و اگر کسی بلده کد رو بهینه کنه
برام خیلی جالبه بدونم اشکال کار کجاست:متفکر:

ویرایش:
ای بابا باز یادم رفت بگم دوست عزیزhttp://barnamenevis.org/images/smilies/yahoo/124.gif