ForestMirror77 2022-03-31 23:42 采纳率: 100%
浏览 26
已结题

在使用C++进行BMP位图处理时遇到的问题

问题遇到的现象和发生背景

在使用C++学习图像处理时,遇到的一个小问题。
现象:复制后的文件数据出现"错位",原因是多了两个字节
背景:使用Visual studio 2022 处理BMP位图

完整代码
#include <iostream>
#include <fstream>

using namespace std;

typedef struct  //位图文件头格式  
{
    short int bfType;       // 位图文件的类型,必须设置为BM    _**正是该部分数据出现问题**_
    int bfSize;      // 位图文件的大小,以字节为单位  
    short int bfReserved1;// 位图文件保留字,必须设置为0   
    short int bfReserved2;// 位图文件保留字,必须设置为0 
    short int bfOffBits;   // 位图数据相对于位图文件头的偏移量表示,即位图点阵偏移量

}HEAD;     //实际上,使用sizeof(HEAD)==16 因为 sizeof以4字节为单位   _**我不清楚是不是这种问题**_

typedef struct  //位图文件头信息
{
    int biSize; //结构体字节的总数
    int biWidth; // 位图的宽度,以像素为单位
    int biHeight; // 位图的高度,以像素为单位
    short int biPlanes; // 目标设备的位平面数,必须为1
    short int biBitCount; // 每个像素的位数,必须是1(单色)、416色)、8256色)或24(真彩色)
    int biCompression; // 位图的压缩类型,必须是0(不压缩)、1(BI-RLE8压缩类型)或2(BI-RLE4压缩类型)
    int biSizeImage; // 位图的大小,以字节为单位
    int biXPeIsPerMeter; // 位图的目标设备水平分辨率,以每米像素数为单位(水平像素数)
    int biYPeIsPerMeter; // 位图的目标设备垂直分辨率,以每米像素数为单位(垂直像素数)
    int biClrUsed; // 位图实际使用的颜色表中的颜色变址数,即使用的颜色数
    int biClrImpotant; // 位图显示过程中被认为重要颜色的变址数,即所使用的重要颜色数,为0时表示所有颜色都很重要

}INFO; //sizeof(INFO)==40正好为4倍数    **_是否因为此处结构体字节数正好是4的倍数才正常?_**

typedef struct   //定义RGBQUAD类型结构体,储存一种颜色信息颜色
{
    unsigned char rgbBlue;      //蓝色所占比重
    unsigned char rgbGreen;     //绿色所占比重
    unsigned char rgbRed;       //红色所占比重
    unsigned char rgbReserved;  //保留字节

}RGBQUAD; // sizeof(RGBQUAD)==4

