读取位图文件:学生反映过的一个由于字节对齐造成的bug_拔剑-浆糊的传说_新浪博客...

One student reported a bug caused by in-memory data alignment, when reading a bitmap file,
it is said that image size and with are always wrong. The fix solution is quite much simple:
You can just simply and temperalily disable data in-memory alignment by calling:
            #pragma pack(push, 1) 
After that BitmapFileheader and BMPheader information could be written faithfully.

#pragma pack(push, 1) 
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;  
DWORD bfSize;
WORD bfReserved1;  
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
#pragma pack(pop) //back to whatever the previous packing mode was

==========================================================
//  Source code appended, quite much in C style
//  There is memory leak issue, haha, just let it be la

#include < string.h >    
#include < math.h >      
#include < stdio.h >      
#include < stdlib.h >      
#include < malloc.h >   

#define bool char
#define ture 1
#define false 0

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

// zxg, 临时不允许4字节对齐
#pragma pack(push, 1) // exact fit - no padding
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;  
DWORD bfSize; 
WORD bfReserved1;  
WORD bfReserved2; 
DWORD bfOffBits; 
} BITMAPFILEHEADER;
#pragma pack(pop) //back to whatever the previous packing mode was 

// zxg, 临时不允许4字节对齐
#pragma pack(push, 1) // exact fit - no padding
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;     
LONG biWidth;    
LONG biHeight;    
WORD biPlanes;    
WORD biBitCount ;  
DWORD biCompression;  
DWORD biSizeImage;   
LONG biXPelsPerMeter;  
LONG biYPelsPerMeter;  
DWORD biClrUsed;  
DWORD biClrImportant; 
}BITMAPINFOHEADER;
#pragma pack(pop) //back to whatever the previous packing mode was 


typedef struct tagRGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
}RGBQUAD;





unsigned char *pBmpBuf = NULL; //pointer that reads the image's data
int bmpWidth; //image' wide
int bmpheight;
RGBQUAD *pColorTable; 
int biBitCount;

bool readBmp(char *bmpName)
{
FILE *fp;
fp =fopen(bmpName,"rb");
if(fp==0)
return 0;

int size1 = sizeof(BITMAPFILEHEADER);
//fseek(fp,sizeof(BITMAPFILEHEADER),SEEK_SET);
BITMAPFILEHEADER h1;
fread(&h1,size1,1,fp);


BITMAPINFOHEADER head;
fread(&head, sizeof(BITMAPINFOHEADER),1,fp);

bmpWidth = head.biWidth ;
bmpheight = head.biHeight ;
biBitCount = head.biBitCount ;

int lineByte = (bmpWidth *biBitCount/8+3)/4*4;
if(biBitCount != 24 ) // by zxg
{
// by zxg
int color_table_size = 1;
for(int __k = 0; __k < biBitCount; __k++)
{
color_table_size *= 2;
}
// end by zxg
pColorTable=new RGBQUAD[color_table_size];
fread(pColorTable,sizeof(RGBQUAD),color_table_size,fp);
}

pBmpBuf = new unsigned char[lineByte*bmpheight];
fread(pBmpBuf,1,lineByte*bmpheight,fp);

fclose(fp);
return 1;
}

bool saveBmp(char *bmpName, unsigned char *imgBuf, int width,int height,int biBitCount,RGBQUAD *pColorTable)
{
if(!imgBuf)
return 0;

int colorTablesize=0;
if(biBitCount==8)
colorTablesize=1024;
int lineByte=(width*biBitCount/8+3)/4*4;
FILE *fp=fopen(bmpName,"wb");
if(fp==0)
return 0;
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42;
fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*height;
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;

fileHead.bfOffBits=54+colorTablesize;
fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);

BITMAPINFOHEADER head;
head.biBitCount = biBitCount;
head.biClrImportant =0;
head.biClrUsed =0;
head.biCompression=0;
head.biHeight=height;
head.biPlanes=1;
head.biSize=40;
head.biSizeImage=lineByte*height;
head.biWidth=width;
head.biXPelsPerMeter=0;
head.biYPelsPerMeter=0;

fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);
// by zxg, start
//if(biBitCount==8) // commented out by zxg
if(biBitCount != 24 ) 
{    
// by zxg
int color_table_size = 1;
for(int __k = 0; __k < biBitCount; __k++)
{
color_table_size *= 2;
}
fwrite(pColorTable,sizeof(RGBQUAD),color_table_size,fp);
}
    // end by zxg

fwrite(imgBuf, height*lineByte, 1, fp);

fclose(fp);
return 1;




}

void main_24bits()
{
char readPath[]="f:\\lele_24_bits.BMP";
readBmp(readPath);
printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpheight,biBitCount);

char writePath[]="f:\\lele_24_bits_copy.BMP";
saveBmp(writePath,pBmpBuf,bmpWidth,bmpheight,biBitCount,pColorTable);

delete[]pBmpBuf;
if(biBitCount==8)
delete[]pColorTable;
}
void main_8bits()
{
char readPath[]="f:\\lele_8_bits.BMP";
readBmp(readPath);
printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpheight,biBitCount);

char writePath[]="f:\\lele_8_bits_copy.BMP";
saveBmp(writePath,pBmpBuf,bmpWidth,bmpheight,biBitCount,pColorTable);

delete[]pBmpBuf;
if(biBitCount==8)
delete[]pColorTable;
}
void main_4bits()
{
char readPath[]="f:\\lele_4_bits.BMP";
readBmp(readPath);
printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpheight,biBitCount);

char writePath[]="f:\\lele_4_bits_copy.BMP";
saveBmp(writePath,pBmpBuf,bmpWidth,bmpheight,biBitCount,pColorTable);

delete[]pBmpBuf;
if(biBitCount==8)
delete[]pColorTable;
}

int main()
{
    main_24bits();
    main_8bits();
    main_4bits();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值