منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب
المعالجة الصورية (الدرس الثاني) - نسخة قابلة للطباعة

+- منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب (http://vb4arb.com/vb)
+-- قسم : قسم لغة السي شارب C#.NET (http://vb4arb.com/vb/forumdisplay.php?fid=175)
+--- قسم : قسم مقالات C#.NET (http://vb4arb.com/vb/forumdisplay.php?fid=177)
+--- الموضوع : المعالجة الصورية (الدرس الثاني) (/showthread.php?tid=4710)



المعالجة الصورية (الدرس الثاني) - Sajad - 01-10-12

[COLOR="#800080"]بسم الله الرحمن الرحيم
((رب اشرح لي صدري ويسر لي أمري واحلل عقدة من لساني يفقه قولي))
صدق الله العلي العظيم
[/COLOR]


[COLOR="#0000FF"]
السلام عليكم إخواني زوار وأعضاء المنتدى الكرام كما تابعتم معنا الأسبوع الفائت الدرس الأول في المعالجة الصورية وكان حول قراءة صورة ما و وضعها في إلPicture Box وأعطيتكم نبذة مختصرة عن الصور الرقمية ومكوناتها وأنواعها.

أما في هذا الدرس سوف اشرح لكم الCodeالذي استخدمناه في قراءة الصورة وما الطرق الذي اتبعناه للحصول على مكونات الصورة لكي نتعامل معها في الدروس القادمة انشاءالله.
[/COLOR]



[COLOR="#FF0000"]بسم الله الرحمن الرحيم
وصلى الله على محمد واله الطاهرين[/COLOR]


الدرس الثاني:

[COLOR="#0000FF"]أولا: يجب علينا تضمين مجال الأسماء التالي: using System.Drawing.Imaging;
لكي نعطي أنفسنا الصلاحية لتعريف الBitmapData Class وسنأتي إلى شرحه لاحقا.

ثانيا: المتغيرات [/COLOR]

PHP كود :
public int ijstrideremain
        public 
Color[,] c
        public 
Bitmap bmp
        public 
BitmapData bmpdata

[COLOR="#0000FF"]عرفنا المتغيرين i,j وذلك لاستخدامهما كعداد لطول وعرض الصورة(Height, Width)
ثم عرفنا المصفوفة c من نوع Color وذلك لخزن محتويات الصورة فيها(اعني خزن بكسلات الصورة في المصفوفة).
بعد ذلك عرفنا متغير من نوع Bitmap أسميناه bmp وذلك لتحويل الصورة إلى كائن الBitmap.

Bitmap عبارة عن كائن يستخدم للعمل مع الصور المعرفة على أساس البكسلات والتحكم من خلاله بخصائص الصور وأيضا لتسهيل التعامل مع الصور من حيث القراءة والكتابة على أساس أن الصورة تتكون من الPixels وكل pixel تتكون من 3 قيم وهي(الأحمر,الأخضر,الأزرق) وفي بعض الأحيان تضاف اليها الAlpha وهي تمثل الOpacity of image شفافية الصورة وهذه القيم عبارة عن بايتات Bytes.

اما المتغير bmpdata فهو من نوع BitmapData وهذا الكائن يصف لنا موقع وتخطيط بيانات الصورة في الجزء المحجوز من الذاكرة(الجزء الذي حجزنا فيه الصورة من الذاكرة كما سنشرحه لاحقا).[/COLOR]


[COLOR="#FF0000"]وألان نأتي إلى شرح سطور الكود:

اولا:
[/COLOR]


PHP كود :
openFileDialog1.Filter "Bitmap files(*.bmp)|*.bmp|Jpeg files(*.jpg)|*.jpg|Tiff files(*.tif)|*.tif|Png files(*.png)|*.png|All Files(*.jpg;*.bmp;*.tif;*.png)|*.jpg;*.bmp;*.tif;*.png"

هذا السطر من الكود يسمح لنا بان نختار صورة بشرط أن تكون صيغة الصورة ضمن الصيغ المذكورة في السطر البرمجي أعلاه(اعني إما jpg, png , tiff , bmp ).

ثانيا:

PHP كود :
openFileDialog1.FilterIndex 5


[COLOR="#0000FF"]كما ترون في السطر البرمجي أعلاه هناك5 احتمالات إما bmp أو jpg أو tiff أو png أو كل الصيغ مسموح بها في آن واحد لذا جعلنا الFilter Index=5 أي الاختيار أو الشرط التلقائي هو الاحتمال الأخير.
[/COLOR]


ثالثا:


PHP كود :
bmp = (Bitmap)Bitmap.FromFile(openFileDialog1.FileNamefalse); 

[COLOR="#0000FF"]كائن الBitmap يحتوي على دالة اسمها From File وهذه الدالة تحتوي على باراميتر وهي اسم الملف الذي سنختاره من الDialog Box وبما أن الدرس يخص المعالجة الصورية فإننا سنختار ملف صورة ونسنده إلى المتغير bmp.
[/COLOR]


PHP كود :
= new Color[bmp.Widthbmp.Height]; 


هذا السطر اعلاه هو لتحديد حجم المصفوفة الثنائية بطول وعرض الصورة الموجودة في المتغير bmp.
-------------------------------------------------------------------------------------------------------

PHP كود :
bmpdata bmp.LockBits(new Rectangle(00bmp.Widthbmp.Height), ImageLockMode.ReadWritePixelFormat.Format24bppRgb); 


[COLOR="#0000FF"]أما هذا السطر البرمجي اعلاه فهو الأهم فكائن Bitmap يحتوي على دالتين وهما:

LockBits :هذه الدالة تسمح لنا أن نحجز مكانا للصورة في الذاكرة لكي نتعامل معها مباشرة من الذاكرة لان معالجة الصورة من الذاكرة تكون أسرع وأسرع.
هذه الدالة تأخذ 3 باراميترات :

1- الباراميتر الأول لتحديد مساحة الحجز في الذاكرة وهي بالتأكيد نفس مساحة الصورة من حيث الطول والعرض.
2- الباراميتر الثاني لتحديد نمط الحجز أي هل هي للقراءة أم للكتابة أم للقراءة والكتابة معا.
3- الباراميتر الثالث لتحديد صيغة الPixel وبما أن كل لون يأخذ8 بتات وكل بكسل عبارة عن 3 ألوان إذا حجم الPixel الواحد هو 24bit ومعنى هذه العبارة Format24bppRgb هي 24bit per pixel RGB يعني 24بت لكل بكسل من بكسلات الصورة.

UnLockBits :هذه الدالة تعمل على فك الحجز للBitmap(وكما تعرفون الصورة حولناها إلى صيغة الBitmap) من ذاكرة النظام عند انتهائنا من المعالجة.
رموز PHP:
IntPtr scan0 = bmpdata.Scan0;
أما في هذا السطر البرمجي عرفنا متغير من نوع IntPtr وأسندنا إليه عنوان أول Pixel من الصورة المحجوزة في الذاكرة,وكما نعرف إننا نصل إلى العناوين في الذاكرة عن طريق المؤشرات لذا أن IntPtr يمثل المؤشر ونوع الbmpdata.Scan0 من نوع IntPtr.

BitmapData :هذا الكائن يحتوي على عدة خصائص نذكر أهمها:

Scan0 : عبارة عن عنوان أول Pixel من الصورة في ذاكرة النظام.

Stride : عبارة عن عرض الصورة بالبايتات في الذاكرة وأحيانا يزداد عن العرض الحقيقي للصورة المخزونة وهذه الزيادة تسمى بالPadding.

الصورة التالية تمثل تركيبة الصورة المخزونة في الذاكرة:[/COLOR]




[COLOR="#0000FF"]Padding :عبارة عن بيانات إضافية تمثل كيفية تخزين الصورة في الذاكرة وليس لها أي تأثير عند عرض الصورة.

وألان نأتي إلى شرح هذا الكودUnsafe Code:[/COLOR]


PHP كود :
unsafe 
            

                
stride bmpdata.Stride
                
remain stride bmp.Width 3
                
byte= (byte*)(void*)scan0
                for (
0bmp.Heighti++) 
                { 
                    for (
0bmp.Widthj++) 
                    { 
                        
c[ji] = Color.FromArgb(p[2], p[1], p[0]); 
                        
+= 3
                    } 
                    
+= remain
                } 
                
bmp.UnlockBits(bmpdata); 
            } 

