首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

帮忙看一下这个小程序。解决思路

2012-02-04 
帮忙看一下这个小程序。#includestdio.h #includeconio.h #includestdlib.h voidmain(){/*BMP文件头*

帮忙看一下这个小程序。
#include   "stdio.h "
#include   "conio.h "
#include   "stdlib.h "
void   main()
{
      /*     BMP文件头   */
      typedef   struct
      {
          unsigned   short   bfType;   /*     文件类型   */
          unsigned   long   bfSize;   /*     文件大小   */
          unsigned   short   bfReserved1;   /*     保留位   */
          unsigned   short   bfReserved2;   /*     保留位   */
          unsigned   long   bfOffBits;   /*     数据偏移位置   */
  }   HEAD;

        /*     BMP信息头   */
      typedef   struct
      {
          unsigned   long   biSize;   /*     此结构大小   */
          long   biWidth;   /*     图像宽度   */
          long   biHeight;   /*     图像高度   */
          unsigned   short   biPlanes;   /*     调色板数量   */
          unsigned   short   biBitCount;   /*     每个象素对应的位数,24:24位图,32:带alpha通道的24位图   */
          unsigned   long   biCompression;   /*     压缩   */
          unsigned   long   biSizeImage;   /*     图像大小   */
          long   biXPelsPerMeter;/*     横向分辨率   */
          long   biYPelsPerMeter;/*     纵向分辨率   */
          unsigned   long   biClrUsed;   /*     颜色使用数   */
          unsigned   long   biClrImportant;   /*     重要颜色数   */
      }BMPINFOHEADER;

    FILE   *file   ;
    HEAD   bmpFile;
    BMPINFOHEADER   bmpInfo;


    /*     打开文件   */
    file   =   fopen( "LENNA.BMP ",   "rb ");
    if   (file==   NULL)
    {
        printf( "   openning   error\n ");
    }
    /*   读入文件头   */
    fread(&bmpFile,   sizeof(HEAD)-2,1,   file);
    if   (bmpFile.bfType   !=   0x4D42)
    {
        printf( "   reading   error!!! ");
    }
    printf( "%x\n ",bmpFile.bfType);   /*     验证文件类型   */
    printf( "%ld\n ",bmpFile.bfSize);
    printf( "%ld\n ",bmpFile.bfOffBits);

    /*   读信息头   */
    fread(&bmpInfo,   sizeof(BMPINFOHEADER),   1,   file);
    printf( "%ld\n ",bmpInfo.biSizeImage);
    printf( "%d\n ",bmpInfo.biWidth);
    printf( "%d\n ",bmpInfo.biHeight);
    printf( "%d\n ",bmpInfo.biBitCount);


   

}
就是读一个位图的信息,我读的是一个512*512的灰度图象。

结果是:
4d42
4
-859045888
0
512
512
8

printf( "%ld\n ",bmpFile.bfSize);
  printf( "%ld\n ",bmpFile.bfOffBits);
printf( "%ld\n ",bmpInfo.biSizeImage);
这三个怎么读的数据不对啊??是什么原因?

[解决办法]
编译器一般会对结构成员进行对齐,所以你定义的结构大小不一定正好和bmp文件头的结构大小一致,导致读文件错位。

不信你可以试试输出sizeof(HEAD),肯定不等于14个字节(bmp头14个字节是文件头)

你可以通过强制编译器按字节对齐来解决这个问题。
#pragma pack(1)
[解决办法]
你知道编译器对HEAD是怎么对齐的吗?
如果按4字节对齐
typedef struct
{
unsigned short bfType; // 4个字节
unsigned long bfSize; // 4个字节
unsigned short bfReserved1; // 下面两个short合成一个4字节
unsigned short bfReserved2;
unsigned long bfOffBits; // 4个字节
} HEAD;
你即使sizeof(HEAD)-2也没用,bfSize本来就和文件里数据错位啦,后面都错位啦

你为什么就不试试
#pragma pack(1)

[解决办法]
程序要有移植性,可以这样写你的程序:

#include "stdio.h "
#include "conio.h "
#include "stdlib.h "

