C# - Crop Image in a Ellipse Shape using Graphics

Posted by ေတဇာလင္း Tuesday, 7 February 2017 0 comments

မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမမ်ား အားလံုးပဲ မဂၤလာပါဗ်ာ။ ဒီေန႔ေတာ့ က်ေနာ္တို႔ Visual Studio C# ကို အသံုးျပဳၿပီး Image တစ္ခုကို မိမိႏွစ္သက္ရာေနရာအား Ellipse ပံုစံျဖစ္ ဘရ္လိုျဖတ္ယူႏိုင္မလဲဆိုတာေလးကို ေလ့လာၾကည့္ပါ့မရ္။ နည္းလမ္းေပါင္းစံု ရွိတဲ့အထဲကေနၿပီ အလြရ္ကူဆံုးနည္းလမ္းျဖစ္တဲ့ Graphic Library ေအာက္က DrawImage() Method ကို အသံုးျပဳၿပီး ေလ့လာၾကည့္ပါ့မရ္။ က်ေနာ့္ ေလ့က်င့္ခန္းေတြကေတာ့ စတင္ ေလ့လာသူမ်ား အတြက္သာ ရည္ရြယ္ပါတရ္။ ဒါေၾကာင့္ သိေနၿပီးသား သူမ်ားအေနနဲ႔ နားလည္ေပးၾကဖို႔နဲ႔ က်ေနာ္ရဲ႕ တင္ျပပံု မွားယြင္းတာမ်ားရွိခဲ့ရင္ ျပန္လည္ေထာက္ျပေပးႏိုင္ဖို႔ ေမွ်ာ္လင့္ပါတရ္ဗ်။
ဒါကေတာ့ က်ေနာ္တို႔ Project မွာ အသံုးျပဳမရ္ Library File ေတြပါ။ က်ေနာ္ကေတာ့ ေအာက္ကပံုအတိုင္း ပံုစံခ်ထားပါတရ္ဗ်ာ။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ GUI ကို ႀကိဳက္သလို ပံုစံေဖာ္ႏိုင္ပါတရ္။
က်ေနာ္ကေတာ့ ေအာက္ကပံုအတိုင္း ပံုစံခ်ထားပါတရ္ဗ်ာ။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ GUI ကို ႀကိဳက္သလို ပံုစံေဖာ္ႏိုင္ပါတရ္။
ဒီေန႔ ေလ့က်င့္ခန္းမွာေတာ့ Crop Processing အတြက္ သီးသန္႔ Button မထည့္ေတာ့ပဲ picOriginalImg ရဲ႕ Event ေတြကပဲ Processing လွမ္းလုပ္တဲ့ ပံုစံေလးနဲ႔ ေလ့လာၾကည့္သြားပါ့မရ္။ အသံုးျပဳသြားမရ္႕ Event ေတြကေတာ့ MouseDown, MouseMove and MouseUp တို႔ပဲ ျဖစ္ပါတရ္။ MouseDown Event ထဲမွာေတာ့ PictureBox ေပၚသို႔ Left_Click ျဖင့္ Mouse Point ခ် Down/Click ေပးလိုက္တဲ့အခ်ိန္မွာ လုပ္ေစခ်င္တဲ့ အလုပ္ေတြကို ခိုင္းေစႏိုင္ပါတရ္။ MouseMove Event ကေတာ့ Left_Clik ေပးၿပီး Drag ဆြဲတဲ့အခ်ိန္မွာ လုပ္ေစခ်င္တဲ့ အလုပ္ေတြကို ခိုင္းဖို႔ပါ။ MouseUp မွာေတာ့ Mouse Down and Move အလုပ္ ႏွစ္ခုလုပ္ၿပီး ျပန္လႊတ္လိုက္တဲ့အခ်ိန္မွာ လုပ္ေစခ်င္တဲ့ အလုပ္ေတြကို ခိုင္းေစႏိုင္ပါတရ္။ ဒီေန႔ ေလ့က်င့္ခန္းမွာေတာ့ Event သံုးခုလံုးၿပီးမွ Processing တစ္ခု လုပ္တဲ့ပံုစံနဲ႔ ခ်ဥ္းကပ္ထားပါတရ္။
Event တစ္ခုခ်င္းစီထဲက Code ကို အေသးစိတ္ေလ့လာၾကည့္ၾကရေအာင္...။ picOriginalImg ရဲ႕ MouseDown_Event ထဲသို႔ ၀င္၍ ေအာက္ပါ Coding ကိုေရးယူလုိက္ပါဗ်ာ။ Method ရဲ႕ အျပင္ဘက္မွာ Global Variable အျဖစ္ x, y, cropWidth, cropHeight ဆိုၿပီး ေလးခုေၾကျငာထားပါတရ္။ ၄င္း variable ေတြကို ဒီ Event တစ္ခုတည္းကတင္ မဟုတ္ဘဲ အျခားေသာ Event ေတြကပါ ေခၚသံုးႏိုင္ေအာင္လို႔ Global ေၾကျငာထားျခင္းျဖစ္ပါတရ္။ MouseDown_Event ထဲမွာ ခိုင္းထားတဲ့အလုပ္ကေတာ့ ရိုးရွင္းပါတရ္။ စစခ်င္းမွာ if()Statement နဲ႔ Mouse ရဲ႕ Event(Action)ကိုဖမ္းၿပီး Left Click ျဖစ္လား/မျဖစ္လားဆိုၿပီး စစ္ထားပါတရ္။ Left_Click Action ျဖစ္ခဲ့ရင္ေတာ့ က်ေနာ္တို႔ Global ေၾကျငာထားေသာ x, y variable ထဲကို မိတ္ေဆြကို Mouse Down/Click ေပးလိုက္ေသာ X,Y Coordinate ကို လွမ္းထည့္လိုက္ပါတရ္။ ဆိုလိုတာကေတာ့ မိတ္ေဆြတို႔ Crop ရဲ႕ Image ဟာ ဒီ X, Y Coordinate က စပါ့မရ္လို႔ မွတ္ထားခိုင္းလိုက္တာပဲျဖစ္ပါတရ္။ ကာဆာကို Cross သံုးထားတာကေတာ့ Mouse Down and Drag လုပ္ေနတဲ့အခ်ိန္မွာ ကာဆာကို Cross ပံုစံေလး ျပေနေစခ်င္တဲ့အတြက္ေၾကာင့္ပါ။ ဒီေလာက္ဆိုရင္ေတာ့ MouseDown_Event မွာ ခိုင္းေစထားတဲ့အခ်ိန္ေတြကို သိၿပီလို႔ ထင္ပါတရ္ဗ်ာ။
picOriginalImg ရဲ႕ MouseMove_Event ထဲသို႔၀င္ၿပီး ေအာက္ပါ Coding ကိုထပ္ေရးယူလိုက္ပါဗ်ာ။ ဒီမွာလည္း ခက္ခဲတာ ဘာမွမပါ ပါဘူးဗ်ာ။ Coding စစခ်င္းမွာ က်ေနာ္တို႔ Crop လုပ္ခ်င္တဲ့ PictureBox ထဲမွာ Image Load ဆြဲတင္ၿပီး သားရွိ/မရွိကို အရင္စစ္ထားပါတရ္။ မရွိရင္ေတာ့ MouseMove_Event အလုပ္လုပ္မွာမဟုတ္ပါဘူး။ ရွိခဲ့ရင္ေတာ့ ဒုတိယ if()statement နဲ႔ Mouse ရဲ႕ Action ကိုဖမ္းၿပီး Left-Click ဖိၿပီး Drag(Move) လုပ္တာ ဟုတ္/မဟုတ္ ထပ္စစ္ထားပါတရ္။ ဟုတ္ခဲ့ရင္ေတာ့ ဘရ္ေလာက္ Width, ဘရ္ေလာက္ Height ေလာက္ထိ Crop လုပ္မရ္ဆုိတဲ့ မိတ္ေဆြတို႔ Drag ဆြဲသြားေသာ Width နဲ႔ Height ကိုမွတ္ပါတရ္။ ရလာတဲ့ တန္ဖိုးေတြကိုေတာ့ အေပၚမွာ global ေၾကျငာခဲ့တဲ့ cropWidth နဲ႔ cropHeight ထဲကို သြားသိမ္းထားပါတရ္။ ဒီမွာ ေနာက္ဆံုး MouseMove ရဲ႕ ဆံုးမွတ္ျဖစ္တဲ့ X,Y Coordinate ေတြထဲက စမွတ္(X,Y coordinate) (e.X - x နဲ႔ e.Y - y) ကိုျပန္ႏုတ္ထားတာကေတာ့ မိတ္ေဆြတို႔ Drag ဆြဲယူလိုက္တဲ့ Width and Height ကို အတိအက်လိုခ်င္လို႔ပါ။ နားမလည္ခဲ့ရင္ေတာ့ X,Y Coordinate မ်ဥ္းဆြဲၿပီး Trace လုပ္ၾကည့္ႏိုင္ပါတရ္။ ဒီ crop Image ရဲ႕ Widht and Height ဖမ္းႏိုင္တဲ့အဆင့္နဲ႔တင္ တကယ္ဆိုရင္ MouseMove_Event ရဲ႕ အလုပ္က ၿပီးပါတရ္။ ဒါကိုမွကြန္႔ၿပီး Selected Area ကို ထင္သာျမင္သာရွိေအာင္ Rectangle and Ellipse ပံုစံေလးဆြဲၿပီး ျပေစခ်င္လို႔သာ ေအာက္က သံုးေၾကာင္းက ထပ္ေရးရတာ ျဖစ္ပါတရ္။ ေအာက္က သံုးေၾကာင္းမပါလည္း အလုပ္ျဖစ္ပါတရ္။
Rectangle and Ellipse ဆြဲဖို႔အတြက္ DrawRectangle() နဲ႔ DrawEllipse() Method ေတြကိုသံုးထားပါတရ္။ Parameter ငါးခုပါၿပီး ပထမ parameter ကေတာ့ Graphic ကိုဆြဲခ်င္တဲ့ Pen Class ပါ။ ဒီမွာေတာ့ Pen ရဲ႕ Color ကို Assign လုပ္ေပးထားပါတရ္။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ ႏွစ္သက္သလို အျခား properties ေတြကို ထည့္သြင္းအသံုးျပဳႏုိင္ပါတရ္။ ေနာက္ x,y Paramenter ႏွစ္ခုကေတာ့ Graphic ရဲ႕ စမွတ္ Coordinate အမွတ္ျဖစ္ပါတရ္။ ေနာက္ဆံုး Parameter ႏွစ္ခုကေတာ့ ဆြဲယူမရ္႕ Graphic ရဲ႕ Width and Height ကို သတ္မွတ္ေပးလိုက္တာပါ။ ဒီမွာ က်ေနာ္ Graphic လုပ္ငန္းစဥ္ကို ႏွစ္ေၾကာင္းကိုတစ္ေၾကာင္းတည္းျဖစ္ေအာင္ ေပါင္းေရးထားတာပါ။ နားလည္ရ ခက္သြားမရ္ဆိုရင္ေတာ့ ...
Graphics gfx = picOriginalImg.CreateGraphics();
gfx.DrawRectangle(Pens.Gold, x, y, cropWidth, cropHeight);
gfx. DrawEllipse(Pens.DarkGoldenrod, x, y, cropWidth, cropHeight);
အခုလိုပံုစံ ခြဲေရးလို႔ရႏိုင္ပါတရ္။ ပထမ တစ္ေၾကာင္းက Graphic ဆြဲယူမရ္႕ Container ကိုသတ္မွတ္ေပးတာပါ။ က်ေနာ္တို႔က picOriginalImg အေပၚမွာဆြဲမွာျဖစ္လို႔ ၄င္း PictureBox ကိုညႊန္းေပးထားတာပဲျဖစ္ပါတရ္။ ဒုတိယ ႏွစ္ေၾကာင္းကေတာ့ သတ္မွတ္ထားတဲ့ Container ေပၚမွာ မိမိႏွစ္သက္ရာ Method ကိုအသံုးျပဳၿပီး Graphic တစ္ခုဆြဲယူ လိုက္တာပဲျဖစ္ပါတရ္။ နားလည္ၾကမရ္လို႔ ထင္ပါတရ္။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ ႏွစ္ေၾကာင္းတစ္ေၾကာင္းေပါင္းၿပီးျဖစ္ေစ၊ ႏွစ္ေၾကာင္းခြဲေရးၿပီးျဖစ္ေစ မိမိအားသာရာကို အသံုးျပဳႏိုင္ပါတရ္။
picOriginalImg.Refresh(); 
PictureBox ကို အၿမဲ Refresh ေပးထားတာကေတာ့ MouseMove Event အတြင္း ေရႊ႕သြားေသာ Pixel အတိုင္း ဆြဲယူသြားေသာ Graphic ေတြကို ျပန္ ျပန္ဖ်တ္ထုတ္ခ်င္လို႔ပါ။ မိတ္ေဆြကို သေဘာတရားကို နားလည္ေစခ်င္ရင္ေတာ့ ၄င္း cmd line ကို off ၿပီး run ၾကည့္ႏိုင္ပါတရ္။
ေနာက္ဆံုး Event တစ္ခုျဖစ္တဲ့ MouseUp_Event ကိုဆက္ေလ့လာၾကည့္မရ္။ ဒါေၾကာင့္ picOriginalImg ရဲ႕ MouseUp Event ထဲသို႔၀င္၍ ေအာက္ပါ Coding ေလးကို ၀င္ေရးယူလိုက္ပါဗ်ာ။ Coding စစခ်င္းမွာ crop Area သတ္မွတ္ေနတဲ့အခ်ိန္ Cross ေပးထားေသာ ကာဆာကို မူလပံုစံျဖစ္တဲ့(မွ်ားေခါင္းပံု) Default ျပန္ေပးလိုက္ပါတရ္။ if()statemet ကေတာ့ crop Area ရွိ/မရွိ စစ္ထားတာပါ။ မိတ္ေဆြတို႔ crop လုပ္မရ္႕ Area ဟာ 1 pixel ထက္နည္းေနရင္ အလုပ္လုပ္မွာ မဟုတ္ပါဘူးဗ်ာ။ ေနာက္တစ္ေၾကာင္းကေတာ့ Crop မလုပ္ရေသးတဲ့ Original Image ကို Bitmap အျဖစ္ Clone ပြားယူလိုက္တာပဲျဖစ္ပါတရ္။ ေနာက္တစ္ေၾကာင္းကေတာ့ Crop လုပ္ယူလိုက္တဲ့ Image ကို သိုေလွာင္ဖို႔အတြက္ Bitmap အသစ္တစ္ခု တည္ေဆာက္လိုက္တာပါ။ ၿပီးရင္ေတာ့ ၄င္း Bitmap ကို Container အျဖစ္ထားၿပီး Graphic ဆြဲယူပါ့မရ္လို႔ ခိုင္းပါတရ္။ SmoothingMode သံုးထားတာကေတာ့ မိတ္ေဆြတို႔ ဖန္တီးယူလိုက္တဲ့ Graphic ကို Smooth ျဖစ္ေစခ်င္လို႔ပါ။ ၿပီးရင္ က်ေနာ္တို႔က Crop Image ကို Ellipse ပံုစံ ျဖတ္ယူမွာျဖစ္လို႔ Ellipse အတြက္ Path ဆြဲႏိုင္ေအာင္ GraphicsPath Object တစ္ခုေဆာက္ပါတရ္။ ေနာက္ ၄င္း GraphicsPath ထဲကိုမွ က်ေနာ္တို႔ MouseDown and MouseMove Method တို႔နဲ႔ Crop လုပ္ယူလိုက္ေသာ Ellipse Graphic Path ကို Add ယူပါတရ္။ Graphic ကို Clear လုပ္ၿပီး အျဖဴေရာင္ ကာလာ Assign လုပ္ထားတာကေတာ့ က်ေနာ္တို႔ Crop ယူလိုက္ေသာ Image မွလြဲ၍ က်န္ Image Background ေနရာမ်ားကို အျဖဴေရာင္ ထားေစခ်င္လို႔ပဲ ျဖစ္ပါတရ္။ ေနာက္တစ္ေၾကာင္းမွာေတာ့ SetClip()Method ကိုအသံုးျပဳၿပီး က်ေနာ္တို႔ သတ္မွတ္ေပးၿပီးသားျဖစ္တဲ့ Ellipse Graphic Path ႀကီးတစ္ခုလံုးကို Graphic Object ထဲ Assign လုပ္ေပးၿပီး Graphic ဆြဲယူရန္အသင့္လို႔ ေျပာပါတရ္။ ေနာက္တစ္ေၾကာင္းကေတာ့ DrawImage() Method ကိုသံုးၿပီး အမွန္တကရ္ Crop Graphic ဆြဲယူတဲ့အဆင့္ပါ။ Parameter ငါးခု passing လုပ္ထားပါတရ္။ ပထမ parameter ကေတာ့ Soucre Image သို႔မဟုတ္ Original Image ပါ။ ေနာက္ parameter ႏွစ္ခုကေတာ့ စမွတ္(X,Y coordinate) သတ္မွတ္ေပးတာပါ။ ေနာက္ parameter ကေတာ့ Selected area ပါ။ Rectangle ကိုသံုးထားပါတရ္။ ေနာက္ဆံုး parameter ကေတာ့ Graphics ရဲ႕ Unit ကို သတ္မွတ္ေပးတာပဲ ျဖစ္ပါတရ္။ က်ေနာ္ကေတာ့ Pixel ကိုေရြးေပးထားပါတရ္။ မိတ္ေဆြတို႔အေနနဲ႔ေတာ့ လက္မ၊ မီလီမီတာ၊ point စတဲ့ ႏွစ္သက္ရာ Unit တစ္ခုခုနဲ႔ ေျပာင္းလဲအသံုးျပဳႏိုင္ပါတရ္။ အႏွစ္ခ်ဳပ္ခိုင္းသြားတဲ့ သေဘာကိုေျပာရရင္ Original ထဲက Select လုပ္ထားေသာ Area ကို Pixel Unit ကိုအသံုးျပဳၿပီး cropBmp ထဲသို႔ စမွတ္(0,0 Coordinate) မွ Graphic ဖန္တီးေပးပါလို႔ ခိုင္းလိုက္တာပါ။ ေနာက္ Crop Image ကို White Color ေပးၿပီး Background ကာလာကို Transparent ေျပာင္းယူတာပါ(Background Color နဲ႔ Transparent Color ညီမွ Background Transparent ျဖစ္မွာျဖစ္ပါတရ္)။ .Png Type နဲ႔ Save ရင္ေတာ့ Background Transparent Color ရၿပီး မည္သည့္ object နဲ႔မဆို တြဲဘက္အသံုးျပဳႏိုင္မွာ ျဖစ္ပါတရ္။ အျခား .Jpg တို႔နဲ႔ Save ရင္ေတာ့ Background Color ကို Black နဲ႔ သိမ္းေပးမွာျဖစ္ပါတရ္။ ေနာက္ဆံုးရလာတဲ့ cropBmp သို႔မဟုတ္ Crop Image ကိုေတာ့ Preview အျဖစ္ picResultImg PictureBox ေပၚသို႔ ဆြဲတင္ေပးလိုက္တာပဲ ျဖစ္ပါတရ္ဗ်ာ။ နားလည္ႏိုင္ၾကလိမ့္မရ္လို႔ ေမွ်ာ္လင့္ပါတရ္။
Coding တစ္ေၾကာင္းခ်င္းစီကိုေတာ့ အေသးစိတ္ ရွင္းျပခဲ့ပါတရ္။ ပိုၿပီး နားလည္ေစခ်င္တရ္ ဆိုရင္ေတာ့ Coding အျပည့္အစံုကို ေအာက္မွာ ေလ့လာၾကည့္ႏိုင္ပါတရ္ဗ်။ မိတ္ေဆြ၊ ညီအစ္ကို၊ ေမာင္ႏွမအားလံုး ေလ့လာျခင္းျဖင့္ ေက်နပ္ႏိုင္ၾကပါေစ။

0 Responses so far.

Post a Comment