الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مثال على استخدام glDrawPixels مع الشرح

مغلق
بدأه hasan_aljudy في 15 نوفمبر 2005 · 19 رد · 5,942 مشاهدة · في OpenGL
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

في OpenGL, نستطيع استخدام الـ function

glDrawPixels

من اجل رسم سلسلة من الـ pixels على شكل صورة (بمعنى آخر, من اجل رسم الصور).

ياخذ طول و عرض المربع (مربع الصورة), و ياخذ ايضا مكونات هذه الصورة على شكل سلسلة "خطية" متواصلة من الـ pixels او النقاط المكونة للصورة.

شكل الـ function يبدو هكذا:

void glDrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels
);

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

هناك عدة طرق لتمثيل pixel, احداها مثلا عن طريق اعطاء بايت واحد byte لكل pixel, و في هذه الحالة فإن قيمة هذا البايت تحدد index في الـ pallete يستخدم لتحديد لون هذا الـ pixel. و هذا يسمى indexed color

يمكن ايضا اعطاء byte واحد لكل مكون من مكونات اللون RGB او Red, Green, Blue, و قيمة كل بايت من 0 الى 255 تحدد مقدار هذا العنصر في اللون, مثلا 0,0,0 أسود, حيث لا يوجد اي لون.

255,0,0 يعني اقصى درجات الحمرة.

و هكذا. و هذا يسمى RGB, و على هذه الفرضية فإن كل لون يحتوي على 3 bytes او 24 bits, و لكن في الحقيقة معظم بطاقات العرض لا تحب التعامل مع 24 بت و تفضل التعامل مع 32 بت .. فهنالك byte إضافي, احيانا يستخدم من اجل لا شيء سوى سد الفراغ, و احيانا يستخدم من اجل تحديد شفافية اللون, او alpha. و بهذه الحالة يسمى RGBA حيث نستخدم 4 بايتات لكل بكسل, و بهذا الترتيب (كما هو واضح من الاسم).

      R         G            B             A
|--------|--------|--------|--------|

البارامتر format يستخدام لتحديد هذه الأشياء, و هو enum ياخذ عدة احتمالات, موجودة في صفحة الـ msdn في الرابط اعلى الموضوع.

سنستخدم GL_RGBA في هذه المثال.

السؤال الان هو كيف نمثل هذه البايتات في الـ array؟ هل نستخدم int لكل بكسل (و الـ int ياخذ 4 بايتات)؟ ام نستخدم 4 متغيرات من نوع byte لكل بكسل؟

اذا استخدمنا الـ int فسيكون علينا ان ننتبه فيما اذا كان النظام اللذي نعمل عليه هو big-endian او little-endian لان ترتيب البايتات سيختلف حسب النظام. لذلك من الأفضل استخدام سلسلة من الـ bytes.

لذلك سنختار للبارامتر الرابع, و هو type و هو ايضا enum, نختار منه GL_UNSIGNED_BYTE.

لماذا unsigned؟ اترك الاجابة لكم :P

بقيت مسألة واحدة و هي تحديد مكان الصورة!

لمن لا يعرف, opengl يعتبر بمثابة state machine, يعني انت تضعها في حالة معينة ثم ترسل لها اوامر, و استجابتها للاوامر تعتمد على الحالة اللتي وضعتها فيها.

لتحديد مكان الصورة, تقوم باستدعاء glRasterPos2d و تحدد الاحداثيات x,y اللتي تريد رسم الصورة فيها, و بعد ذلك تقوم باستدعاء glDrawPixels

المثال يستخدم glut, و من لا يعرفه يمكن مراجعة درس CompuM4n

/index.php?showtopic=41970

#include<GL/glut.h> 

GLubyte * getPicture( int w, int h )
{
    int length = w * h * 4;
    GLubyte * bytes = new GLubyte[length];
    for( int i = 0; i < length; i++ )
    {
        bytes = 0;
    }
    int m = min(w,h);

    //draw a line!
    for( int i = 0; i < m; i++ )
    {
        int p = i*4;
        p = p+p*w;
        int pe = p + 4;
        while( p <= pe )
        {
            bytes[p] = 200;
            p++;
        }        
    }

    return bytes;
}

