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


    تحميل ملفات bmp يدويا! موضوع للنقاش

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

    كلمات مفتاحية  :
    تحميل ملفات bmp يدويا

    مع وجود العديد من الأدوات الجاهزة و المكتبات اللتي توفر الكثير على المبرمج, قد ينظر البعض بغرابة الي عندما أقول انني اريد تحميل ملف bmp يدويا بدون استخدام اي من تلك الأدوات!

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

    من المفيد دائما للمبرمج ان يطلع على ما يجري خلف الكواليس, فهو أمر يوسع المدارك و يجعل الشخص يشعر بأنه يعرف شيئا مهما!! ههههه, و يستطيع من خلالها ان يتفلسف على الناس :lol:

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

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

    يمكن البحث في جووجل عن bmp file format من أجل الحصول على المزيد من التفاصيل.

    و هذه بعض الوصلات اللتي تتحدث عن تفاصيل محتويات الملف, او صيغة الملف, يمكن الضغط على اي منها و قرائتها, فهي ليست سلسلة, بل كلها تقليد لبعض!
    http://pages.cpsc.ucalgary.ca/~walpole/325...E_INFO/BMP.html
    http://pages.cpsc.ucalgary.ca/~walpole/325...pfileformat.htm
    http://pages.cpsc.ucalgary.ca/~walpole/325...O/bmpffrmt.html

    مع ملاحظة انها كلها من موقع احد اساتذتي :P

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

    نريد الخروج من المناقشة و كلنا قد فهمنا طريقة تخزين و تحميل ملفات الـ bmp, إن شاء الله

    يمكن الملاحظة من خلال الروابط السابقة او من خلال البحث في جووجل, ان ملفات bmp في نظام وندوز مقسمة الى ثلاثة أقسام: اول قسمين هما بمثابة مقدمة عن الملف, و القسم الثالث هو سسلسلة النقاط في الصورة نفسها. مع وجود قسم اختياري و هو الـ palette, فإذا كان كل بكسل في الصورة عبارة عن 8 بت, فسيكون هناك palette, و هي مثل الـ indexed mode في الـ photoshop لمن لا يعرف.

    يرجى ملاحظة ان هذا ليس درس, بل مجرد محاولة لتحريك النقاش .. كيف يكون درس و انا لم اكتب كود تحميل ملفات bmp الا اليوم!!! و لأول مرة!! :lol: مش ناقص غير اني اعطي فيها درس!!

    اعتقد انه يمكننا اعتبار الملف مقسم الى قسمين, المقدمة و الصورة.
    المقدمة بالنسبة لنا هي عبارة عن سلسلة من الـ bytes, نقوم بقرائتها بالتسلسل لكي نحصل على المعلومات المطلوبة عن هذه الصورة!

    أول بايت هو دائما 'B' و ثاني بايت هو دائما 'M', يلي ذلك اربعة بايتات (تمثل int) تعطينا حجم الملف بالبايتات .. يليها سلسلة أخرى من المعلومات, يمكن النظر اليها في الجداول الموجودة في بعض الروابط اللتي وضعتها أعلاه.

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

    طبعا هنالك عدة طريق لقرائة المقدمة الموجودة في ملفات الـ bmp, و هي مسألة مثل كل مسائل البرمجة, لا يوجد لها حل صحيح واحد, بل يوجد لها عدة حلول, و لا احد يخجل ان يضع حله!!

    انا شخصيا حلي قد يكون من أسوأ الحلول .. و لكني لن اضعه هنا قبل ان يقوم شخصان على الأقل بوضع محاولاتهما .. لا أريد ان أكون واقفا هنا مثل الأهبل .. أكلم نفسي!! :rolleyes:

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

    typedef unsigned int uint;
    typedef unsigned char byte;

    typedef struct
    {
        byte red;
        byte green;
        byte blue;
    } PalleteEntry;

    typedef struct
    {
        char * fileName;
        byte * imageData;
        uint fileSizeInBytes;
        uint imageWidth;
        uint imageHeight;
        uint imageDataOffset;
        uint numberOfColours;
        PalleteEntry * palleteTableArray;
    } BmpInfo;

    BmpInfo * loadImage( char * fileName )
    {
        int i = 0;
        int rasterSize;
        int currentPosition;
        byte readBuffer[128];
        int skip; //dummy used to read unused data;
        FILE * file = fopen( fileName, "rb" ); //read binary?
        BmpInfo * bmp = new BmpInfo;
        bmp->fileName = fileName;

        fread( readBuffer, 1, 2, file); //read the first two bytes, should be 'BM'
        if( readBuffer[0] != 'B' && readBuffer[1] != 'M' )
        {
            printf("wrong bmp signature");
            return 0;
        }

        fread( &(bmp->fileSizeInBytes), 4, 1, file ); //read file size in bytes and store it in the bmp structure
        fread( &skip, 4, 1, file ); //skip next 4 bytes (they are unused)
        fread( &(bmp->imageDataOffset), 4, 1, file ); //the next 4 bytes in the file are the 4-byte-integer value for the offset
        fread( &skip, 4, 1, file ); //this should read 40 into skip, indicating the size of the BITMAPINFOHEADER block
        if( skip != 40 )
        {
            printf(" BITMAPINFOHEADER size wrong ");
            return 0;
        }
        fread( &(bmp->imageWidth), 4, 1, file ); //next 4 bytes indicate the width of the bitmap
        fread( &(bmp->imageHeight), 4, 1, file ); //next 4 bytes indicate the height of the bitmap
        skip = 0;
        fread( &skip, 2, 1, file ); //next two  bytes indicate number of planes, should be 1 always
        if( skip != 1 )
        {
            printf(" wrong number of planes " );
            return 0;
        }
        skip = 0;
        fread( &skip, 2, 1, file ); //next two bytes indicate color mode, this code assumes it must be 8
        if( skip != 8 )
        {
            printf("This is not a palettized bmp .... no can do!!");
            return 0;
        }
        fread( &skip, 4, 1, file ); //next 4 bytes are an integer indicating type of compression, for the purpose of this code, it must be 0 for no compression
        if( skip != 0 )
        {
            printf("Can't open compressed bmp");
            return 0;
        }
        fread( &skip, 4, 1, file ); //next 4 bytes indicate size of compressed image, seems unimportant to me!!
                                    // from one of the docs: (compressed) Size of Image. It is valid to set this =0 if Compression = 0
        fread( &skip, 4, 1, file ); // horizontal resolution, i.e. pixels per meter, seems unimportant to me!
        fread( &skip, 4, 1, file ); //vertical resolution, see above line.
        fread( &skip, 4, 1, file ); //next 4 bytes indicate the number of colors used, I don't think that we need this for the palllete, because the pallete size is always 256
        fread( &skip, 4, 1, file ); // number of important colors, I'm thinking this is not important for our purposes    
       
        //create pallete table
        bmp->palleteTableArray = new PalleteEntry[256];
        //read the pallete
        for( i = 0; i < 256; i++ )
        {
            //is it stored as r,g,b or b,g,r? it seems to work only if I read it as b,g,r??!
            fread( &(bmp->palleteTableArray[i].blue), 1, 1, file );        //read B byte
            fread( &(bmp->palleteTableArray[i].green), 1, 1, file );    //read G byte
            fread( &(bmp->palleteTableArray[i].red), 1, 1, file );        //read R byte
            fread( &skip, 1, 1, file );                                    //ignore 4th byte
        }

        currentPosition = fgetc( file );
        //create a buffer for image data
        rasterSize = bmp->imageHeight * bmp->imageWidth;
        bmp->imageData = new byte[rasterSize];
        //read the raster data
        fread( bmp->imageData, rasterSize, 1, file );

        return bmp;
    }




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

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

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


    كلمات مفتاحية  :
    تحميل ملفات bmp يدويا

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