020-29133788
    资 讯
    您的位置:首页 >> 资 讯 >> 软件应用 >> 编程开发 >> 正文
    C++读取BMP图档心得

    点击:   发布日期:2013-01-20

    本文来自 www.020fix.com

    要读取档案,就我从不会到会的经验来看,有两个重点

    1.用fstream读取档案的方式。

    2.了解要读取的档案的格式,这点比较重要。
    复制内容到剪贴板
    代码:
    #include <fstream>
    //开档
    char Name[]=“01.bmp”; //档名。注意:这边的NAME就是下一行的NAME,也就是要读进去的档案名称,这名称有包括副档名。
    file.open(Name,参数);

    //读档
    file.read(变数,长度);//变数:将读进去的资料以"变数"这么名称储存。长度:要读多少长度进去。

    例如:
    file.read(line1,3);//这行的意思就是,读进三个位元组的长度,将这三个位元组储存在名称为line1的阵列里面。当然了,前面要先宣告一个名称为line1的阵列才行阿。(char line1[32];)

    //写档
    file2.write(变数,长度);
    例如:file.write(line1,3);//将阵列line1里面的内容前面三个写出到档案里面,详细请见下面那一个完整的code。
    这就是基本的fstream读档方式

    因为在写code时,你必须要知道这个档案的哪几个资料代表什么,所以一定要先找出这个档的组成结构。

    之前有人回覆给我这个网址http://blog.pixnet.net/crazycat1130/post/1345538
    内容不错,必看!

    除此网站之外,我们助教给我们的PDF也很详细,也必看!
    http://myweb.ncku.edu.tw/~f7495223/BMP_PDF.rar


    附上一些fstream的开档基本用法
    复制内容到剪贴板
    代码:
    开启档案时需使用open()这个函式。其格式如下。
    file.open(Name,nMode);
       ios::app:档案开启后,档案指位器直接跳到末端位置,输入的资料将接在档案后面。。
    &#1048708;ios::in:以输入的方式处理档案,这是ifstream的内定值。
    &#1048708;ios::out:以输出的方式处理档案,这是ofstream的内定值。
    &#1048708;ios::trunc:如果档案已经存在,则内容将被清除。
    &#1048708;ios::nocreate:如果档案不存在,则会有错误讯息。
    &#1048708;ios::noreplace:如果档案已经存在,则会有错误讯息。
    &#1048708;ios::binary:以二进位的形式来处理档案。

    所以整行可以写成这样
    file.open(Name,ios::in||ios::binary);
    听同学说处理非纯文字的档案都要加上ios::binary

    上面的code"简化"自助教给的PDF,因为那PDF里面我看不懂的地方没有PO上来。


    在了解档案结构之后,建议使用Ultra edit比对之前看到的教学,你会更清楚那是什么意思!

    Ultra edit下载:http://toget.pchome.com.tw/intro/business_wordprocessing/286.html


    我觉得最重要的观念是,「PDF中所写的图片资讯,在Ultra edit中,就是按照PDF中介绍的顺序一路排列下来的。」(只有我觉得重要吧,同学都很直接这样想.....)

    意思就是,Ultra edit看到的一堆码,前两组就是代表档案形式,接下来四组代表档案大小,再来两组是保留区‧‧‧以此类堆。

    知道那些码代表什么之后,你还要会解读!

    例如:Ultra edit中显示BMP图档最开头两组是42 4D,在ASCII(阿斯KEY)中,42=B,4D=M。

    再来后两组是大小的资讯,以一张17462位元组的BMP图档为例,第三跟第四组资讯为,36 44。

    然后我们开启小算盘,将它改为工程用的模式(检视→工程型),在16进位下输入3644,在转换到10进位看,却发现他不是17462。

    可是当我们将16进位中的数字改为4436,再将它转换到10进位,没错!它变成17462了。为什么要从后面开始读,这我也不知道,反正事实上就是这样子,而这对我们写code不会有什么影响,只是写出来让大家轻鬆一下而已。

    注:有时会有有一种很诡异的情况:「图片大小跟储存的资讯不一样」。

    例如原本我从助教那边拿到的作业图片是一张128*128的图片,整张图片加上一些档头资讯后,这张图片按照36 44的计算,大小应该是17462位元组,但事实上。刚从助教那边拿过来时他的大小是17464位元组(右键内容看到的),莫名奇妙多出两个位元组。

    原因不明,但是在将图片用小画家开启,随便做个动作然后复原它,然后另存新档,档案大小就变成了17462了(右键内容看到的)。
    当它的大小是17464时,用Ultra edit看里面的大小资讯,依然是36 44。


    上面就够让一个新手头痛啦!

    再来就是整个code怎么做了。
    复制内容到剪贴板
    代码:
    #include <iostream>
    using std::cout;
    using std::cin;
    using std::endl;

    #include <fstream>
    using std::fstream;
    using std::ios;

    typedef unsigned char   BYTE;
    typedef unsigned short  WORD;
    typedef unsigned long   DWORD;
    typedef long            LONG;

    void main(){
        fstream file;
            int i,j;
        char fileName[32], RGBQUAD[4][256], PIXEL[128][128],temp[128][128];
       

        WORD bfType;
        DWORD bfSize;
        WORD bfReserved1;
        WORD bfReserved2;
        DWORD bfOffBits;
        DWORD biSize;
        LONG biWidth;
        LONG biHeight;
        WORD biPlanes;
        WORD biBitCount;
        DWORD biCompression;
        DWORD biSizeImage;
        LONG biXPelsPerMeter;
        LONG biYPelsPerMeter;
        DWORD biClrUsed;
        DWORD biClrImportant;

        //将资料从档案输入到记忆体
            cout << "Open FileName: ";
        cin >> fileName;

        file.open(fileName, ios::in|ios::binary);
        file.read((char*)&bfType, sizeof(WORD));
        file.read((char*)&bfSize, sizeof(DWORD));
        file.read((char*)&bfReserved1, sizeof(WORD));
        file.read((char*)&bfReserved2, sizeof(WORD));
        file.read((char*)&bfOffBits, sizeof(DWORD));
        file.read((char*)&biSize, sizeof(DWORD));
        file.read((char*)&biWidth, sizeof(LONG));
        file.read((char*)&biHeight, sizeof(LONG));
        file.read((char*)&biPlanes, sizeof(WORD));
        file.read((char*)&biBitCount, sizeof(WORD));
        file.read((char*)&biCompression, sizeof(DWORD));
        file.read((char*)&biSizeImage, sizeof(DWORD));
        file.read((char*)&biXPelsPerMeter, sizeof(LONG));
        file.read((char*)&biYPelsPerMeter, sizeof(LONG));
        file.read((char*)&biClrUsed, sizeof(DWORD));
        file.read((char*)&biClrImportant, sizeof(DWORD));
        file.read(RGBQUAD[0], sizeof(RGBQUAD));
        file.read(PIXEL[0], sizeof(PIXEL));
        file.close();

        //显示档案资讯
            cout << "FILE_HEADER\n"
             << "bfType=\t\t"       << bfType       << '\n'
             << "bfSize=\t\t"       << bfSize       << '\n'
             << "bfReserved1=\t"    << bfReserved1  << '\n'
             << "bfReserved2=\t"    << bfReserved2  << '\n'
             << "bfOffBits=\t"      << bfOffBits    << "\n\n"
             << "INFO_HEADER\n"
             << "biSize=\t\t"       << biSize       << '\n'
             << "biWidth=\t"        << biWidth      << '\n'
             << "biHeight=\t"       << biHeight     << '\n'
             << "biPlanes=\t"       << biPlanes     << '\n'
             << "biBitCount=\t"     << biBitCount   << '\n'
             << "biCompression=\t"  << biCompression    << '\n'
             << "biSizeImage=\t"    << biSizeImage      << '\n'
             << "biXPelsPerMeter="  << biXPelsPerMeter  << '\n'
             << "biYPelsPerMeter="  << biYPelsPerMeter  << '\n'
             << "biClrUsed=\t"      << biClrUsed        << '\n'
             << "biClrImportant=\t" << biClrImportant   << "\n\n";

                    //将图片资讯暂存到TEMP里面
                    for(i=127;i>=0;i--){
                            for(j=127;j>=0;j--){
                                    temp[i][j]=PIXEL[i][j];
                                    }
                            }
                            //将资讯反转180度
                    for(i=0;i<=127;i++){
                            for(j=0;j<=127;j++){
                                    PIXEL[127-i][127-j]=temp[i][j];
                                    }
                            }
                    //将资料从记忆体输出到档案       
                    cout << "输入旋转后储存的名称:\t";
                cin >> fileName;

                    file.open(fileName, ios::out|ios::binary);
                    file.write((char*)&bfType, sizeof(WORD));
                    file.write((char*)&bfSize, sizeof(DWORD));
                    file.write((char*)&bfReserved1, sizeof(WORD));
                    file.write((char*)&bfReserved2, sizeof(WORD));
                    file.write((char*)&bfOffBits, sizeof(DWORD));
                    file.write((char*)&biSize, sizeof(DWORD));
                    file.write((char*)&biWidth, sizeof(LONG));
                    file.write((char*)&biHeight, sizeof(LONG));
                    file.write((char*)&biPlanes, sizeof(WORD));
                    file.write((char*)&biBitCount, sizeof(WORD));
                    file.write((char*)&biCompression, sizeof(DWORD));
                    file.write((char*)&biSizeImage, sizeof(DWORD));
                    file.write((char*)&biXPelsPerMeter, sizeof(LONG));
                    file.write((char*)&biYPelsPerMeter, sizeof(LONG));
                    file.write((char*)&biClrUsed, sizeof(DWORD));
                    file.write((char*)&biClrImportant, sizeof(DWORD));
                    file.write(RGBQUAD[0], sizeof(RGBQUAD));
                    file.write(PIXEL[0], sizeof(PIXEL));
                    file.close();
    因为我要显示档案资讯

    所以中间那一段比较复杂

    一般要做特效的话,不必将中间档案资讯的地方每一段都读出来,直接将它读做一个headfile就可以了。


    要读取的图档记得要放在你的专案所储存的资料夹。

    差不多就这样吧。拜拜

    上一篇:C 语言教学第二节
    下一篇:双生质数