void putMyImage( int x, int y, int w, int h )
{
    glRasterPos2d( x, y );
    glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, getPicture( w, h ) );
}

void myInit()
{
    glClearColor(0.3,0.3,0.3,0.0);
    glColor3f(1.0,1.0,0.5);
    glPointSize(2.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0,640.0,0.0,480.0);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glEnd();
    putMyImage( 100, 100, 20, 20 );
    glFlush();
    
}

int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB);
    glutInitWindowSize(400,400);
    glutInitWindowPosition(50,50);
    glutCreateWindow("Draw Polygon");
    myInit();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

هذا مثال glut تقليدي, و الكود اصلا لسست انا من كتبه, بل اخذته من مصدر من الانترنت و احتفظت بها, و بصراحة لم اعد اذكر ما هو المصدر!!!

الشي اللي اضفته هنا هو putMyImage حيث يتم استدعائه في display

void putMyImage( int x, int y, int w, int h )
{
       glRasterPos2d( x, y );
       glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, getPicture( w, h ) );
}

البارامترات في glDrawPixels هي كما وضحت في السابق, و آخر بارامتر هو استدعاء لـ getPicture و هي تعطينا مصفوفة من الـ unsigned byte تمثل بكسلات الصورة.

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

تفاصيل كيف كونت الصورة نفسها غير مهمة, و هي ليست لب الموضوع, بالامكان تكوين صورة بأي طريقة, و لكن المهم هو اننا عندنا array of pixels و قمنا برسمه على الشاشة,

اعرف ان الشرح ناقص, و قد فعلت هذا عمدا, حيث كتبت الموضوع على عجالة و من دون تحضير.

لماذا؟

حتى اللي عنده سؤال يسأل!

لعل و عسى بهذه الطريقة نحصل على بعض التفاعل!!!

لو كان هناك اي شيء في الشرح لم تفهمه, اسأل ولا تتردد, و لا تقلي الشرح واضح! لانه لا يبدو واضحا بالنسبة لي!

تم تعديل هذه المشاركة بواسطة hasan_aljudy في 15 نوفمبر 2005 في 06:26

#2

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

السؤال .. لماذا استخدمها ,, الصور الجاهزة اعتقد خففت الحمل عنا ..

هل تعرف فيما تستخدم الان ؟

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#3

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

ما هي الطريقة الأفضل لرسم الصور؟

على كل حال, انا اتصور انك لما تحمل الصورة من ملف فإنك ستقوم بتخزين الـ pixels بإحدى الهيئات الموجودة ضمن format على شكل array, و بعد ذلك تقوم باستدعاء glDrawPixel لرسم الصورة!

تم تعديل هذه المشاركة بواسطة hasan_aljudy في 15 نوفمبر 2005 في 06:25

#4

السلام عليكم

أعتقد أن مثل هذه الدالة مفيدة في عمل graphics demo و التي تضم مؤثرات على الألوان مثل plasma, fade ...

أي أنك على سبيل المثال تأخذ buffer و الذي تحصل عليه مثلا بإستخدام getpicture بعد ذلك يمكنك عمل أي شيئ فيه

كأن تجعل مثلا كل pixel يساوي x * x + y * y + tick أو أي معادلة أخرى ثم ترسل buffer إلى الشاشة.

لكن لدي سؤال حول الإحداثيات، ماهو مرجع الإحداثيات في الشاشة و ماذا يحدث لو كانت خارج إطار الشاشة ؟

#5

باعتقادي ان نظام الاحداثيات في OpenGL يتم اعداده في

gluOrtho2D(0.0,640.0,0.0,480.0);

لست متأكدا بالضبط,

بالنسبة لنقطة الصفر و هذه الأشياء, فإن الاتجاه الموجب للـ x هو الى اليمين, و الاتجاه الموجب للـ y هو الى الأعلى, اما موقع النقطة 0,0 فإعتقد انه ايضا يتم تحديده من خلال

gluOrtho2D

http://msdn.microsoft.com/library/default....ufnc01_5alg.asp

لكن السؤال هو, اذا غيرتنا القيم المرسلة الى هذا الـ function, فهل سيتغير شكل الصورة (الخط) او حجمها؟

