بتـــــاريخ : 2/26/2011 8:40:39 PM
الفــــــــئة
  • الحـــــــــــاسب
  • التعليقات المشاهدات التقييمات
    0 1878 0


    الآلية اللتي يستخدمها الكومبيوتر للرسم على الشاشة من أساسيات برمجة الـ graphics

    الناقل : elmasry | العمر :42 | الكاتب الأصلى : hasan_aljudy | المصدر : www.arabteam2000-forum.com

    كلمات مفتاحية  :

    السلام عليكم و رحمة الله


    لعل هناك سؤالا ملحا يدور في أذهان الكثيرين, ألا و هو كيف يقوم الحاسوب بالرسم على الشاشة؟ أغلب المبتدئين في السي و السي بلص بلص يبدأون عادة مع برامج الكونسول (الشاشة السوداء الشبيهة بالدوز DOS), و بالنسبة لهم فكل ما يستطيعون فعله على الشاشة هو كتابة الحروف, و لكنهم لا يتعاملون مع الشاشة ابدا على اساس انها شي تستطيع ان ترسم عليه ما تشاء!

    لننظر اولا الى الشاشة نفسها, كيف تعمل؟ و كيف تظهر الصور عليها؟
    طبعا لن نشرح تفاصيل عمل الشاشة كجهاز, لأن ما يهمنا هو طريقة عملها من وجهة نظر البرنامج.

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

    طيب, كيف نقوم بوضع هذه الألوان؟ او بمعنى ادق, كيف نقوم بتلوين النقاط pixels؟ و سؤال آخر, كيف نقوم بتغيير الصورة على الشاشة؟ بمعنى اننا نعرف ان الشاشة مكونة من مجموعة نقاط, و لكننا نلاحظ ان صورة الشاشة تتغير باستمرار, فهي ليست صورة جامدة! بل فيها حركة و animation, فكيف نقوم بتغيير هذه الصورة باستمرار؟

    هنا نأتي الى نقطة مهمة, و هي محور الاجابة على هذين السؤالين.
    من أين تأخذ الشاشة الوان الـ pixels؟ كيف تعرف ما هو اللون اللذي يجب ان ياخذه كل بكسل؟
    الجواب و ببساطة, ان هناك مكان معين في الذاكرة يحتوي buffer او مصفوفة طويلة من الارقام, كل رقم يمثل لون معين, و هذه الألوان هي الوان النقاط اللتي تكون الشاشة.

    هنا يوجد سؤالين:
    - كيف يتم استخدام الارقام للتعبير عن الألوان؟
    - كيف يتم تحديد لون نقطة معينة من هذا الـ buffer؟

    أولا:
    - كيف يتم استخدام الارقام للتعبير عن الألوان؟
    المسألة بسيطة .. و هناك عدة طرق لعمل ذلك .. و لكن ابسط طريقة هي استخدام ثلاث أرقام للون: لون يمثل درجة الحمرة (بضم الحاء و سكون الميم), و لون يمثل درجة الخضرة, و لون يمثل درجة الزرقة.
    فكما نعلم, جميع الالوان يمكن تشكيلها عن طريق مزج هذه الألوان الأساسية بدرجات مختلفة, مثلا, اللون الأصفر يمكن الحصول عليه عن طريق مزج الأخضر و الازرق!
    تذكرو اننا هناك نتكلم عن الوان الضوء, و خصائص مزج الالوان هنا مختلفة قليلا عن مزج الألوان على الورق, على كل حال, لا اريد تحويل المسألة الى درس عن الألوان!
    قلنا اننا نستخدم ثلاثة ارقام لتحديد درجات الحمرة و الزرقة و الخضرة.
    مثلا, الرقم اللذي يحدد الحمرة, لو كان 0, فلن يكون هناك اي لون أحمر, اما لو كان 255 فسيكون اقصى درجات الحمرة! و لو كان مثلا 100, فسيكون احمر بدرجة معقولة .. يعني ..و نفس الشي لبقية الألوان!

    فلو اردنا التعبير عن لون معين بهذه الأرقام الثلاثة:
    100, 30, 70
    و لو فرضنا ان اول لون هو مقدار الحمرة, و الثاني هو مقدار الخضرة, و الثالث هو مقدار الزرقة, فإن هذا اللون هو مزيج من حمرة بمقدار 100, مع خضرة بمقدار 30, و زرقة بمقدار 70

    افضل طريقة لفهم العملية هي الذهاب الى فوتوشوب و قم بتحريك المؤشرات على الـ R (احمر) و الـ G (اخضر) و الـ B (ازرق) و انظر كيف يتم مزج الألوان!!
    Posted Image

    لماذا نستخدم الارقام من 0 الى 255 بالذات؟
    لأننا نستخدام byte واحد من اجل تخرين الرقم .. و البايت الواحد لا يستطيع تخزين قيمة اكبر من 255!

    فإذا, لتخزين لون معين على شكل رقم, نحتاج الى 3 بايتات على الأقل! لتخزين الألوان الثلاثة RGB
    على فكرة, RGB تعني red green blue
    و لكننا لا نستخدم 3 بايتات لتخزين الرقم .. بل اربعة! و البايت الرابع عادة يكون مهملا!
    لماذا؟
    لان الاجهزة لا تحب التعامل مع 24 بت, بل مع 32 بت!
    لماذا؟ اشياء معقدة :P ليس لها علاقة بموضوعنا!

    إذا, نستخدم 4 بايتات لتخزين لون واحد, حيث يتكون هذا اللون من 3 بتات لتحديد قيم RGB و البايت الرابع من أجل لا شيء (سد فراغ)!!

    الـ buffer هو عبارة عن سلسلة طويلة من البايتات bytes, كل اربع بايتات على حدة تشكل لونا معينا, لنقل ان اول بايت هو R و ثاني بايت هو G و ثالث بايت هو B, و الرابع هو لسد الفراغ ..
    إذا, لو كان هناك buffer معرف بهذا الشكل (على فرض ان هناك نوع اسمه byte):

    byte buffer[8];

    buffer[0] = 100; //R
    buffer[1] = 200; //G
    buffer[2] = 40; //B
    buffer[3] = 12; // ignore ..
    buffer[4] = 134; //R
    buffer[5] = 12; //G
    buffer[6] = 217; //B
    buffer[7] = 103; // ignore ..


    فهذا الـ buffer يقوم بتخزين سلسلة مكونة من لونين اثنين فقط, الأول RGB=100,200,40 و الثاني هو RGB=134,12,217
    لاحظوا, كل مجموعة اربع بايتات تمثل لون.

    فما هو الـ buffer؟ هو مصفوفة الوان ..لكنها معقدة قليلا, فلو اردت ان تضع في هذه المصفوفة عدد n من الألوان, فيجب ان يكون حجم هذه المصفوفة هو n * 4, و اذا اردت الوصول الى اللون رقم i فعليك الذهاب الى العنصر i * 4 في الـ buffer, و قرائة اول 4 بايتات من هناك ..

    فيمكن تخيل الـ buffer على انه مصفوفة الوان ..

    طيب, أجبنا على السؤال الأول, نأتي الى السؤال الثاني:
    كيف يتم تحديد لون نقطة معينة من هذا الـ buffer؟ و نقصد هنا الـ buffer اللذي يحتوي على الوان الـ pixels في الشاشة.

    طبعا كما نعلم, ذاكرة الكومبيتر هي عبارة عن سلسلة طويلة من البياتات, بينما الشاشة عبارة عن "مربع" طويل من النقاط, او جدول يحتوي على العديد من الخلايا الصغيرة,
    بمعنى آخر, الـ buffer هو في الذاكرة, و هي سلسلة خطية, او مصفوفة احادية الابعاد, بينما الشاشة هي جدول, او بمعنى آخر, مصفوفة ثنائية الأبعاد! فكيف نحدد مثلا لون النقطة (45,69)؟

    لننظر للأمر من هذه الناحية:
    لكي تقوم الشاشة برسم الألوان من الـ buffer, فإنها تمر على الألوان واحدا واحدا, ثم تقوم برسم كل لون على حدة, هذا من ناحية الذاكرة buffer, اما من ناحية الشاشة, فهي تقوم بالمرور على الـ pixels سطرا سطرا, ابتداءا من النقطة العلوية اليسرى, و انتهائا بالنقطة السفلية اليمنى.

    لا ادري كيف اشرح هذا الأمر بالكلمات ..

    للننظر الى الصورة التالية: لو كان الـ buffer يحتوي على 30 لون في داخله, فسيكون شكله هكذا:

    Posted Image

    حيث الارقام تعبر عن ترتيب اللون, يعني اللون رقم 1, اللون رقم 2 .. الخ.

    الان الشاشة عندما تقوم بقرائة هذا الـ buffer, ستحوله الى هذه الصورة:

    Posted Image

    يعني الشاشة تقرأ الالوان من الـ buffer و تقوم برسمه على الشاشة بالترتيب الموضح في الصور.

    طيب, السؤال هو, لو نظرنا الى هذه الصورة (و هي نفس صورة الشاشة, و لكن مع احداثيات النقاط):
    Posted Image



    نلاحظ انه مثلا النقطة 3,1 تحمل لون رقم 3, كيف حصل هذا؟
    او لنقل, نلاحظ ايضا ان النقطة 4,3 تحمل الرقم 16, لماذا؟

    لو لنقل, لو اردنا معرفة ما هو اللون الموجود في النقطة x,y, كيف نستطيع معرفة ذلك؟
    لو قلنا ان اللون الموجود في هذه النقطة هو اللون رقم i, السؤال هو, كيف نعرف قيمة i؟

    الامر يعتمد على معادلة رياضية, فلنحاول ان نستنتجها:
    لو فرضنا ان الشاشة هي مربع, و ان طول المربع هو h و ان عرضه هو w,
    لننظر الى بعض الامثلة أولا:
    إذا كانت
    x,y = 4,1
    فإن i = 4

    طيب, لو اضفنا 1 الى y, سنلاحظ ان
    x,y = 4,2
    و i = 10
    !!
    اضفنا 1 الى y, فاحتجنا لإضافة 6 الى i
    لماذا؟
    لان عرض المربع هو w = 6

    نستطيع ان نقول:
    انه اذا كان y = 1 فإن i = x
    كلما أضفنا 1 الى y, يجب ان نضيف 6 الى i

    إذا,
    i = x + (y-1) * w


    فمثلا, لو اردنا تلوين النطقة 3,4 باللون الاحمر, يجب ان نقوم اولا بحساب رقم اللون:
    i = 3 + (4-1) * 6 = 3 + 3 * 6 = 3 + 18 = 21

    إذا نريد تغيير اللون رقم 21 ليصبح احمر
    تذكروا ان 21 هو فقط رقم (ترتيب) اللون في الـ buffer, فلو كان الـ buffer هو متغير اسمه screenBuffer, فللوصول الى اللون 21 يجب ان نذهب الى الاربع بايتات الموجودة عند الـ index = 21 * 4 (راجعوا ما ذكرته فوق حول تمثيل الـ buffer على شكل مصفوفة بايتات).
    حاصل الضرب هو 84, إذا, لتغيير لون النقطة 4,3 الى أحمر يجب ان نكتب:
    //change pixel at 3,4 to be red
    screenBuffer[84] = 255; //R
    screenBuffer[85] = 0; //G
    screenBuffer[86] = 0; //B
    screenBuffer[87] = 0; //ignore .. we don't really need to change this


    طبعا هذه الطريقة ليست ثابتة دائما, فالأمر يعتمد على عدة أشياء, اهمها هو ابعاد الشاشة (في الحقيقة عرضها)


    حسنا, كما هي العادة, اذا كانت المعلومات الموجودة هنا جديدة عليك, فأرجوا منك مراجعتها الان و البدء في قراءة الموضوع من جديد, و من الصعب ان تفهم كل شيء من أول مرة, سياخذ الامر بعض الوقت (و الممارسة) لكي تستطيع فهمه و هضهمه جيدا.

    زين عيني؟ قبل ان تكمل القراءة, ارجو ان تعود الى البداية و تقرأ المقالة من جديد.

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

    أولا, الـ buffer ليس بالضرورة يمثل الالوان على شكل 4 بايتات, هناك طرق اخرى لتمثيل الالوان, منها مثلا تمثيل الألوان ببايت واحد فقط, و هي هذه الحالة هذا البايت سيحتوي على رقم يحدد اللون, و الطريق المستخدمة لتمثيل اللون على شكل رقم هي انه يوجد في الحقيقة جدول آخر في مكان ما اسمه pallete يحدد ما هو اللون اللذي يمثله كل رقم.
    هذه الطريقة في تمثيل الالوان تسمى indexed color
    يمكن ايضا تمثيل اللون ببايتين فقط (16 بت) و في هذه الحالة يجب توزيع هذه البتات الـ 16 على ثلاثة الوان .. و حسب ما اتصور انهم يستخدمون اول 5 بتات للون الاحمر, ثم الست بتات التالية للون الاخضر, و الخمس بتات الباقية للون الازرق.
    في photoshop إذهب الى image->mode و سترى بعض الطرق المختلفة لتمثيل الالوان.

    المهم انك تفهم الفكرة الاساسية, اذا فهمتها فستستطيع بسرعة ان تتأقلم مع اي طريقة جديدة لتمثيل الالوان تقابلها.

    المسألة الثانية, في الكومبيوتر نبدأ الترقيم من 0 و ليس من 1 .. لذلك فإن معادلة التحويل من x,y الى i ستكون مختلفة قليلا, حيث انها ستكون:
    i = x + y * w

    لاحظ انه لا داعي لطرح 1 من قيمة y

    طيب ...

    نأتي الان الى السؤال التالي اللذي لم نجب عنه:
    كيف نقوم بعمل animation؟
    اول شي يجب ان نفهم ان عملية قراءة الـ buffer و رسمه على الشاشة هي عملية يقوم بها الجهاز (في الحقيقة كرت الشاشة) و هي عملية تتم باستمرار, حوالي 60 مرة في الثانية (هذا الشي يسمى تردد, يعني نقول تردد الشاشة هو 60hz).
    يعني لو حطيت شي في الـ buffer و انتظرت قليلا (برهة من الوقت) ثم وضعت فيه شيئا آخر, فسترى النتيجة على الشاشة بظهور الصورة الاولى, ثم بعد برهة من الزمن ستجد الصورة الثانية.

    لكي نقوم بإظهار حركة (انيميشن) يجب ان نقوم بتغيير الصورة في الـ frame buffer على فواصل زمنية محددة لكي نحصل على تأثير الحركة.
    الموضوع معقد بعض الشيء, لذلك سأتركه لمواضيع لاحقة. المهم الفكرة الأساسية.

    طبعا كما تلاحظون هذا الموضوع ليس عملي, بل هو نظري, و هو ابسط الاساسيات.

    موضوع رسم linear buffer (سلسلة الوان خطية) على rectangular surface (سطح مستطيل) هي الطريقة اللتي تستخدم دائما لرسم شكل معين داخل مربع على الشاشة, و المعادلة المستخدمة للتحويل ما بين x,y الى i هي دائما نفسها (على فرض ان العد يبدأ من الصفر)
    i = x + y * w

    حيث w هو عرض المربع او المستطيل.



    مرة أخرى, اتمنى منك قراءة الموضوع من جديد .. يمكن يساعدك أكثر على الفهم.

    هناك تطبيق عملي لهذه الأفكار في هذا الموضوع:
    http://www.arabteam2...showtopic=80961
    حيث أقوم برسم "خط" مائل بزاوية 45 درجة عن طريق تلوين الـ pixels المناسبة من الـ buffer

    و يمكن لمن لم يفهم الكود في حينها ان يحاول الان الربط بين ما ذكرته في هذه المقالة و بين الكود في ذلك الموضوع.

    اذا يوجد اي اسئلة فأنا حاضر ....

    كلمات مفتاحية  :

    تعليقات الزوار ()