视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
c语言读取BMP
2025-09-23 16:08:21 责编:小OO
文档
C语言读取和显示BMP文件 (zt)

默认分类   2009-09-19 14:23   阅读106   评论0   

字号: 大大  中中  小小 

C语言读取和显示BMP文件 

Posted on 2008-01-21 01:12 hoodlum1980 阅读(2624) 评论(0)  编辑 收藏 网摘 

在TC2.0下,隶属于16位子系统,所以int是2字节,long是4字节,char是1字节。绘图系统模式是VGA,颜色当然也很有限,所以读取bmp像素后需要把像素颜色转换为“最近”的已有VGA颜色。用int GetColor(int r,int g,int b)实现返回一个颜色值(color code)。用putpixel(int x,int y,int color)绘制一个像素。

      下图是几种在.NET Framework中的已知颜色和其RGB值(下图当然也是使用代码绘制的,代码略)。

      

      16种颜色是位于RGB立方体中的16个点,相当于寻找一个最接近指定颜色的点。为了简化计算,计算出两点距离的平方即可。

      为了加快搜索,我们可以用下面的类似绘制“金刚石”的代码提前求出最短距离的平方,这个数据将应用到GetColor函数中。原因是我们已知最近的两个颜色点的距离,如果某点与某颜色的距离小于最短距离的一半,则此颜色就是我们要找的结果。

Compute Minimum Dist^2 Code

int COLORS[16][3]={.};

/* i,j - color index */

/* ret - distance^2 */

long GetDist(int i,int j)

{

        long dist=0;

        dist+=(COLORS[i][0]-COLORS[j][0])*(COLORS[i][0]-COLORS[j][0]);

        dist+=(COLORS[i][1]-COLORS[j][1])*(COLORS[i][1]-COLORS[j][1]);

        dist+=(COLORS[i][2]-COLORS[j][2])*(COLORS[i][2]-COLORS[j][2]);

        return dist;

}

void main(void)