ما لاحظته هو ان تغيير البارامترات المرسلة الى gluOrtho2D لا يغير حجم الصورة, بل يغير مكانها فقط!

فالظاهر ان drawPixels يرسم النقط على شكل pixels حقيقية, بغض النظر عن الـ projection matrix هذا اللذي حددنها في gluOrtho2D؟!

هل هناك من يعرف الحكاية بالضبط؟

#6

بارك الله فيك و نأمل المزيد من هذه الدروس النادره و الرائعه أيضا

كتبت و قد أيقنت يوم كتابتي أن يدي تفنى و يبقى كتابها

فان كتبت خيرا ستجزى بمثله و ان كتبت شرا عليها حسابها

#7

الم يتسائل أحد كيف يعمل getPicture؟

و كيف يرسم خط ابيض في مربع اسود؟

ولا الكل فاهمين كل شي!!! :rolleyes:

GLubyte * getPicture( int w, int h )
{
   int length = w * h * 4;
   GLubyte * bytes = new GLubyte[length];
   for( int i = 0; i < length; i++ )
   {
       bytes = 0;
   }
   int m = min(w,h);

   //draw a line!
   for( int i = 0; i < m; i++ )
   {
       int p = i*4;
       p = p+p*w;
       int pe = p + 4;
       while( p <= pe )
       {
           bytes[p] = 200;
           p++;
       }        
   }

   return bytes;
}
#8

الم يتسائل أحد كيف يعمل getPicture؟

و كيف يرسم خط ابيض في مربع اسود؟

glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, getPicture( w, h ) );

حيث البيانات ..توجد في .. GLubyte * getPicture ..

لكن مانوع هذه البيانات وكيف اتحكم بشكلها .....ما ادري .. ممكن اعرف : ) ,,

انا عندي نقطة ثانية .. شبيهة بمثالك .. وهو التحكم بشكل الخط المرسوم .. متقطع ..نقاط ..

تعقدت منها ,,, سأضع السؤال في وقت لاحق .. ان شاء الله

[ gluOrtho2D(0.0,640.0,0.0,480.0);

الافضل كذا

حتى تكون مشابهة لطريقة الويندوز ...

gluOrtho2D(0.0,640.0,480.0,0.0);

البارمتر الاول النقطة اليسرى من الشاشة ...

الثاني .. قيمة اخر نقطة من الشاشة في الجهة اليمنى

الثالث .. قيمة اعلى نقطة .

الرابع قيمة اسفل نقطة من الشاشة

وانت تقدر تختار اي شيء ..

بالتالي هنا نقطة الصفر هي الجهة العلوية اليمنى ..

فيه دالة glOrtho ... هي اوسع .

لكن في الغالب نستخدمها مع التو دي ... مثل رسم النصوص ....

لكن كيف استخدم

glOrtho

مع الثري دي ..

؟؟

بالرغم من انه بامكاني تحديد مدى العمق ... الا انه لاتظهر المجسمات الثلاثية ...

سأجرب واتاكد

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#9

البيانات الموجودة في المصفوفة التي ترجعها getpicture تتغير حسب ال format الذي تستخدمه فمثلا عند استخدامك لـ RGBA فإن كل pixel في الشاشة يأخد 4 بيتات في المصفوفة يعني أول 4 بيتات تمثل ال pixel الأول للصورة وهكذا، لو الصورة طولها 100 pixel و عرضها 100 pixel فإن حجم المصفوفة سيكون 100 * 100 * 4 بايت

بالنسبة للأشكل عليك التفكير بطريقة ثنائية البعد يعني تغير الألوان على السطح لتحصل على الشكل الذي تريد و ذلك ما يحدث في ال getpicture حيث يتم رسم المستقيم عن طريق

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

#10

البيانات اللتي اقصدها هي الـ pixels اللتي سيقوم الـ function برسمها.

اقتباس
لكن مانوع هذه البيانات وكيف اتحكم بشكلها .....ما ادري .. ممكن اعرف : ) ,,

نوع هذه البيانات تحدده انت, هل تريدها ان تكون RGBA ام Indexed color ام ماذا؟ يجب ان تخبر glDrawPixels باختيارك عن طريق البارامتر format, و ايضا عن طريق البارامتر type.