/* BMP文件头 */
typedef struct
{
unsigned short bfType; /* 文件类型 */
unsigned long bfSize; /* 文件大小 */
unsigned short bfReserved1; /* 保留位 */
unsigned short bfReserved2; /* 保留位 */
unsigned long bfOffBits; /* 数据偏移位置 */
} HEAD;

/* BMP信息头 */
typedef struct
{
unsigned long biSize; /* 此结构大小 */
long biWidth; /* 图像宽度 */
long biHeight; /* 图像高度 */
unsigned short biPlanes; /* 调色板数量 */
unsigned short biBitCount; /* 每个象素对应的位数,24:24位图,32:带alpha通道的24位图 */
unsigned long biCompression; /* 压缩 */
unsigned long biSizeImage; /* 图像大小 */
long biXPelsPerMeter;/* 横向分辨率 */
long biYPelsPerMeter;/* 纵向分辨率 */
unsigned long biClrUsed; /* 颜色使用数 */
unsigned long biClrImportant; /* 重要颜色数 */
}BMPINFOHEADER;

int readChar( FILE *f ) {
unsigned char ch;

if( fread( &ch, 1, 1, f ) != 1 )
return -1;
int r = ch;
return r & 0x0ff;

}
int readInt16( FILE *f ) {
int b_1 = readChar( f );
int b_2 = readChar( f );
if( b_2 < 0 ) return -1;

return b_2 < < 8 | b_1;
}

int readInt32( FILE *f ) {
int b_1 = readChar( f );
int b_2 = readChar( f );
int b_3 = readChar( f );
int b_4 = readChar( f );

if( b_4 < 0 ) {
printf( "error ");
exit( -1 );
return -1;
}
return (b_4 < < 24) | (b_3 < < 16) | (b_2 < < 8) | b_1;
}

void readHeader(FILE *f, HEAD* pHead ) {
pHead-> bfType = (unsigned short)readInt16( f );
pHead-> bfSize = (unsigned long)readInt32( f );
pHead-> bfReserved1 = (unsigned short)readInt16( f );
pHead-> bfReserved2 = (unsigned short)readInt16( f );
pHead-> bfOffBits = (unsigned long)readInt32( f );

}

void readInfoHeader(FILE *f, BMPINFOHEADER* pHead ) {
pHead-> biSize = (unsigned long)readInt32( f );
pHead-> biWidth = (long)readInt32( f );
pHead-> biHeight = (long)readInt32( f );
pHead-> biPlanes = (unsigned short)readInt16( f );
pHead-> biBitCount = (unsigned short)readInt16( f );
pHead-> biCompression = (unsigned long)readInt32( f );
pHead-> biSizeImage = (unsigned long)readInt32( f );
pHead-> biXPelsPerMeter = (long)readInt32( f );
pHead-> biYPelsPerMeter = (long)readInt32( f );
pHead-> biClrUsed = (unsigned long)readInt32( f );


pHead-> biClrImportant = (unsigned long)readInt32( f );
}

int main( int argc, char** argv )
{


FILE *file ;
HEAD bmpFile;
BMPINFOHEADER bmpInfo;

/* 打开文件 */
file = fopen( argv[1], "rb ");
if (file== NULL)
{
printf( " openning error\n ");
}
/* 读入文件头 */
//fread(&bmpFile, sizeof(HEAD)-2,1, file);
readHeader( file, &bmpFile);
if (bmpFile.bfType != 0x4D42)
{
printf( " reading error!!! ");
}
printf( "%x\n ",bmpFile.bfType); /* 验证文件类型 */
printf( "%ld\n ",bmpFile.bfSize);
printf( "%ld\n ",bmpFile.bfOffBits);

/* 读信息头 */
//fread(&bmpInfo, sizeof(BMPINFOHEADER), 1, file);
readInfoHeader( file, &bmpInfo );
printf( "%ld\n ",bmpInfo.biSizeImage);
printf( "%d\n ",bmpInfo.biWidth);
printf( "%d\n ",bmpInfo.biHeight);
printf( "%d\n ",bmpInfo.biBitCount);

return 0;
}

热点排行