{

        int i, j;

        long dist,mindist=195075;

        for(i=0;i<15;i++)

        {

                for(j=i+1;j<16;j++)

                {

                        dist=GetDist(i,j);

                        if(dist                                mindist=dist;

                }

        }

        printf("mindis^2=%d",mindist);

}_

      在下面的代码里为了简化处理,我们仅考虑了一种比较常见的BMP文件,即bpp=24,未经压缩的文件。

Code

#include 

#include 

#include 

#include 

int MAX_Y=480;

int MAX_X=0;

int COLORS[16][3]=

    {

        /* R   G   B        Index    ColorName        */

        {  0,  0,  0},     /* 00 Black                */

        {  0,  0,255},     /* 01 Blue                */

        {  0,128,  0},        /* 02 Green                */

        {  0,255,255},     /* 03 Cyan                */

        {255,  0,  0},     /* 04 Red                */

        {255,  0,255},     /* 05 Magenta            */

        {165, 42, 42},     /* 06 Brown                */

        {211,211,211},     /* 07 LightGray        */

        {169,169,169},     /* 08 DarkGray            */

        {173,216,230},     /* 09 LightBlue        */

        {144,238,144},     /* 10 LightGreen        */

        {144,238,238},        /* 11 LightCyan        */

        {238,144,144},     /* 12 LightRed            */

        {238,144,238},     /* 13 LightMegenta    */

        {255,255,  0},     /* 14 Yellow            */

        {255,255,255},        /* 15 White                */

    };

/* pixel : keep channel order with readfile order */

typedef struct _PIXEL

{

    unsigned char b;

    unsigned char g;

    unsigned char r;

} PIXEL;

/* color item in palette */

typedef struct _RGBQUAD

{

    unsigned char rgbBlue;

    unsigned char rgbGreen;

    unsigned char rgbRed;

    unsigned char rgbReserved;

} RGBQUAD;

/* bitmap file header */

typedef struct _BITMAPFILEHEADER

{

    unsigned int type;

    long fileSize;

    long reserved;

    long offbits;

} BITMAPFILEHEADER,*PBITMAPFILEHEADER;

/* bitmap info header */

typedef struct _BITMAPINFOHEADER

{

    long dwSize;

    long width;

    long height;

    int  planes;

    int  bpp;

    long compression;

    long sizeImage;

    long hResolution;

    long vResolution;

    long colors;

    long importantColors;

} BITMAPINFOHEADER,*PBITMAPINFOHEADER;

/* Functions Declare List */

int      GetColor();

void    ReadImage();

void    DrawAxes();

void    CopyScreen();

/* Entry Point Function */

void main()

{

    int driver,mode;

    char filename[255];

    printf("input the filename of bitmap file:\\n");

    scanf("%s",filename);

    driver=DETECT;

    initgraph(&driver,&mode,"c:\\\c\\\\");

    /* draw a bitmap */

    ReadImage(filename);

    getch();

    closegraph();

}

/* read pixels from imagefile and display */

void ReadImage(char* filename)

{

    FILE* stream;

    char string[255];

    int i,j,width,height,color;

    size_t bytesRead,stride,itemSize=1;

    long offset;

    BITMAPFILEHEADER fileHeader;

    BITMAPINFOHEADER infoHeader;

    unsigned char *pPixels,red,green,blue;

    stream=fopen(filename,"rb");

    if(stream==NULL)

    {

        printf("open file error!\\n");

        exit(0);

    }

    fseek(stream,0,0);

    fread(&fileHeader,1,sizeof(fileHeader),stream);

    fread(&infoHeader,1,sizeof(infoHeader),stream);

    width=infoHeader.width;

    height=infoHeader.height;

    /* stride: scan line bytes count. padding for 4 bytes */

    stride=(infoHeader.bpp*width+31)/32*4;

    pPixels=malloc(stride);

    for(j=height-1;j>=0;j--)

    {

        /* !!! stride (2 bytes) must be convert to long (4 bytes) */

        offset=fileHeader.offbits+j*((long)stride);

        fseek(stream,offset,0);

        bytesRead=fread(pPixels,itemSize,stride,stream);

        for(i=0;i        {

            red    = pPixels[i*3+2];

            green    = pPixels[i*3+1];

            blue    = pPixels[i*3];

            color=GetColor(red,green,blue);

            putpixel(100+i,height+100-j,color);

        }

    }

    fclose(stream);    /* close the bitmap file */

    free(pPixels);

    setcolor(63);

    /* draw the bitmap border rect */

    rectangle(100,100,100+width,100+height);

    /* Draw X and Y axes */

    DrawAxes(width,height);

    setcolor(3);

    sprintf(string,"FileName:\\"%s\\" bpp=%d",filename,infoHeader.bpp);

    outtextxy(100,30,string);

    outtextxy(200,460,"press any key to save screen to a bitmap.");

    getch();

    /* copy the screen and save to bmp file */

    CopyScreen("c:\\\c\\\\SCREEN.BMP",0,0,199+width,199+height);

}

/* compute a color by RGB  */

int GetColor(unsigned int red,unsigned int green,unsigned int blue)

{

    int i,index=0;

    unsigned long dist,temp;

    temp=195075;

    for(i=0;i<16;i++)

    {

        dist=0;

        dist+=(COLORS[i][0]-red)*(COLORS[i][0]-red);

        dist+=(COLORS[i][1]-green)*(COLORS[i][1]-green);

        dist+=(COLORS[i][2]-blue)*(COLORS[i][2]-blue);

         /* minimum dist^2=2492, 623=[minimum dist^2]/4 */

        if(dist<=623) 

            return i;

        if(dist        {

            index=i;

            temp=dist;

        }

    }

    return index;

}

/* draw X and Y axes */

void DrawAxes(int width,int height)

{

    int i,j;

    char text[50];

    setcolor(15);

    line(100,100,150+width,100);            /* X axis */

    line(150+width,100,145+width,97);

    line(150+width,100,145+width,103);

    outtextxy(154+width,95,"X");

    line(100,100,100,150+height);         /* Y axis */

    line(100,150+height,97,145+height);

    line(100,150+height,103,145+height);

    outtextxy(95,154+height,"Y");

    for(i=0;i<=width+20;i+=10)

    {

        sprintf(text,"%d",i);

        line(100+i,97,100+i,100);

        if(i%50==0)

        {

            line(100+i,94,100+i,97);     /* make longer */

            sprintf(text,"%d",i);

            outtextxy(95+i,85,text);

        }

    }

    for(j=0;j<=height+20;j+=10)

    {

        line(97,j+100,100,j+100);

        if(j%50==0)

        {

            line(94,j+100,97,j+100);    /* make longer */

            sprintf(text,"%d",j);

            outtextxy(70,j+98,text);

        }

    }

    sprintf(text,"ImageSize: %d * %d pixels",width,height);

    setcolor(2);

    outtextxy(100,50,text);

}

/* copy the screen and save to a bmp file */

void CopyScreen(char* filename,int left,int top,int right,int bottom)

{

    int i,j,width,height,bpp=4,colorUsed=16,stride,index0,index1;

    BITMAPFILEHEADER fileHeader;

    BITMAPINFOHEADER infoHeader;

    RGBQUAD *palette;

    unsigned char *pPixels;

    FILE *stream;

    width=right-left+1;

    height=bottom-top+1;

    stride=(width*bpp+31)/32*4;

    /* fill file header */

    fileHeader.type=0x4D42;    /* filetype:"BM" ascii code */

    fileHeader.fileSize=sizeof(infoHeader);

    fileHeader.fileSize+=sizeof(RGBQUAD)*colorUsed;

    fileHeader.fileSize+=((long)stride)*height;

    fileHeader.reserved=0;

    fileHeader.offbits=sizeof(fileHeader)+sizeof(infoHeader)+4*16;

    /* fill info header */

    infoHeader.dwSize=sizeof(BITMAPINFOHEADER);

    infoHeader.width=width;

    infoHeader.height=height;

    infoHeader.planes=1;    /* must set to 1 */

    infoHeader.bpp=bpp;

    infoHeader.compression=0;

    infoHeader.sizeImage=((long)stride)*height;

    infoHeader.hResolution=0x27;

    infoHeader.vResolution=0x27;

    infoHeader.colors=16;

    infoHeader.importantColors=0;

    /* fill RGBQUAD items */

    palette=malloc(sizeof(RGBQUAD)*16);

    if(palette==NULL)

    {

        printf("malloc for palette fail!");

        return;

    }

    for(i=0;i<16;i++)

    {

        palette[i].rgbRed = COLORS[i][0];

        palette[i].rgbGreen = COLORS[i][1];

        palette[i].rgbBlue = COLORS[i][2];

        palette[i].rgbReserved = 0;

    }

    /* open the file in wb mode */

    stream=fopen(filename,"wb");

    if(stream==NULL)

    {

        printf("open file fail!");

        return;

    }

    fwrite(&fileHeader,sizeof(fileHeader),1,stream);

    fwrite(&infoHeader,sizeof(infoHeader),1,stream);

    fwrite(palette,sizeof(RGBQUAD),16,stream);

    free(palette);

    /* write the bitmap data: color indexes ,bpp=4 */

    pPixels=malloc(stride);

    if(pPixels==NULL)

    {

        printf("malloc for pPixels fail!");

        return;

    }

    for(j=bottom;j>=top;j--)

    {

        memset(pPixels,0,stride);

        for(i=left;i<=right;i+=2)

        {

            /* 2 pixels to 1 byte */

            index0=getpixel(i,j);

            index1=(i==right)? 0: getpixel(i+1,j);

            pPixels[i/2]=(index0<<4)+index1;

        }

        fwrite(pPixels,1,stride,stream);

    }

    fclose(stream);

}   /* ---------END------------ */_

      首先我们要知道的几个概念:

      bpp:位深度,单位是位/像素(bits per pixel),bpp决定了所能表示的颜色数量。例如bpp=1,则说明图像只有黑白两色(二值图像)。bpp=8,为普通的灰度图像。bpp=24,是最常见的RGB三通道彩色图片。

      stride:扫描行宽度,单位是字节。这是一个在图像数据块(文件或内存中的)中进行定位非常重要的概念,指一行像素占据的内存大小。它必须是4bytes整数倍。因此stride从下面表达式的计算:

      stride=(bm.Width*bpp+31)/32*4;      

      在这里我们必须注意,读取BMP文件时,文件地址是long型(4bytes),即32位的地址,当计算偏移地址时,我们必须把16位的size_t或者int类型首先转化为long型,以免高位地址丢失,导致不能正确定位文件。例如下面这句代码中的类型显示转换是不可缺少的。

       offset=fileHeader.offbits+j*((long)stride);

      由于在TC VGA绘图模式下无法截屏(没有DC),所以通过另存为一个4bpp的bmp图片来做示范。

(24 bpp Win32 bmp)->(TC VGA Graph Mode“截屏”)

  

(请您对文章做出评价)下载本文

显示全文
专题