ib_doom, كلام سليم. icon1.gif

اقتباس
البيانات الموجودة في المصفوفة التي ترجعها getpicture تتغير حسب ال format الذي تستخدمه فمثلا عند استخدامك لـ RGBA فإن كل pixel في الشاشة يأخد 4 بيتات في المصفوفة يعني أول 4 بيتات تمثل ال pixel الأول للصورة وهكذا، لو الصورة طولها 100 pixel و عرضها 100 pixel فإن حجم المصفوفة سيكون 100 * 100 * 4 بايت

رائع! :D

طبعا للوصول الى اي بكسل, مثلا البكسل رقم 54, فعلينا ان نضرب 54 في 4 لكي نحصل على البايت اللذي يمثل بداية هذا البكسل, بما ان البكسل نفسه هو 4 بايتات, فلتلوين هذا البكسل بلون معين يجب ان نعطي القيم المطلوبة للبايتات

54 * 4 + 0

54 * 4 + 1

54 * 4 + 2

54 * 4 + 3

اقتباس
بالنسبة للأشكل عليك التفكير بطريقة ثنائية البعد يعني تغير الألوان على السطح لتحصل على الشكل الذي تريد و ذلك ما يحدث في ال getpicture حيث يتم رسم المستقيم عن طريق

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

صحيح, و ما اقوم به هو ببساطة هو المرور على كل النقاط (i,i) يعني من 0,0 الى m,m و تلوين كل نقطة.

  for( int i = 0; i < m; i++ )
  {
        // color (i, i) with white!!        
  }

السؤال هو, كيف يقوم الكود:

      int p = i*4;
      p = p+p*w;
      int pe = p + 4;
      while( p <= pe )
      {
          bytes[p] = 200;
          p++;
      }

بتلوين النطقة i, i باللون الأبيض؟

في الحقيقة هو ليس اللون الأبيض تمام, هو 200,200,200 و الـ alpha ايضا 200

#11

بالنسبة لرسم خط منقط, يمكن تغيير الـ loop اللتي ترسم الخط ببساطة شديد

بدل ++i نخليها i += 2

GLubyte * getPicture( int w, int h )
{
   int length = w * h * 4;
   GLubyte * bytes = new GLubyte[length];
   for( int i = 0; i < length; i++ )
   {
       bytes = 0;
   }
   int m = min(w,h);

   //draw a line!
   for( int i = 0; i < m; i+=2 )
   {
       int p = i*4;
       p = p+p*w;
       int pe = p + 4;
       while( p <= pe )
       {
           bytes[p] = 200;
           p++;
       }        
   }

   return bytes;
}

و إذا اردنا التقطيع ان يكون اكبر قليلا, يمكن اضافة سطر بسيط لاهمال نقطة بعد كل 5 نقاط مثلا

   //draw a line!
   for( int i = 0; i < m; i++ )
   {
       if( !((i+1) % 5) ) continue;       
       int p = i*4;
       p = p+p*w;
       int pe = p + 4;
       while( p <= pe )
       {
           bytes[p] = 200;
           p++;
       }        
   }
#12

انا لم اقصد ذلك ..

اقصد

http://www.rush3d.com/reference/opengl-red.../chapter02.html

ستجد عنوان فرعي واضح في الصفحة

Displaying Points, Lines, and Polygons

اقرأ اللي تحته

اقتباس
Stippled Lines

To make stippled (dotted or dashed) lines, you use the command glLineStipple() to define the stipple pattern, and then you enable line stippling with glEnable():

glLineStipple(1, 0x3F07);

glEnable(GL_LINE_STIPPLE);

void glLineStipple(GLint factor, GLushort pattern);

Sets the current stippling pattern for lines. The pattern argument is a 16-bit series of 0s and 1s, and it's repeated as necessary to stipple a given line. A 1 indicates that drawing occurs, and 0 that it does not, on a pixel-by-pixel basis, beginning with the low-order bits of the pattern. The pattern can be

.

.

.

.

ثم

