PDA

View Full Version : الگوریتم سطل رنگ



modirmasool
دوشنبه 10 خرداد 1389, 20:50 عصر
سلام دوستان
من میخوام سطل رنگ paint رو شبیه سازی کنم. چه راه هایی برای این کار وجود داره؟
ممنون.

aryasoft2872
دوشنبه 10 خرداد 1389, 22:05 عصر
اگه فقط نیاز شما در حد این باشه که روی اون پیکسلی که کلیک شد رنگ رو بگیره و در تمام تصویر اون رنگ رو تغییر بده که سادست ولی اگه مثل paint بخواد خطوط و اتصالات رو هم بشناسه فک می کنم مشکل باشه ولی برای حالت اول که گفتم می تونید از تنابع setPixel و getpixel استفاده کنید.

(ولی عجب تفاهمی یا شاید هم تله پاتی ای چون منم داشتم دیروز فکر می کردم چطوری میشه اینکارو کرد)

modirmasool
دوشنبه 10 خرداد 1389, 23:13 عصر
اگه فقط نیاز شما در حد این باشه که روی اون پیکسلی که کلیک شد رنگ رو بگیره و در تمام تصویر اون رنگ رو تغییر بده که سادست ولی اگه مثل paint بخواد خطوط و اتصالات رو هم بشناسه فک می کنم مشکل باشه ولی برای حالت اول که گفتم می تونید از تنابع setPixel و getpixel استفاده کنید.

(ولی عجب تفاهمی یا شاید هم تله پاتی ای چون منم داشتم دیروز فکر می کردم چطوری میشه اینکارو کرد)

نه منظورم دقیقا عین paint بود.
یکی از راهاش استفاده از پشته هستش. اما این روش سرعت پایینی داره. اگه دقت کرده باشین paint با سرعت بسیار بالایی شکل های درهم رو رنگ میکنه!

modirmasool
سه شنبه 11 خرداد 1389, 20:37 عصر
آقا کسی تا حاله این برنامه رو ننوشته؟!!!:افسرده:

Babak.Hassanpour
چهارشنبه 12 خرداد 1389, 14:28 عصر
خب چرا از API استفاده نمی کنید؟


Private Declare Function ExtFloodFill Lib "GDI32" (ByVal hDC As Long, _
ByVal X As Long, ByVal Y As Long, ByVal colorCode As Long, _
ByVal fillType As Long) As Long
Const FLOODFILLBORDER = 0
Const FLOODFILLSURFACE = 1

' Fill a region using the current color or brush
' OBJ can be a form or a control that exposes
' a device context (eg a picture box)
' X,Y are given in the current system coordinates
'
' If BORDERCOLOR is specified, fills the area
' enclosed by a border of that color
' If BORDERCOLOR is omitted, the area is filled with
' the color now at coordinates (x,y), and any
' different color is considered to a the border

Sub AreaFill(obj As Object, ByVal X As Long, ByVal Y As Long, _
ByVal colorCode As Long, Optional borderColor As Variant)

Dim x2 As Long, y2 As Long
Dim saveFillStyle As Long
Dim saveFillColor As Long

With obj
' convert into pixel coordinates
x2 = .ScaleX(X, .ScaleMode, vbPixels)
y2 = .ScaleY(Y, .ScaleMode, vbPixels)

' save FillStyle and FillColor properties
saveFillStyle = .FillStyle
saveFillColor = .FillColor
' enforce new properties
.FillStyle = 0
.FillColor = colorCode

If IsMissing(borderColor) Then
' get color at given coordinates
borderColor = .Point(X, Y)
' change all the pixels with that color
ExtFloodFill .hDC, x2, y2, borderColor, FLOODFILLSURFACE
Else
ExtFloodFill .hDC, x2, y2, borderColor, FLOODFILLBORDER
End If

' restore properties
.FillStyle = saveFillStyle
.FillColor = saveFillColor
End With

End Sub

modirmasool
چهارشنبه 12 خرداد 1389, 21:06 عصر
خب چرا از API استفاده نمی کنید؟


Private Declare Function ExtFloodFill Lib "GDI32" (ByVal hDC As Long, _
ByVal X As Long, ByVal Y As Long, ByVal colorCode As Long, _
ByVal fillType As Long) As Long
Const FLOODFILLBORDER = 0
Const FLOODFILLSURFACE = 1

