020-29133788
    资 讯
    您的位置:首页 >> 资 讯 >> 软件应用 >> 编程开发 >> 正文
    读取 bitmap 档案的 C 范例程式

    点击:   发布日期:2013-01-19

    本文来自 www.020fix.com

    bitmap 没那么难,那么多人在问,我写一段 code 大家看吧
    bitmap 格式自己查,本程式只处理 24 bits/per pixel,并且是没经过压缩的 bitmap 图档。
    如果把其他 1bit, 2bits, 8bits 都放进去程式码就太长了,更何况处理动作都是一样的。
    如果是压缩的 bitmap 格式,那只是 run length algorithm 而已,有兴趣的自己做做看。
    本范例只是告诉你怎么把 bitmap 档案的资讯读出来,把图档内容读出来,把多馀的资料(padding)去掉。
    读完档案之后若要处理图形,请对 image[] 内的资料下手。

    我已经尽量把每个步骤都用最笨的方式一步一步全部写出来。
    我想,市面上的书大概不会有比这一段程式码更清楚交代 bitmap 的处理过程了。

    good luck!
    复制内容到剪贴板
    代码:
    /* bmpinfo.h */
    #define FOUR_BYTE_ALIGN(x) ( ( (x)+3 ) >> 2 << 2 )

    #pragma pack(1)
    typedef struct tagBitMapFileHeader {/* size  offset */
        char            Type[2];        /*  2   0   */
        unsigned long   Size;           /*  4   2   */
        unsigned short  Reserved1;      /*  2   6   */
        unsigned short  Reserved2;      /*  2   8   */
        unsigned long   OffBits;        /*  4   10  */
    } BitMapFileHeader;                 /* Total size: 14 */
    #pragma pack()

    #pragma pack(1)
    typedef struct tagBitMapInfoHeader {/* size  offset */
        unsigned long   Size;           /*  4   0   */
        long            Width;          /*  4   4   */
        long            Height;         /*  4   8   */
        unsigned short  Planes;         /*  2   12  */
        unsigned short  BitCount;       /*  2   14  */
        unsigned long   Compression;    /*  4   16  */
        unsigned long   SizeImage;      /*  4   20  */
        long        XPelsPerMeter;      /*  4   24  */
        long        YPelsPerMeter;      /*  4   28  */
        unsigned long   ClrUsed;        /*  4   32  */
        unsigned long   ClrImportant;   /*  4   36  */
    } BitMapInfoHeader;                 /* Total size: 40 */
    #pragma pack()

    #pragma pack(1)
    typedef struct RGBQ {   /* Colormap entry structure */
        char  rgbBlue;      /* Blue value */
        char  rgbGreen;     /* Green value */
        char  rgbRed;       /* Red value */
        char  rgbReserved;  /* Reserved */
    } RGBQuad;
    #pragma pack()

    typedef struct tagBitMapInfo {          /* Bitmap information structure */
        BitMapInfoHeader    bmiHeader;      /* Image header */
        RGBQuad             bmiColors[256]; /* Image colormap */
    } BitMapInfo;
    复制内容到剪贴板
    代码:
    /* mybmp.c */
    #include <stdio.h>
    #include "bmpinfo.h"

    //#define _PRINT_BMP_HEADER
    //#define _PRINT_BMP_PALETTE
    //#define _PRINT_BMP_PAYLOAD
    //#define _PRINT_BMP_RAWIMAGE

    int GetBMPHeader (const char *filename, BitMapFileHeader *bmfh, BitMapInfoHeader *bmih)
    {
        static char *scheme[] = {
            "BI_RGB (no compression)",
            "BI_RLE8",
            "BI_RLE4"   };
        FILE    *fp;
        long    file_length;

        fp = fopen(filename, "rb");
        if (fp == NULL) return 0;

        // Get BitMap file header
        fread (bmfh, sizeof(BitMapFileHeader), 1, fp);
        fseek (fp, 0L, SEEK_END);
        file_length = ftell(fp);    // get file length
        fseek (fp, sizeof(BitMapFileHeader), SEEK_SET);  // move fp
        // detect if the input file is BMP file
        if ( memcmp(bmfh->Type, "BM", 2) != 0 && file_length != bmfh->Size)
            return 0;

        // Get BitMap file information
        fread (bmih, sizeof(BitMapInfoHeader), 1, fp);

    #ifdef _PRINT_BMP_HEADER
        printf("\nType      : %c%c",bmfh->Type[0], bmfh->Type[1]);
        printf("\nSize      : %U", bmfh->Size);
        printf("\nRes1      : %u", bmfh->Reserved1);
        printf("\nRes2      : %u", bmfh->Reserved2);
        printf("\nOffBits   : %U\n", bmfh->OffBits);
        printf("\nSize          : %U", bmih->Size);
        printf("\nWidth * Height: %D * %D", bmih->Width, bmih->Height);
        printf("\nPlanes        : %u", bmih->Planes);
        printf("\nBitCount      : %u", bmih->BitCount);
        printf("\nCompression   : %s", scheme[bmih->Compression]);
        printf("\nSizeImage     : %U", bmih->SizeImage);
        printf("\nXPels         : %D", bmih->XPelsPerMeter);
        printf("\nYPels         : %D", bmih->YPelsPerMeter);
        printf("\nClrUsed       : %U", bmih->ClrUsed ? bmih->ClrUsed : 1 << bmih->BitCount);
        printf("\nClrImpor      : %U", bmih->ClrImportant);
        printf("\n\n");
    #endif

        fclose(fp);
        return 1;
    }

    int GetBMPColorMap (const char *filename, const BitMapInfoHeader *bmih, RGBQuad *bmp_bgr)
    {
        int     colorMapSize, i;
        FILE    *fp;

        if ( (bmih->BitCount != 24) &&
            (bmih->BitCount == 1 || bmih->BitCount == 4 || bmih->BitCount == 8) )
            colorMapSize = 1 << bmih->BitCount;
        else
            colorMapSize = 0;

        // Get the color palette
        if (colorMapSize) {
            fp = fopen(filename, "rb");
            if (fp == NULL) return 0;
            fseek(fp, sizeof(BitMapFileHeader) + sizeof(BitMapInfoHeader), SEEK_SET);
            for ( i = 0; i < colorMapSize; ++i) // read the data of color palette
                fread (&bmp_bgr[i], sizeof (RGBQuad), 1, fp);
            fclose (fp);
        }
        return 1;
    }

    int GetBMPPayload (const char *filename, const BitMapFileHeader *bmfh,
                    const BitMapInfoHeader *bmih, char *payload)
    {
        FILE    *fp;
        int     i = 0;

        fp = fopen(filename, "rb");
        if (fp == NULL) return 0;
        fseek (fp, bmfh->OffBits, SEEK_SET);
        fread(payload, bmih->SizeImage, 1, fp);
        fclose (fp);
        return 1;
    }

    int CutPadding (const char *payload, char *rawImage, const BitMapInfoHeader *bmih)
    {
        int i, j;
        int bytesPerLine, padding;

        // calculate padding
        bytesPerLine = ((int)bmih->Width * (int)bmih->BitCount + 7) >> 3;
        padding = FOUR_BYTE_ALIGN(bytesPerLine) - bytesPerLine;
       
        for (i = 0, j = 0; i < bmih->SizeImage; i++, j++) {
            rawImage[j] = payload[i];
            if ( i % bytesPerLine == 0 && i != 0)
                i = i + padding;
        }
        return 1;
    }

    int main (int argc, char *argv[])
    {
        BitMapFileHeader    bmfh;
        BitMapInfoHeader    bmih;
        RGBQuad             *bm_bgr;
        int                 isBmp = 0;
        int                 i, j;
        char                *payload, *image;

        if (argc != 2) {
            printf("\nUSAGE : mybmp.exe <file.bmp>");
            exit(-1);
        }

        if ( !GetBMPHeader(argv[1], &bmfh, &bmih) ) {
            printf ("Load file fail !!\n");
            exit (-1);
        }
        else { isBmp = 1; }

        // Get color palette
        if ( isBmp && (bmih.BitCount != 24) &&
            (bmih.BitCount == 1 || bmih.BitCount == 4 || bmih.BitCount == 8) ) {
            bm_bgr = (RGBQuad *) malloc(sizeof(RGBQuad) * (1 << bmih.BitCount));
            if (!GetBMPColorMap(argv[1], &bmih, bm_bgr))
                printf ("Can not Get BMP ColorMap\n");
        }

    #ifdef _PRINT_BMP_PALETTE
            if (bmih.BitCount == 1 || bmih.BitCount == 4 || bmih.BitCount == 8) {
                printf ("\n--- The BMP palette content ---\n");
                printf (" Color Index     B   G   R\n");
                printf (" ----------------------------\n");
                for ( i = 0; i < (1 << bmih.BitCount); ++i)
                    printf ("      %3d:         %02X %02X %02X\n", i,
                        bm_bgr[i].rgbBlue, bm_bgr[i].rgbGreen, bm_bgr[i].rgbRed);
            }
    #endif

        if (isBmp) {    // Get payload (include padding data)
            payload = (char *) malloc(bmih.SizeImage);
            if (!GetBMPPayload (argv[1], &bmfh, &bmih, payload))
                printf ("Can not get payload\n");
        }

    #ifdef _PRINT_BMP_PAYLOAD
        printf ("\n Print BMP Payload (with padding)=====================\n");
        for (i = 0; i < bmih.SizeImage; i++) {
            if (i % 10 == 0)
                printf ("\n");
            printf (" %02X", payload[i]);
        }
    #endif

        if (isBmp) {    // cut padding data
            image = (char *) malloc(bmih.Width * bmih.Height * bmih.BitCount);
            if (!CutPadding (payload, image, &bmih))
                printf ("CutPadding error\n");
        }

    #ifdef _PRINT_BMP_RAWIMAGE
            printf ("\n Print BMP rawImage (without padding)==============\n");
            for (i = 0; i < bmih.Width * bmih.Height * bmih.BitCount >> 3; i++) {
            if (i % 10 == 0)
                printf ("\n");
            printf (" %02X", image[i]);
        }
    #endif

        if ( isBmp && (bmih.BitCount != 24) &&
                (bmih.BitCount == 1 || bmih.BitCount == 4 || bmih.BitCount == 8) )
        free (bm_bgr);
       
        free (payload);
        free (image);
        return 1;
    }