glEnable (GL_LINE_STIPPLE);
    glLineStipple (1, 0x0101);   /*  dotted   */
    drawOneLine (50.0, 125.0, 150.0, 125.0);
    glLineStipple (1, 0x00FF);   /*  dashed   */
    drawOneLine (150.0, 125.0, 250.0, 125.0);
    glLineStipple (1, 0x1C47);   /*  dash/dot/dash   */
    drawOneLine (250.0, 125.0, 350.0, 125.0);

لماذا احيانا مقطع واحيانا منقط ....

لماذا اضع قيم عشرية ...

glLineStipple (1, 0x00FF);   /*  dashed   */

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

يمكن خارج الموضوع ... لكن اللي عنده معلومات .. يفيدنا :) ,,,

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#13

The pattern argument is a 16-bit series of 0s and 1s

لكي تعرف شكل الـ pattern, لازم تعرف شكل الرقم بالـ binary

0x00FF شكلها هو:

0000000011111111

كررها عدة مرات .. تخيل ان الـ 0 هو بسكل غير ملون, و الـ 1 هو بكسل ملون .... يطلعلك شكل مخطط!

00000000111111110000000011111111000000001111111100000000111111110000000011111111

0x1C47 شكلها هو (او بالأحرى, قيمتها بالاعداد الثانئية):

0001110001000111

نفس الشي, الـ 1 هو بكسل ملون و الـ 0 هو بكسل غير ملون. كرر هذا الشكل عدة مرات, ستجد انه عبارة عن نقاط و خطوط متتابعة

0001110001000111000111000100011100011100010001110001110001000111

0x0101 هو:

0000000100000001

و نفس الفكرة!

0000000100000001000000010000000100000001000000010000000100000001

#14

كل هذا كلام جميل بل أكثر من رائع ولكن لندخل فى الموضوع بشكل أعمق

هل بمكننا تحديد الطريقه التى يتم العمل بها لل glDrawPixels ليس للخط أو للمستطيل او النقطه

ولكن للكلمه

أعنى ان كنا سنقوم بكتابه أحرف لكلمه فى مثلا DBGrid أو Text ونريد تحوبل هذه الكلمه الى صوره

فكيف ينم ذلك

#15
اقتباس
هل بمكننا تحديد الطريقه التى يتم العمل بها لل glDrawPixels ليس للخط أو للمستطيل او النقطه

ولكن للكلمه

أعنى ان كنا سنقوم بكتابه أحرف لكلمه فى مثلا DBGrid أو Text ونريد تحوبل هذه الكلمه الى صوره

فكيف ينم ذلك

أسعدني سؤالك icon1.gif

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

أول مشكلة هي أين نطبع الكلمة؟

يمكننا الان اعتبار ان الـ function اللذي سيطبع الكلمة, يقوم ايضا باستقبال الاحداثيات x,y اللتي نريد استخدامها كنقطة البداية للكلمة. سنفترض ايضا ان الكلمة هي بالانجليزي (تتجه من اليسار الى اليمين), و أن محور الـ x يزداد كلما اتجهنا الى اليمين, و المحور العمودي y-axis يزداد كلمة اتجهنا الى أسفل. يعني نقطة الصفر هي النقطة العلوية اليسرى في الشاشة.

فنرض ان تعريف الـ function هو هكذا:

void printMsg( char* str, int x, int y )

نحتاج الى pixel array لكل حرف لتحديد شكله, يعني مجموعة pixels معدة مسبقا على شكل الحرف. لنفترض ان هذه الـ pixel array مجهزة مسبقا, و أنه يمكن الحصول عليها و على طولها و عرضها عن طريق استدعاء شيء مثل:

getPixels( 'A', &pixelArray, &width, &height );

حيث pixelArray هو عنوان سلسلة النقاط اللتي تمثل شكل الحرف, و الـ widht و الـ height هما ابعاد هذه الصورة, حيث ستقوم هذه الدالة بإعطاء هذه المعلومات لنا.

تذكروا انني اقوم بافتراض وجود هذه الدالة, و يمكننا ان نكبتها فيما بعد لو أردتم!

لكي نرسم الحروف في الـ string, نقوم بعمل loop بسيطة على كل الحروف, و كتباتها:

