用c ++读取BMP文件的所有字节并旋转图片

Posted

技术标签:

【中文标题】用c ++读取BMP文件的所有字节并旋转图片【英文标题】:Reading all bytes of a BMP file in c++ and rotate picture 【发布时间】:2013-10-07 18:41:34 【问题描述】:

我有一个 BMP 文件。我想读取它的所有字符并通过这些代码将图片旋转 90 cw。但是此代码仅适用于小图片,并且颜色已更改。我想将此代码用于 800*686 像素的图片。此代码不适用于它。我认为错误是在读取文件时,因为当我检查输入文件的字符向量时,在 59000 字节之后,向量中的所有字符都被 0 填充并且文件没有完全读取:

struct pixel
   char blue;
    char green;
    char red;
;

int _tmain(int argc, _TCHAR* argv[])


        //Reading file and save all into data vector
        fstream fl("d://b.bmp");
        ofstream fl2("d://b2.bmp");
        fl.seekg(0,std::ios::end);
        streampos  length = fl.tellg();
        vector<char>  data(length);
        fl.seekg(0,ios::beg);
        fl.read(&data[0],length);


    //make a string of bytes based on characters in "file" vector ,to calculate file features
        byte intfile[54];
        for(int i=0;i<54;i++)
        
            if (data[i]<0)
                intfile[i]=(256+data[i]);
            else
                intfile[i]=data[i];
        

        //bpp is 2 bytes on 28,29 characters
        short int bpp = intfile[28] | intfile[29] << 8;

        //size of file is 4 bytes on 2,3,4,5 characters
        unsigned int size= intfile[2] | intfile[3] << 8 | intfile[4] << 16 | intfile[5] << 24;

        //offset of pixeles array is 4 bytes on 10,11,12,13 characters
        unsigned int offset= intfile[10] | intfile[11] << 8 | intfile[12] << 16 | intfile[13] << 24;

        //with is 4 bytes on 18,19,20,21 characters
        unsigned int with= intfile[18] | intfile[19] << 8 | intfile[20] << 16 | intfile[21] << 24;

        //height is 4 bytes on 22,23,24,25 characters
        unsigned int height= intfile[22] | intfile[23] << 8 | intfile[24] << 16 | intfile[25] << 24;

        //format of compression is 4 bytes on 30,31,32,33 characters
        unsigned int format= intfile[30] | intfile[31] << 8 | intfile[32] << 16 | intfile[33] << 24;


        //2D vector of pixels and filling it by data vector
        vector< vector<pixel> > arrpix;
        arrpix.resize(height);
        for(int j=0;j<height;j++)
            arrpix[j].resize(with);

        int ix=offset;
        for(int i=0;i<height;i++)
            for(int j=0;j<with;j++)
                arrpix[i][j].blue=data[ix++]; 
                arrpix[i][j].green=data[ix++];
                arrpix[i][j].red=data[ix++]; 
            
            ix+=2;//padd
        

        //2d new vector for making new rotated file
        vector< vector<pixel> > arrpix2;
        arrpix2.resize(with);
        for(int j=0;j<with;j++)
            arrpix2[j].resize(height);

        for(int i=0;i<with;i++)
            for(int j=0;j<height;j++)
                arrpix2[i][j].blue=arrpix[j][with-1-i].blue;
                arrpix2[i][j].green=arrpix[j][with-1-i].green;          
                arrpix2[i][j].red=arrpix[j][with-1-i].red;
               

        //newsize
        unsigned int news=(with*height*3)+54;//in rotation pad is not need because the new with is 800

        //makeing new vector
        vector<char>  data2(news);
        for(int i=0;i<news;i++)
            data2[i]=data[i];

        //change size
        data2[5] = (news >> 24) & 0xFF;
        data2[4] = (news >> 16) & 0xFF;
        data2[3] = (news >> 8) & 0xFF;
        data2[2] = news & 0xFF;


        //replace height and with
        for(int i=0;i<4;i++)
            data2[18+i]=data[22+i];
            data2[22+i]=data[18+i];
        ix=offset;
        //filling data by 2d new vector
        for(int i=0;i<with;i++)
            for(int j=0;j<height;j++)
                data2[ix++]=arrpix2[i][j].blue;
                data2[ix++]=arrpix2[i][j].green;
                data2[ix++]=arrpix2[i][j].red;
               
        


        fl2.write(&data2[0],news);
        fl2.seekp(news,ios::beg);
        fl2.close();


    return 0;

【问题讨论】:

为什么数据是向量 不是向量 你有很多“神奇的数字” 54是什么?什么是28? 29是什么?你应该给它们起有意义的名字,并且可能计算它们而不是硬编码它们。 @DaleWilson 我对此进行了检查,但是出现了错误。因为 file.read 适用于 char 54 是基于 wikipedia 文档的 bmp 文件的标题,我对这些数字进行了注释 我认为这些并不重要。问题是读取字节的所有字符,但此代码读取向量中的前 59000 个字符和其他由 0 填充的字符。 【参考方案1】:

当您将文件重新定位到开头时,以实际读取我认为您想要的数据:

 fl.seekg(0,ios::beg);

而不是

 fl.seekg(length,ios::beg);

编辑:

阅读后添加以下代码:

if(f1.eof())

   std::cerr << "Error reading file."
             << " Requested " << length << " bytes."
             << " Read " << f1.gcount() << bytes."
             << std::endl;

这应该告诉您代码认为文件有多大(根据实际文件大小验证),以及 f1 是否认为读取顺利。


您还应该在打开文件时使用 ios::binary 模式标志以二进制模式打开文件。

【讨论】:

以上是关于用c ++读取BMP文件的所有字节并旋转图片的主要内容,如果未能解决你的问题,请参考以下文章

用C语言编写程序处理图片bmp文件 1.读取图片的宽度,高度,每个像素所需的位数,水平分辨率,垂直

C语言读取1位的BMP图

读bmp图片:头文件为66字节。。。怎么用c语言来读取数据啊,网上的代码我看不懂。新手,希望能写明白些

用c#编写一个程序读取一张bmp图片的数据并转化为灰度图保存到文件中

用标准c读取某bmp文件的长宽及象素等信息需要哪些函数?

用C语言读取16位bmp图片的每个像素的信息~