int main()
{
        HEAD strHead;
        INFO strInfo;
        RGBQUAD straPla[256]{};
        unsigned char strPixel[262144];
    
        char szFilena_1[30] = { "C:\\LENA.BMP" }, szFilena_2[30] = { "C:\\LENA2.BMP"};   //记录要处理的源文件与处理后的目的文件名
    
        ifstream infile;
        ofstream outfile;

        infile.open(szFilena_1,ios::binary);
        
        outfile.open(szFilena_2, ios::binary);

        int nCounti;//用以实现循环中对颜色板数据的读取与写入

        
        //读出原文件头 14字节
        infile.read((char*)&strHead.bfType, 2);
        infile.read((char*)&strHead.bfSize, 4);
        infile.read((char*)&strHead.bfReserved1, 2);
        infile.read((char*)&strHead.bfReserved2, 2);
        infile.read((char*)&strHead.bfOffBits, 4);

        //读出原文件信息头 40字节          
        infile.read((char*)&strInfo.biSize, 4);
        infile.read((char*)&strInfo.biWidth, 4);
        infile.read((char*)&strInfo.biHeight, 4);
        infile.read((char*)&strInfo.biPlanes, 2);
        infile.read((char*)&strInfo.biBitCount, 2);
        infile.read((char*)&strInfo.biCompression, 4);
        infile.read((char*)&strInfo.biSizeImage, 4);
        infile.read((char*)&strInfo.biXPeIsPerMeter, 4);
        infile.read((char*)&strInfo.biYPeIsPerMeter, 4);
        infile.read((char*)&strInfo.biClrUsed, 4);
        infile.read((char*)&strInfo.biClrImpotant, 4);

        //读出原文件颜色板                                        //颜色板也没有错位
        for (nCounti = 0; nCounti < 256; nCounti++)
        {
            infile.read((char*)&straPla[nCounti], 4);
        }

        //读取位图数据                                               //位图数据也没有出现错位
        for (nCounti = 0; nCounti < 262144; nCounti++)
        {
            infile.read((char*)&strPixel[nCounti], 1);
        }

        //写入文件头
        outfile.write((char*)&strHead, 14);

        //写入文件信息头
        outfile.write((char*)&strInfo, 40);

        //写入颜色板
        for (nCounti = 0; nCounti < 256; nCounti++)
        {
            outfile.write((char*)&straPla[nCounti], 4);
        }

        //写入位图数据

        for (nCounti = 0; nCounti < 262144; nCounti++)
        {
            outfile.write((char*)&strPixel[nCounti], 1);
        }

        //控制台输出文件信息          
        cout << "bfType:" << strHead.bfType << endl;
        cout << "bfSize:" << strHead.bfSize << endl;
        cout << "bfReserved1:" <<  strHead.bfReserved1 << endl;
        cout << "bfReserved2:" <<  strHead.bfReserved2 << endl;
        cout << "bfOffBits:" <<  strHead.bfOffBits << endl;

        cout << "biSize :" <<  strInfo.biSize << endl;
        cout << "biWidth :" <<  strInfo.biWidth << endl;
        cout << "biHeight :" <<  strInfo.biHeight << endl;
        cout << "biPlanes :" <<  strInfo.biPlanes << endl;
        cout << "biBitCount :" <<  strInfo.biBitCount << endl;
        cout << "biCompression:" <<  strInfo.biCompression << endl;
        cout << "biSizeImage :" << strInfo.biSizeImage << endl;
        cout << "biXPeIsPerMeter :" <<  strInfo.biXPeIsPerMeter << endl;
        cout << "biYPeIsPerMeter:" <<  strInfo.biYPeIsPerMeter << endl;
        cout << "biClrUsed :" <<  strInfo.biClrUsed << endl;
        cout << "biClrImpotant :" <<  strInfo.biClrImpotant << endl;
    return 0;
}

运行结果

无报错,控制台输出:

img


原BMP位图 LENA.BMP以16进制打开:

img

创建的BMP位图LENA2.BMP以16进制打开:

img

尝试过的方法

将写入文件头结构体 Head部分改为:

//写入文件头
        outfile.write((char*)&strHead.bfType, 2);
        outfile.write((char*)&strHead.bfSize, 4);
        outfile.write((char*)&strHead.bfReserved1, 2);
        outfile.write((char*)&strHead.bfReserved2, 2);
        outfile.write((char*)&strHead.bfOffBits, 4);

所创建的BMP位图 LENA2.BMP能正常打开而且与原文件一模一样(本笨蛋只能想到这个.)

希望的解决方案:

就是想知道这种问题出在哪。凡是字节数为4的倍数都没有多字节的问题.
以及范式的编程方法.

  • 写回答

3条回答 默认 最新

  • CSDN专家-link 2022-04-01 07:24
    关注

    数据结构有字节对齐问题,所以outfile.write((char*)&strHead, 14);是有问题的。因为其中有一个是int类型,第一个短整型数据之后会空两个字节,导致直接按结构变量写入会出现cc cc这个无效字节。应该逐个写入数据结构变量。
    outfile.write((char*)&strInfo, 40); 没有问题是这个结构运气不错,全是int型,有两个短整型正好填满一个int,所以没有为了对齐增加空余字节。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 4月9日
  • 已采纳回答 4月1日
  • 创建了问题 3月31日

悬赏问题

  • ¥20 关于线性结构的问题:希望能从头到尾完整地帮我改一下,困扰我很久了
  • ¥20 设计一个二极管稳压值检测电路
  • ¥15 内网办公电脑进行向日葵
  • ¥15 如何输入双曲线的参数a然后画出双曲线?我输入处理函数加上后就没有用了,不知道怎么回事去掉后双曲线可以画出来
  • ¥50 WPF Lidgren.Network.Core2连接问题
  • ¥15 soildworks装配体的尺寸问题
  • ¥100 有偿寻云闪付SDK转URL技术
  • ¥30 基于信创PC发布的QT应用如何跨用户启动后输入中文
  • ¥20 非root手机,如何精准控制手机流量消耗的大小,如20M
  • ¥15 远程安装一下vasp