void printMsg( int tSeg, int vSeg, char* str, int x, int y )
{
    int w, h;
    GLubyte * pixels;
    while( *str != 0 )
    {
        getPixels( *str, &pixels, &w, &h );
        drawPixels( x, y, w, h, pixels );
        str++; 
        x += w; //advance x (aka cursor)

    }
}

حيث نقوم بالمرور على كل حروف الـ string حتى نصل الى الـ '0\' او الـ null-terminator و نقوم بطباعة الحرف في (x,y) ثم نقوم بتحريك x حسب عرض الحرف, ينضعه في المكان المناسب للحرف التالي.

لاحظا ان drawPixels هو ايضا دالة وهمية افترض وجودها, و يمكن كتابتها ببساطة في سطرين:

void drawPixels( int x, int y, int w, int h, GLubyte * pixels )
{
   glRasterPos2d( x, y );
   glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
}

المهم, هناك مشكلة في طريقتنا, و هي انه اذا كان الـ string كبيرا لدرجة انه اكبر من عرض الشاشة, يجب علينا في هذه الحالة كتابته على عدة أسطر, و في تلك الحالة, يجب ان نقوم بفحص قيمة x و إذا كانت اكبر من عرض الشاشة, نقوم بإعادتها الى الصفر و إضافة طول الحروف الى y

void printMsg( int tSeg, int vSeg, char* str, int x, int y )
{
    int w, h;
    GLubyte * pixels;
    while( *str != 0 )
    {
        getPixels( *str, &pixels, &w, &h );
        drawPixels( x, y, w, h, pixels );
        str++; 
        x += w; //advance x (aka cursor)

        if( x > getScreenWidth() )
        {
            x = 0;
            y += h;
        }

    }
}

هنا نفترض طبعا ان جميع الحروف لها نفس الطول ...

هذه طريقة بدائية نوعا ما, و فيها عدة مشاكل. إحداها مثلا اننا لا نستطيع تحديد لون الخلفية و لا لون الحرف نفسه, يعني الـ foreground و الـ background.

هناك limitations (لا اعرف كيف اترجمها :/) أخرى في هذه الطريقة, نناقشها إذا أردتم.

بالمناسبة, حل مشكلة التلوين (او احد حلولها المحتملة), يشبه جدا حتة الـ bit patterns في نتقيط و تقطيع الخطوط! اللتي سأل عنها الشمري, و تحديدا هي باستخدام bitmap (بتات) لتمثيل شكل الحرف, يعني حرف A مثلا يصبح:

00000000
00011000
00111100
01100110
01100110
11111111
11000011
11000011

و في هذا المثال هي bitmap 8 x 8 و هي في الحقيقة سلسلة من 8 بايتات, شكلها الخطي هو:

00000000
00011000
00111100
01100110
01100110
11111111
11000011
11000011

او بالـ hexidecimal

00183C6666FFC3C3

هل احد عنده فكرة عن كيفية قرائتها و تحويلها الى سلسلة pixels على شكل مربع طوله و عرضه هو 8 * 8 و أعطاء لون محدد للحرف و لون آخر للخلفية؟

قد يبدو الأمر معقدا, لكنه ليس بتلك الصعوبة أبدا!!

هل من شخص يحاول؟

كذلك, هل تريدون ان نقوم بكتابة الدالة اللتي تعطينا الـ pixel array للحرف, مع طوله و عرضه؟

تم تعديل هذه المشاركة بواسطة hasan_aljudy في 18 نوفمبر 2005 في 18:17

#16

هذه محاولة بإفتراض أن طول و عرض كل حرف 8 * 8 و pattern مصفوفة تضم كل أشكال الحروف

void getpixels(char c, GLubyte *p, int *w, int *h, int fc, int bc)
{
	char *ch = pattern[c - 'a'];


	*w = 64;
	*h = 64;

	p = new GLubyte[8 * 8 * 4]

	int *buffer = (int *)p;

	for (int j = 0; j < 8; j++) {
  int off = j * 8;
  for (int i = 0; i < 8; i++) {
 	 if (ch[off + i])
    buffer[off + i] = fc;
 	 buffer[off + i] = bc;
  }
	}
}

لم أجرب الكود لذلك يمكن أن يحتوى الكثير من الأخطاء.

#17