' Fill a region using the current color or brush
' OBJ can be a form or a control that exposes
' a device context (eg a picture box)
' X,Y are given in the current system coordinates
'
' If BORDERCOLOR is specified, fills the area
' enclosed by a border of that color
' If BORDERCOLOR is omitted, the area is filled with
' the color now at coordinates (x,y), and any
' different color is considered to a the border

Sub AreaFill(obj As Object, ByVal X As Long, ByVal Y As Long, _
ByVal colorCode As Long, Optional borderColor As Variant)

Dim x2 As Long, y2 As Long
Dim saveFillStyle As Long
Dim saveFillColor As Long

With obj
' convert into pixel coordinates
x2 = .ScaleX(X, .ScaleMode, vbPixels)
y2 = .ScaleY(Y, .ScaleMode, vbPixels)

' save FillStyle and FillColor properties
saveFillStyle = .FillStyle
saveFillColor = .FillColor
' enforce new properties
.FillStyle = 0
.FillColor = colorCode

If IsMissing(borderColor) Then
' get color at given coordinates
borderColor = .Point(X, Y)
' change all the pixels with that color
ExtFloodFill .hDC, x2, y2, borderColor, FLOODFILLSURFACE
Else
ExtFloodFill .hDC, x2, y2, borderColor, FLOODFILLBORDER
End If

' restore properties
.FillStyle = saveFillStyle
.FillColor = saveFillColor
End With

End Sub


ممنون اما من الگوریتمشو لازم دارم.

مصطفی ساتکی
پنج شنبه 13 خرداد 1389, 13:12 عصر
دوست عزیز اینجا بخش الگوریتم و به زبان خاصی کد نمی نویسن.در ضمن در اختیار گذاشتن کد برای دیگران اختیاریه.
اما برای انجام این کار شما میتونید به نحوه زیر عمل کنید.

SelectObject(Canvas.Handle, CreateSolidBrush(clRed));
ExtFloodFill(Canvas.Handle,CurrentX,CurrentY,Borde rColor,FLOODFILLBORDER);

شما در ابتدا Brush مربوط به DC رو تنظیم می کنید و سپس با ExtFloodFill کار مورد نظر رو انجام می دید.
اما الگوریتم پیاده سازی این function
با شروع از نقطه ای که کلیک میشه به صورت بازگشتی هر 8 خانه مجاور یک پیکسل را چک می کنید در صورتیکه رنگ هر کدام از پیسکل های مجاور برابر پیکسل مرکزی باشد دوباره این رویه بازگشتی با مقدار همسایه جدید فراخوانی می نماید. اینکار را تا زمانی انجام می دهید که دیگر پیسکل در مجاورتی پیکسل جاری وجود نداشته باشد که دارای رنگی برابر با پیکسل جاری داشته باشد . در صورت برابر بودن رنگ پیکسل مجاور به رنگی که مد نظر ماست رنگ آن پیکسل را تنظیم می کنیم.
برای گرفتن و تنظیم مقدار پیکسل در هر x,y به ترتیب می توانید ار توابع GetPixel و SetPixel استفاده نماید.
در پیاده سازی این تابع شما می تونید یا توابع بازگشتی استفاده کنید که در صورت اینکه تصویر دارای ابعاد بزرگی باشه ممکن فضای زیادی از Stack رو اشغال کنید. برای رفع این مکشل شما می تونید یه Stack رو به صورت دستی تعریف کنید و هر نقطه همسایه رویت شده رو در اون قرار بده و در صورت استفاده کرده اون نقطه همسایه اونو از بالای این Stack حذف کنید.
برای پیاده سازی این روش برای بهینه سازی در سرعت می تونید بجای استفاده کردن از 2دو api فوق از روش scanline یا آدرس مربوط به هر ردیف Bitmap استفاده نماید.

این روش به صورت دینامیک تر در نرم افزار ویرایش تصویر تحت عنوان اعصای جادویی)Magic Wand) یا سطل رنگ )Paint Bucket مرد استفاده قرار می گیره .که در اونجا رنگ همسایه رو به صورت ثابت در نظر نمی گیرن به threshold این مقایسه صورت می گیره یعنی اگر تفاضل رنگ پیکسل مجاور با پیکسل جاری کمتر از Threshold مورد نظر باشه اون نقطه هم جزء ناحیه هدف میشه

Babak.Hassanpour
پنج شنبه 13 خرداد 1389, 14:26 عصر
ببخشید این تاپیک انتقال داده شده گویا.چون من بعلت اینکه توی بخش وی بی بود نمونه کد وی بی ضمیمه کردم.