[COLOR="#0000FF"]في الدرس الأول سمحنا لأنفسنا باستخدام الUnsafe Code وذلك لكي نتمكن من استخدام المؤشرات(Pointers) في قراءة وكتابة الصورة ولكن لماذا المؤشرات؟ لماذا لم نستخدم دالتي الSet Pixel وGet Pixel؟

الجواب : لان التعامل مع الصور باستخدام هاتين الدالتين تكون بطيئة جدا جدا خاصة مع الصور ذات الأبعاد الكبيرة اقصد من حيث الطول والعرض, أما باستخدامنا للمؤشرات فتكون التعامل مع الصور سريعة جدا اقصد المعالجات التي تتم على الصورة تتم بصورة أسرع.

بالبداية أسندنا قيمة Stride إلى المتغير stride ثم قمنا بحساب الPadding واسندنا قيمة الPadding إلى المتغير remain في حسب هذه المعادلة:
[/COLOR]
PHP كود :
remain stride bmp.Width 3


[COLOR="#0000FF"]stride: شرحناها سابقا.

bmp.Width*3 : يعني عرض الصورة*3, لكن لماذا3؟ لان كل بكسل يحتوي على3قيم وهي قيم كل من (Red ,Green , Blue) وكل قيمة تخزن في موقع بمعزل عن القيمة الأخرى في الذاكرة.

اما هذا السطر:
[/COLOR]

byte* p = (byte*)(void*)scan0;

[COLOR="#0000FF"]أسندنا عنوان أول Pixel للصورة في الذاكرة إلى المؤشر *p من نوع Byte حيث (*) تمثل الPointer.

اما هذا السطر:[/COLOR]

PHP كود :
c[ji] = Color.FromArgb(p[2], p[1], p[0]); 
                        
+= 3

[COLOR="#0000FF"]هو لجلب مكونات كل بكسل من الصورة و وضعها في مصفوفة الألوان عن طريق دالة FromArgb, أما P+=3 فهو لتحريك المؤشر إلى الموقع التالي بثلاث خانات لان كما قلنا إن كل قيمة تخزن في موقع بمعزل عن الأخر.

ملاحظة: إن قيم الصورة تخزن بصورة معكوسة في الذاكرة بشكل BGR وليس RGB.

حيث تمثل:

p[0]=Blue ,p[1]=Green ,p[2]=Red

ومن ثم p+=remain عند الانتقال إلى صف جديد حيث الremain تمثل قيمة الPadding.



الحمد لله والشكر لله انتهينا من الدرس الثاني من سلسلة دروس خاصة في المعالجة الصورية والى أن ألقاكم إنشاء الله في الأسبوع القادم أنا بانتظار استفساراتكم وأسئلتكم حول هذا الدرس ولا تنسوني و والدي من صالح دعائكم.
[/COLOR]