تذكروا انني اقوم بافتراض وجود هذه الدالة, و يمكننا ان نكبتها فيما بعد لو أردتم!

لكي نرسم الحروف في الـ string, نقوم بعمل loop بسيطة على كل الحروف, و كتباتها:

هناك limitations (لا اعرف كيف اترجمها :/) أخرى في هذه الطريقة, نناقشها إذا أردتم.

كذلك, هل تريدون ان نقوم بكتابة الدالة اللتي تعطينا الـ pixel array للحرف, مع طوله و عرضه؟

#18
اقتباس
أخى العزيز

بالطبع نريد مناقشه limitations وأيضا كتابه الداله pixel array

ولى عده أستفسارات أخرى ستجىء فى وقتها

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

ib_doom, محاولة جيدة, و لكن تذكر ان الـ pattern هو bitmap و ليس bytpemap

اعتذر عن المشاركة القصيرة .. حيث انني عدت قبل قليل من دوام طويييييل و ليس لدي دافع كبير للكتابة!

#19

اخى hasan_aljudy

اسف على وضعى للمشاركه فى هذا الموضوع لكنى وددت ان اوجهها لك وللاخوه المتناقشين فيها لارتباطها بنفس الموضوع

فكره البرنامج

=============

جميعنا بعلم اللوحات الالكترونيه المضيئه التى تستخدم فى الاعلانات

والتى تستخدم فى الملاعب الرياضيه لعرض النتائج ومقاطع الحركه

وهذه اللوحات تعمل ببرنامج معد خصيصا لها على الدوس

================

وفكره برنامجنا هذا هو أعداد النص أو الكلمه وأعطائها مؤثرات الحجم

واللون والمساحه التى تتماشى مع حجم اللوحه وأعطاءها التأثير الحركى

مثل طريقه دخول وخروج النص وطرق الانيميشن الخاصه بالتأثير على الخطوط

ثم حفظ العمل فى ملف خارج البرنامج بأمتداد seq

وبهذا يكون النص جاهز لنقله على الكمبيوتر المتصل بلوحه العرض

===========================

أرجو أن تكون الفكره أتضحت

وهذه مكونات البرنامج الملحق

DBGrid لكتابه النص المراد

Combo5 لاختيار الحركه المراده للنص

Combo6 لاختيار نمط الحركه

cboFont لاختيار نوع الخط

cboWeight لاختيار نمط الخط

Combo2 لاختيار لون الخط

Combo4 لاختيار حجم الخط

txtWidth & txtHeight وهم لتحديد حجم العمل ليتناسب مع حجم شاشه العرض

Text7 وهو لتحديد فتره ثبات النص على اللوحه قبل أن يتحرك مره أخرى

Text9 وهو لتجديد سرعه النص على اللوحه

cmdpicture وهو لحفط العمل على هيئه صوره وسحبه على برنامج الرسام اذا أردنا التعديل عليه خارج البرنامج

cmdSave وهو لحفظ العمل بعد الانتهاء منه بصيغه (seq)

==================

وهذا هورابط المشروع

http://www.twa9ef.com/uploads/5f80a1f5ac.zip

وهذا ملف (seq) المفترض ان ينتحه البرنامج محتويات الملف عند فتحه بالوورد مثلا بهذا الشكل الموجود فى هذا الرابط

http://www.twa9ef.com/uploads/e4dbedd8d9.zip

#20

آسف لعدم دخول الموضوع في اليومين الماضيين ...

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

عموما بالنسبة لهذا الموضوع, فلدي عدة نقاط كنت اود المشاركة بها, و لكن ليس الان على كل حال, ما عندي واهس :P

- الـ garbage collection

كما تلاحظون اننا نستخدم new بكثرة, و اذا لم نقم بعمل delete في مرحلة ما, فإن الذاكرة ستخلص!!

- تحويل من bitmap الى RGBA, و هنا لا اقصد ملفات bmp, بل اقصد انماط الآحاد و الأصفار bit pattern

- اختيار بكسل معين و تحديد لونه.

- اختيار البكسل الخاص بنقطة معينة, يعني مثلا بكسل النقطة 132,48 على سبيل المثال!!

هذا الموضوع مغلق.

مواضيع مشابهة