PDA

View Full Version : سوال: سطل رنگ برنامه مشابه Paint در #C



soorenpersia
سه شنبه 29 دی 1394, 16:55 عصر
با درود
برای طراحی برنامه مشابه سطل رنگ ویندوز از کد زیر کمک گرفتم اما موقع اجرا سیستم هنگ میکنه... کلی هم تو نت گشتم اما متاسفانه مشکل حل نشده , و نظرات بیشتر جنبه راهنمایی دارند تا راه حل.
از اساتید اگر علت رو تشخیص دادند لطف کنند راهنمایی بفرمایند و یا اگر کد سی شارپ مشابه برای سطل رنگ میشناسید لطفا اطلاع دهید.تو همین سایت هم بعضی از دوستان دیگه هم با این کد مشکل داشتند و کلا راه حلی پیدا نشد!


بعد از کلیک روی آیکون سطل رنگ که یک picture box هست طبق کد زیر آرگومان ها به تابع fill ارسال میشه وبا فراخوانی تابع fill و در واقع کلیک بر روی قسمتهای انتخابی جهت رنگ شدن اتفاق خاصی نمیوفته و برنامه هنگ میکنه.





private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{

if (act == "color")
{

fill(bmp, e.X, e.Y, bmp.GetPixel(e.X, e.Y));
pictureBox1.Image = bmp;

}
=============
private void fill(Bitmap picture, int x, int y, Color bcolor)
{

if (x > 0 && x < picture.Width && y > 0 && y < picture.Height)
{

Point p = new Point(x, y);
Stack<Point> s = new Stack<Point>();
s.Push(p);
while (s.Count != 0)
{
p = s.Pop();
Color currentcolor = picture.GetPixel(p.X, p.Y);

if (currentcolor == bcolor)
{
picture.SetPixel(p.X, p.Y, currentcolor);
s.Push(new Point(p.X - 1, p.Y));
s.Push(new Point(p.X + 1, p.Y));
s.Push(new Point(p.X, p.Y - 1));
s.Push(new Point(p.X, p.Y + 1));
}
}
}
}

ژیار رحیمی
سه شنبه 29 دی 1394, 18:35 عصر
سلام دوست گرامی شما نحوه کار (سطل رنگ) به درستی درک نکردی(یا تجربه کمتری در کار با گرافیک در #C داری).تو بخش نمونه برنامه های تالار نمونه برنامه paint (کار با گرافیگ)هست دانلود کن و کدها و نحوه پیاده سازی بررسی کن.درک بهتری از نحوه پیاده سازی برنامه paint بدست میاری

soorenpersia
سه شنبه 29 دی 1394, 20:33 عصر
سلام دوست گرامی شما نحوه کار (سطل رنگ) به درستی درک نکردی(یا تجربه کمتری در کار با گرافیک در #C داری).تو بخش نمونه برنامه های تالار نمونه برنامه paint (کار با گرافیگ)هست دانلود کن و کدها و نحوه پیاده سازی بررسی کن.درک بهتری از نحوه پیاده سازی برنامه paint بدست میاری

اگر مشخصا درباره سطل رنگ توضیح میدادید خیلی بهتر میشد.برنامه نمونه تو سایت خیلی مختصره و سطل رنگ هم نداره. درمورد سایر قسمتهای Paint فعلا مشکلی نیست .فقط این قسمت مشکل داره که باید درست کار کنه اما ..؟یه جای کار ایراد داره شاید در حد یکی دو خط.
جالب اینجاست که کمتر پیدا میشن کد رو درست کنند.

این دوستمون هم مٍثل ما با این کد مشکل داره
(http://barnamenevis.org/showthread.php?515826-%D8%AA%D8%BA%D9%8A%D9%8A%D8%B1-%D8%B3%D8%A7%D9%8A%D8%B2-%D8%B9%D9%83%D8%B3-%D9%88-%D8%B3%D8%A7%D8%AE%D8%AA-%D8%B3%D8%B7%D9%84-%D8%B1%D9%86%DA%AF-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-paint&highlight=paint)

با تشکر

soorenpersia
جمعه 02 بهمن 1394, 13:19 عصر
اساتید نظری ندارند ؟ (http://stackoverflow.com/questions/34865402/paint-bucket-function-code-in-c-sharp-hangs-when-running)

bardia225
جمعه 02 بهمن 1394, 13:24 عصر
این مشکل رو تو فروم Stackoverflow هم مطرح شده , اما اونجا هم به نتیجه ای نرسیدند, ظاهرا همه با سطل رنگ مشکل دارند!!

http://stackoverflow.com/questions/3...s-when-running (http://stackoverflow.com/questions/34865402/paint-bucket-function-code-in-c-sharp-hangs-when-running)

khokhan
جمعه 02 بهمن 1394, 20:02 عصر
اساتید نظری ندارند ؟

یه پیشنهاد براتون دارم............................ :لبخند:
اگه می خوای هم خیال خودت راحت باشه و هم خیال کاربران برنامه ات ..........می تونی از API خود ویندوز استفاده کنی
برای مثال من یه نمونه براتون می زارم ..... بقیه اش با خودتونه تا با یه خورده خلاقیت و سلیقه مطابق میلتون تغییرات لازم رو بدین
می تونین کنار آیکن سطل رنگ چند تا پلت رنگی قرار بدین و کاربر ابتدارنگ مورد نظر رو از پلتها انتخاب کنه بعد روی آیکن سطل رنگ کلیک کنه و ........
کد رنگ انتخابی بایستی در این خط جایگزین بشه (عدد رنگ داخل پرانتز باید تغییر کنه):


hBr = CreateSolidBrush(265);


مثال :

ژیار رحیمی
جمعه 02 بهمن 1394, 21:41 عصر
سلام منم یه نمونه Paint چند سال پیش نوشتم امیدوارم مورد استفاده واقع شود
138575

مهیار.
جمعه 02 بهمن 1394, 23:27 عصر
با سلام
این شبه کد رو هم نگاه کن فکر کنم بتونی بنویسی


138580

soorenpersia
شنبه 03 بهمن 1394, 00:53 صبح
یه پیشنهاد براتون دارم............................ :لبخند:
اگه می خوای هم خیال خودت راحت باشه و هم خیال کاربران برنامه ات ..........می تونی از API خود ویندوز استفاده کنی
برای مثال من یه نمونه براتون می زارم ..... بقیه اش با خودتونه تا با یه خورده خلاقیت و سلیقه مطابق میلتون تغییرات لازم رو بدین
می تونین کنار آیکن سطل رنگ چند تا پلت رنگی قرار بدین و کاربر ابتدارنگ مورد نظر رو از پلتها انتخاب کنه بعد روی آیکن سطل رنگ کلیک کنه و ........
کد رنگ انتخابی بایستی در این خط جایگزین بشه (عدد رنگ داخل پرانتز باید تغییر کنه):


hBr = CreateSolidBrush(265);


مثال :

خیلی ممنون بابت راهنمایی.اما دشوار تر از حل مشکل ,گنجاندن کد های جدید در برنامه هست که با انواع ارور ها مواجه میشی.
وقتی کد شما رو وارد میکنم باز سطل رنگ عمل نمیکنه و ارور میده.مربوط به تعریف شی گرافیک..تا جای ممکن تغییرات رو لحاظ کردم

soorenpersia
شنبه 03 بهمن 1394, 01:11 صبح
با سلام
این شبه کد رو هم نگاه کن فکر کنم بتونی بنویسی


مشکل اصلی مربوط به ذخیره و تشخیص محدوده نقاط هست که باید در stack ذخیره بشه. تو کد بالای صفحه هم مشکل stack over flow پیش میاد که سیستم هنگ میکنه.

خیلی ممنون

khokhan
شنبه 03 بهمن 1394, 02:05 صبح
خیلی ممنون بابت راهنمایی.اما دشوار تر از حل مشکل ,گنجاندن کد های جدید در برنامه هست که با انواع ارور ها مواجه میشی.
وقتی کد شما رو وارد میکنم باز سطل رنگ عمل نمیکنه و ارور میده.مربوط به تعریف شی گرافیک..تا جای ممکن تغییرات رو لحاظ کردم
به این دلیله که شما در یک رویداد واحد به طور هم زمان چندین حالت رو پیاده کردین
و از طرف دیگه هم در رویداد pictureBox1_MouseMove و هم در رویداد pictureBox1_MouseUp کد نویسی کردین
و این دو رویداد در یک زمان عمل می کنن و همه چیز به هم می ریزه

بهترین کار اینه که اولاً اون کد فعال کردن سطل رنگ رو ببری به یه رویداد دیگه مثلا pictureBox1_MouseClick
به این شکل :


private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (act=="color")
{
this.Fill(e);
}
}

و بعد از اون .......... موقع کلیک بر روی سطل رنگ اون دو تا رویداد رو با کد نویسی خاموش کنی :لبخند: با این دستور :

pictureBox1.MouseMove -= new MouseEventHandler(pictureBox1_MouseMove);
pictureBox1.MouseUp -= new MouseEventHandler(pictureBox1_MouseUp);

یعنی کد تون رو اینطوری بنویسین :


private void pictureBox5_Click(object sender, EventArgs e)
{
settool(pictureBox5);
pictureBox1.Cursor = Cursors.Hand;
act = "color";
pictureBox1.MouseMove -= new MouseEventHandler(pictureBox1_MouseMove);
pictureBox1.MouseUp -= new MouseEventHandler(pictureBox1_MouseUp);
pictureBox21.Visible = false;
pictureBox22.Visible = false;
pictureBox23.Visible = false;
pictureBox24.Visible = false;
}

بعد هر جا که لازم بود تا هر کدوم از این رویداد ها فعال بشه باز دوباره فعالشون کنی ...به این شکل که اون علامت منهای قبل از علامت مساوی رو به بعلاوه یا پلاس (+) تغییر بدی :

اینطوری :

pictureBox1.MouseMove += new MouseEventHandler(pictureBox1_MouseMove);
pictureBox1.MouseUp += new MouseEventHandler(pictureBox1_MouseUp);
این هم تصویر پروژه خودتون که رنگ آمیزی کار می کنه :

soorenpersia
پنج شنبه 08 بهمن 1394, 03:04 صبح
با تشکر
البته اگر دوباره رویداد رو فعال کنیم , رویداد mouse move ارور میده.

soorenpersia
پنج شنبه 08 بهمن 1394, 15:22 عصر
با درود و تشکر از همه دوستان که در این مورد راهنمایی کردند , الگوریتم های عنوان شده هر کدام دارای نقاط قوت و ضعفی هستند که هماهنگی آنها با سایر اجزای برنامه کمی دشوار است.
برای اجرای الگوریتم سطل رنگ در #C روشهای بسیاری وجود دارد . الگوریتم زیر جهت ایده برداری و رفع اشکال دوستان برنامه نویس که تقریبا بدون مشکل اجرا میشود ارائه شده است .




void Form1_Paint(object sender, PaintEventArgs e)
{
using (Bitmap bitmap = new Bitmap(500, 500))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
List<Point> points = new List<Point>();
for (double i = 0; i < 10; i++)
{
double dist = (i % 2 == 0) ? 100 : 50;
double x = 200 + Math.Cos(i / 10d * Math.PI * 2d) * dist;
double y = 200 + Math.Sin(i / 10d * Math.PI * 2d) * dist;
points.Add(new Point((int)x, (int)y));
}
g.DrawPolygon(Pens.Black, points.ToArray());
}

Fill(bitmap, 200, 200, Color.Red);

e.Graphics.DrawImage(bitmap, 0, 0);
}
}

void Fill(Bitmap bitmap, int x, int y, Color color)
{
BitmapData data = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
int[] bits = new int[data.Stride / 4 * data.Height];
Marshal.Copy(data.Scan0, bits, 0, bits.Length);

LinkedList<Point> check = new LinkedList<Point>();
int fillTo = color.ToArgb();
int fillFrom = bits[x + y * data.Stride / 4];
bits[x + y * data.Stride / 4] = fillTo;

if (fillFrom != fillTo)
{
check.AddLast(new Point(x, y));
while (check.Count > 0)
{
Point cur = check.First.Value;
check.RemoveFirst();

foreach (Point off in new Point[] {
new Point(0, -1), new Point(0, 1),
new Point(-1, 0), new Point(1, 0)})
{
Point next = new Point(cur.X + off.X, cur.Y + off.Y);
if (next.X >= 0 && next.Y >= 0 &&
next.X < data.Width &&
next.Y < data.Height)
{
if (bits[next.X + next.Y * data.Stride / 4] == fillFrom)
{
check.AddLast(next);
bits[next.X + next.Y * data.Stride / 4] = fillTo;
}
}
}
}
}

Marshal.Copy(bits, 0, data.Scan0, bits.Length);
bitmap.UnlockBits(data);
}

yacjam
شنبه 26 تیر 1395, 19:04 عصر
سلام دوست گرامی شما نحوه کار (سطل رنگ) به درستی درک نکردی(یا تجربه کمتری در کار با گرافیک در #C داری).تو بخش نمونه برنامه های تالار نمونه برنامه paint (کار با گرافیگ)هست دانلود کن و کدها و نحوه پیاده سازی بررسی کن.درک بهتری از نحوه پیاده سازی برنامه paint بدست میاری

سلام تو نمونه برنامه هاتون سطل رنگ نیست چرا این تابع عمل نمیکنه؟