代码
#ifndef _BMP_H_
#define _BMP_H_


/**************************************************************

    QDBMP - Quick n' Dirty BMP

    v1.0.0 - 2007-04-07
    
http://qdbmp.sourceforge.net


    The library supports the following BMP variants:
    1. Uncompressed 32 BPP (alpha values are ignored)
    2. Uncompressed 24 BPP
    3. Uncompressed 8 BPP (indexed color)

    QDBMP is free and open source software, distributed
    under the MIT licence.

    Copyright (c) 2007 Chai Braudo (braudo@users.sourceforge.net)

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.

*************************************************************
*/

#include 
<stdio.h>



/* Type definitions */
#ifndef UINT
    
#define UINT    unsigned long int
#endif

#ifndef USHORT
    
#define USHORT    unsigned short
#endif

#ifndef UCHAR
    
#define UCHAR    unsigned char
#endif


/* Version */
#define QDBMP_VERSION_MAJOR        1
#define QDBMP_VERSION_MINOR        0
#define QDBMP_VERSION_PATCH        1


/* Error codes */
typedef 
enum
{
    BMP_OK 
= 0,                /* No error */
    BMP_ERROR,                
/* General error */
    BMP_OUT_OF_MEMORY,        
/* Could not allocate enough memory to complete the operation */
    BMP_IO_ERROR,            
/* General input/output error */
    BMP_FILE_NOT_FOUND,        
/* File not found */
    BMP_FILE_NOT_SUPPORTED,    
/* File is not a supported BMP variant */
    BMP_FILE_INVALID,        
/* File is not a BMP image or is an invalid BMP */
    BMP_INVALID_ARGUMENT,    
/* An argument is invalid or out of range */
    BMP_TYPE_MISMATCH,        
/* The requested action is not compatible with the BMP's type */
    BMP_ERROR_NUM
} BMP_STATUS;


/* Bitmap image */
typedef 
struct _BMP BMP;




/*********************************** Public methods **********************************/


/* Construction/destruction */
BMP
*            BMP_Create                    ( UINT width, UINT height, USHORT depth );
void            BMP_Free                    ( BMP* bmp );


/* I/O */
BMP
*            BMP_ReadFile                ( const char* filename );
void            BMP_WriteFile                ( BMP* bmp, const char* filename );


/* Meta info */
UINT            BMP_GetWidth                ( BMP
* bmp );
UINT            BMP_GetHeight                ( BMP
* bmp );
USHORT            BMP_GetDepth                ( BMP
* bmp );


/* Pixel access */
void            BMP_GetPixelRGB                ( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b );
void            BMP_SetPixelRGB                ( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b );
void            BMP_GetPixelIndex            ( BMP* bmp, UINT x, UINT y, UCHAR* val );
void            BMP_SetPixelIndex            ( BMP* bmp, UINT x, UINT y, UCHAR val );


/* Palette handling */
void            BMP_GetPaletteColor            ( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b );
void            BMP_SetPaletteColor            ( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b );


/* Error handling */
BMP_STATUS        BMP_GetError                ();
const char*        BMP_GetErrorDescription        ();


/* Useful macro that may be used after each BMP operation to check for an error */
#define BMP_CHECK_ERROR( output_file, return_value ) \
    
if ( BMP_GetError() != BMP_OK )                                                    \
    {                                                                                \
        fprintf( ( output_file ), 
"BMP error: %s\n", BMP_GetErrorDescription() );    \
        
return( return_value );                                                        \
    }                                                                                \

#endif

 

 

代码
#include "qdbmp.h"
#include 
<stdlib.h>
#include 
<string.h>


/* Bitmap header */
typedef 
struct _BMP_Header
{
    USHORT        Magic;                
/* Magic identifier: "BM" */
    UINT        FileSize;            
/* Size of the BMP file in bytes */
    USHORT        Reserved1;            
/* Reserved */
    USHORT        Reserved2;            
/* Reserved */
    UINT        DataOffset;            
/* Offset of image data relative to the file's start */
    UINT        HeaderSize;            
/* Size of the header in bytes */
    UINT        Width;                
/* Bitmap's width */
    UINT        Height;                
/* Bitmap's height */
    USHORT        Planes;                
/* Number of color planes in the bitmap */
    USHORT        BitsPerPixel;        
/* Number of bits per pixel */
    UINT        CompressionType;    
/* Compression type */
    UINT        ImageDataSize;        
/* Size of uncompressed image's data */
    UINT        HPixelsPerMeter;    
/* Horizontal resolution (pixels per meter) */
    UINT        VPixelsPerMeter;    
/* Vertical resolution (pixels per meter) */
    UINT        ColorsUsed;            
/* Number of color indexes in the color table that are actually used by the bitmap */
    UINT        ColorsRequired;        
/* Number of color indexes that are required for displaying the bitmap */
} BMP_Header;


/* Private data structure */
struct _BMP
{
    BMP_Header    Header;
    UCHAR
*        Palette;
    UCHAR
*        Data;
};


/* Holds the last error code */
static BMP_STATUS BMP_LAST_ERROR_CODE = 0;


/* Error description strings */
static const char* BMP_ERROR_STRING[] =
{
    
"",
    
"General error",
    
"Could not allocate enough memory to complete the operation",
    
"File input/output error",
    
"File not found",
    
"File is not a supported BMP variant (must be uncompressed 8, 24 or 32 BPP)",
    
"File is not a valid BMP image",
    
"An argument is invalid or out of range",
    
"The requested action is not compatible with the BMP's type"
};


/* Size of the palette data for 8 BPP bitmaps */
#define BMP_PALETTE_SIZE    ( 256 * 4 )



/*********************************** Forward declarations **********************************/
int        ReadHeader    ( BMP* bmp, FILE* f );
int        WriteHeader    ( BMP* bmp, FILE* f );

int        ReadUINT    ( UINT* x, FILE* f );
int        ReadUSHORT    ( USHORT *x, FILE* f );

int        WriteUINT    ( UINT x, FILE* f );
int        WriteUSHORT    ( USHORT x, FILE* f );






/*********************************** Public methods **********************************/


/**************************************************************
    Creates a blank BMP image with the specified dimensions
    and bit depth.
*************************************************************
*/
BMP
* BMP_Create( UINT width, UINT height, USHORT depth )
{
    BMP
*    bmp;
    
int        bytes_per_pixel = depth >> 3;
    UINT    bytes_per_row;

    
if ( height <= 0 || width <= 0 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
        
return NULL;
    }

    
if ( depth != 8 && depth != 24 && depth != 32 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_FILE_NOT_SUPPORTED;
        
return NULL;
    }


    
/* Allocate the bitmap data structure */
    bmp 
= calloc( 1sizeof( BMP ) );
    
if ( bmp == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_OUT_OF_MEMORY;
        
return NULL;
    }


    
/* Set header' default values */
    bmp
->Header.Magic                = 0x4D42;
    bmp
->Header.Reserved1            = 0;
    bmp
->Header.Reserved2            = 0;
    bmp
->Header.HeaderSize            = 40;
    bmp
->Header.Planes                = 1;
    bmp
->Header.CompressionType        = 0;
    bmp
->Header.HPixelsPerMeter        = 0;
    bmp
->Header.VPixelsPerMeter        = 0;
    bmp
->Header.ColorsUsed            = 0;
    bmp
->Header.ColorsRequired        = 0;


    
/* Calculate the number of bytes used to store a single image row. This is always
    rounded up to the next multiple of 4. 
*/
    bytes_per_row 
= width * bytes_per_pixel;
    bytes_per_row 
+= ( bytes_per_row % 4 ? 4 - bytes_per_row % 4 : 0 );


    
/* Set header's image specific values */
    bmp
->Header.Width                = width;
    bmp
->Header.Height                = height;
    bmp
->Header.BitsPerPixel        = depth;
    bmp
->Header.ImageDataSize        = bytes_per_row * height;
    bmp
->Header.FileSize            = bmp->Header.ImageDataSize + 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
    bmp
->Header.DataOffset            = 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );


    
/* Allocate palette */
    
if ( bmp->Header.BitsPerPixel == 8 )
    {
        bmp
->Palette = (UCHAR*) calloc( BMP_PALETTE_SIZE, sizeof( UCHAR ) );
        
if ( bmp->Palette == NULL )
        {
            BMP_LAST_ERROR_CODE 
= BMP_OUT_OF_MEMORY;
            free( bmp );
            
return NULL;
        }
    }
    
else
    {
        bmp
->Palette = NULL;
    }


    
/* Allocate pixels */
    bmp
->Data = (UCHAR*) calloc( bmp->Header.ImageDataSize, sizeof( UCHAR ) );
    
if ( bmp->Data == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_OUT_OF_MEMORY;
        free( bmp
->Palette );
        free( bmp );
        
return NULL;
    }


    BMP_LAST_ERROR_CODE 
= BMP_OK;

    
return bmp;
}


/**************************************************************
    Frees all the memory used by the specified BMP image.
*************************************************************
*/
void BMP_Free( BMP* bmp )
{
    
if ( bmp == NULL )
    {
        
return;
    }

    
if ( bmp->Palette != NULL )
    {
        free( bmp
->Palette );
    }

    
if ( bmp->Data != NULL )
    {
        free( bmp
->Data );
    }

    free( bmp );

    BMP_LAST_ERROR_CODE 
= BMP_OK;
}


/**************************************************************
    Reads the specified BMP image file.
*************************************************************
*/
BMP
* BMP_ReadFile( const char* filename )
{
    BMP
*    bmp;
    FILE
*    f;

    
if ( filename == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
        
return NULL;
    }


    
/* Allocate */
    bmp 
= calloc( 1sizeof( BMP ) );
    
if ( bmp == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_OUT_OF_MEMORY;
        
return NULL;
    }


    
/* Open file */
    f 
= fopen( filename, "rb" );
    
if ( f == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_FILE_NOT_FOUND;
        free( bmp );
        
return NULL;
    }


    
/* Read header */
    
if ( ReadHeader( bmp, f ) != BMP_OK || bmp->Header.Magic != 0x4D42 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_FILE_INVALID;
        fclose( f );
        free( bmp );
        
return NULL;
    }


    
/* Verify that the bitmap variant is supported */
    
if ( ( bmp->Header.BitsPerPixel != 32 && bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 8 )
        
|| bmp->Header.CompressionType != 0 || bmp->Header.HeaderSize != 40 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_FILE_NOT_SUPPORTED;
        fclose( f );
        free( bmp );
        
return NULL;
    }


    
/* Allocate and read palette */
    
if ( bmp->Header.BitsPerPixel == 8 )
    {
        bmp
->Palette = (UCHAR*) malloc( BMP_PALETTE_SIZE * sizeof( UCHAR ) );
        
if ( bmp->Palette == NULL )
        {
            BMP_LAST_ERROR_CODE 
= BMP_OUT_OF_MEMORY;
            fclose( f );
            free( bmp );
            
return NULL;
        }

        
if ( fread( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
        {
            BMP_LAST_ERROR_CODE 
= BMP_FILE_INVALID;
            fclose( f );
            free( bmp
->Palette );
            free( bmp );
            
return NULL;
        }
    }
    
else    /* Not an indexed image */
    {
        bmp
->Palette = NULL;
    }


    
/* Allocate memory for image data */
    bmp
->Data = (UCHAR*) malloc( bmp->Header.ImageDataSize );
    
if ( bmp->Data == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_OUT_OF_MEMORY;
        fclose( f );
        free( bmp
->Palette );
        free( bmp );
        
return NULL;
    }


    
/* Read image data */
    
if ( fread( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
    {
        BMP_LAST_ERROR_CODE 
= BMP_FILE_INVALID;
        fclose( f );
        free( bmp
->Data );
        free( bmp
->Palette );
        free( bmp );
        
return NULL;
    }


    fclose( f );

    BMP_LAST_ERROR_CODE 
= BMP_OK;

    
return bmp;
}


/**************************************************************
    Writes the BMP image to the specified file.
*************************************************************
*/
void BMP_WriteFile( BMP* bmp, const char* filename )
{
    FILE
*    f;

    
if ( filename == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
        
return;
    }


    
/* Open file */
    f 
= fopen( filename, "wb" );
    
if ( f == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_FILE_NOT_FOUND;
        
return;
    }


    
/* Write header */
    
if ( WriteHeader( bmp, f ) != BMP_OK )
    {
        BMP_LAST_ERROR_CODE 
= BMP_IO_ERROR;
        fclose( f );
        
return;
    }


    
/* Write palette */
    
if ( bmp->Palette )
    {
        
if ( fwrite( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
        {
            BMP_LAST_ERROR_CODE 
= BMP_IO_ERROR;
            fclose( f );
            
return;
        }
    }


    
/* Write data */
    
if ( fwrite( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
    {
        BMP_LAST_ERROR_CODE 
= BMP_IO_ERROR;
        fclose( f );
        
return;
    }


    BMP_LAST_ERROR_CODE 
= BMP_OK;
    fclose( f );
}


/**************************************************************
    Returns the image's width.
*************************************************************
*/
UINT BMP_GetWidth( BMP
* bmp )
{
    
if ( bmp == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
        
return -1;
    }

    BMP_LAST_ERROR_CODE 
= BMP_OK;

    
return ( bmp->Header.Width );
}


/**************************************************************
    Returns the image's height.
*************************************************************
*/
UINT BMP_GetHeight( BMP
* bmp )
{
    
if ( bmp == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
        
return -1;
    }

    BMP_LAST_ERROR_CODE 
= BMP_OK;

    
return ( bmp->Header.Height );
}


/**************************************************************
    Returns the image's color depth (bits per pixel).
*************************************************************
*/
USHORT BMP_GetDepth( BMP
* bmp )
{
    
if ( bmp == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
        
return -1;
    }

    BMP_LAST_ERROR_CODE 
= BMP_OK;

    
return ( bmp->Header.BitsPerPixel );
}


/**************************************************************
    Populates the arguments with the specified pixel's RGB
    values.
*************************************************************
*/
void BMP_GetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b )
{
    UCHAR
*    pixel;
    UINT    bytes_per_row;
    UCHAR    bytes_per_pixel;

    
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
    }
    
else
    {
        BMP_LAST_ERROR_CODE 
= BMP_OK;

        bytes_per_pixel 
= bmp->Header.BitsPerPixel >> 3;

        
/* Row's size is rounded up to the next multiple of 4 bytes */
        bytes_per_row 
= bmp->Header.ImageDataSize / bmp->Header.Height;

        
/* Calculate the location of the relevant pixel (rows are flipped) */
        pixel 
= bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );


        
/* In indexed color mode the pixel's value is an index within the palette */
        
if ( bmp->Header.BitsPerPixel == 8 )
        {
            pixel 
= bmp->Palette + *pixel * 4;
        }

        
/* Note: colors are stored in BGR order */
        
if ( r )    *= *( pixel + 2 );
        
if ( g )    *= *( pixel + 1 );
        
if ( b )    *= *( pixel + 0 );
    }
}


/**************************************************************
    Sets the specified pixel's RGB values.
*************************************************************
*/
void BMP_SetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b )
{
    UCHAR
*    pixel;
    UINT    bytes_per_row;
    UCHAR    bytes_per_pixel;

    
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
    }

    
else if ( bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 32 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_TYPE_MISMATCH;
    }

    
else
    {
        BMP_LAST_ERROR_CODE 
= BMP_OK;

        bytes_per_pixel 
= bmp->Header.BitsPerPixel >> 3;

        
/* Row's size is rounded up to the next multiple of 4 bytes */
        bytes_per_row 
= bmp->Header.ImageDataSize / bmp->Header.Height;

        
/* Calculate the location of the relevant pixel (rows are flipped) */
        pixel 
= bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );

/**************************************************************
    为什么呢?
*************************************************************
*/

        
//if ( bmp->Header.BitsPerPixel == 8 )
        
//{
        
//    *pixel = r;
        
//    return ;
        
//}

        
/* Note: colors are stored in BGR order */
        
*( pixel + 2 ) = r;
        
*( pixel + 1 ) = g;
        
*( pixel + 0 ) = b;
    }
}


/**************************************************************
    Gets the specified pixel's color index.
*************************************************************
*/
void BMP_GetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR* val )
{
    UCHAR
*    pixel;
    UINT    bytes_per_row;

    
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
    }

    
else if ( bmp->Header.BitsPerPixel != 8 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_TYPE_MISMATCH;
    }

    
else
    {
        BMP_LAST_ERROR_CODE 
= BMP_OK;

        
/* Row's size is rounded up to the next multiple of 4 bytes */
        bytes_per_row 
= bmp->Header.ImageDataSize / bmp->Header.Height;

        
/* Calculate the location of the relevant pixel */
        pixel 
= bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );


        
if ( val )    *val = *pixel;
    }
}


/**************************************************************
    Sets the specified pixel's color index.
*************************************************************
*/
void BMP_SetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR val )
{
    UCHAR
*    pixel;
    UINT    bytes_per_row;

    
if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
    }

    
else if ( bmp->Header.BitsPerPixel != 8 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_TYPE_MISMATCH;
    }

    
else
    {
        BMP_LAST_ERROR_CODE 
= BMP_OK;

        
/* Row's size is rounded up to the next multiple of 4 bytes */
        bytes_per_row 
= bmp->Header.ImageDataSize / bmp->Header.Height;

        
/* Calculate the location of the relevant pixel */
        pixel 
= bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );

        
*pixel = val;
    }
}


/**************************************************************
    Gets the color value for the specified palette index.
*************************************************************
*/
void BMP_GetPaletteColor( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b )
{
    
if ( bmp == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
    }

    
else if ( bmp->Header.BitsPerPixel != 8 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_TYPE_MISMATCH;
    }

    
else
    {
        
if ( r )    *= *( bmp->Palette + index * 4 + 2 );
        
if ( g )    *= *( bmp->Palette + index * 4 + 1 );
        
if ( b )    *= *( bmp->Palette + index * 4 + 0 );

        BMP_LAST_ERROR_CODE 
= BMP_OK;
    }
}


/**************************************************************
    Sets the color value for the specified palette index.
*************************************************************
*/
void BMP_SetPaletteColor( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b )
{
    
if ( bmp == NULL )
    {
        BMP_LAST_ERROR_CODE 
= BMP_INVALID_ARGUMENT;
    }

    
else if ( bmp->Header.BitsPerPixel != 8 )
    {
        BMP_LAST_ERROR_CODE 
= BMP_TYPE_MISMATCH;
    }

    
else
    {
        
*( bmp->Palette + index * 4 + 2 ) = r;
        
*( bmp->Palette + index * 4 + 1 ) = g;
        
*( bmp->Palette + index * 4 + 0 ) = b;

        BMP_LAST_ERROR_CODE 
= BMP_OK;
    }
}


/**************************************************************
    Returns the last error code.
*************************************************************
*/
BMP_STATUS BMP_GetError()
{
    
return BMP_LAST_ERROR_CODE;
}


/**************************************************************
    Returns a description of the last error code.
*************************************************************
*/
const char* BMP_GetErrorDescription()
{
    
if ( BMP_LAST_ERROR_CODE > 0 && BMP_LAST_ERROR_CODE < BMP_ERROR_NUM )
    {
        
return BMP_ERROR_STRING[ BMP_LAST_ERROR_CODE ];
    }
    
else
    {
        
return NULL;
    }
}





/*********************************** Private methods **********************************/


/**************************************************************
    Reads the BMP file's header into the data structure.
    Returns BMP_OK on success.
*************************************************************
*/
int    ReadHeader( BMP* bmp, FILE* f )
{
    
if ( bmp == NULL || f == NULL )
    {
        
return BMP_INVALID_ARGUMENT;
    }

    
/* The header's fields are read one by one, and converted from the format's
    little endian to the system's native representation. 
*/
    
if ( !ReadUSHORT( &( bmp->Header.Magic ), f ) )            return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.FileSize ), f ) )        return BMP_IO_ERROR;
    
if ( !ReadUSHORT( &( bmp->Header.Reserved1 ), f ) )        return BMP_IO_ERROR;
    
if ( !ReadUSHORT( &( bmp->Header.Reserved2 ), f ) )        return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.DataOffset ), f ) )        return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.HeaderSize ), f ) )        return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.Width ), f ) )            return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.Height ), f ) )            return BMP_IO_ERROR;
    
if ( !ReadUSHORT( &( bmp->Header.Planes ), f ) )        return BMP_IO_ERROR;
    
if ( !ReadUSHORT( &( bmp->Header.BitsPerPixel ), f ) )    return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.CompressionType ), f ) )    return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.ImageDataSize ), f ) )    return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.HPixelsPerMeter ), f ) )    return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.VPixelsPerMeter ), f ) )    return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.ColorsUsed ), f ) )        return BMP_IO_ERROR;
    
if ( !ReadUINT( &( bmp->Header.ColorsRequired ), f ) )    return BMP_IO_ERROR;

    
return BMP_OK;
}


/**************************************************************
    Writes the BMP file's header into the data structure.
    Returns BMP_OK on success.
*************************************************************
*/
int    WriteHeader( BMP* bmp, FILE* f )
{
    
if ( bmp == NULL || f == NULL )
    {
        
return BMP_INVALID_ARGUMENT;
    }

    
/* The header's fields are written one by one, and converted to the format's
    little endian representation. 
*/
    
if ( !WriteUSHORT( bmp->Header.Magic, f ) )            return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.FileSize, f ) )        return BMP_IO_ERROR;
    
if ( !WriteUSHORT( bmp->Header.Reserved1, f ) )        return BMP_IO_ERROR;
    
if ( !WriteUSHORT( bmp->Header.Reserved2, f ) )        return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.DataOffset, f ) )        return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.HeaderSize, f ) )        return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.Width, f ) )            return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.Height, f ) )            return BMP_IO_ERROR;
    
if ( !WriteUSHORT( bmp->Header.Planes, f ) )        return BMP_IO_ERROR;
    
if ( !WriteUSHORT( bmp->Header.BitsPerPixel, f ) )    return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.CompressionType, f ) )    return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.ImageDataSize, f ) )    return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.HPixelsPerMeter, f ) )    return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.VPixelsPerMeter, f ) )    return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.ColorsUsed, f ) )        return BMP_IO_ERROR;
    
if ( !WriteUINT( bmp->Header.ColorsRequired, f ) )    return BMP_IO_ERROR;

    
return BMP_OK;
}


/**************************************************************
    Reads a little-endian unsigned int from the file.
    Returns non-zero on success.
*************************************************************
*/
int    ReadUINT( UINT* x, FILE* f )
{
    UCHAR little[ 
4 ];    /* BMPs use 32 bit ints */

    
if ( x == NULL || f == NULL )
    {
        
return 0;
    }

    
if ( fread( little, 41, f ) != 1 )
    {
        
return 0;
    }

    
*= ( little[ 3 ] << 24 | little[ 2 ] << 16 | little[ 1 ] << 8 | little[ 0 ] );

    
return 1;
}


/**************************************************************
    Reads a little-endian unsigned short int from the file.
    Returns non-zero on success.
*************************************************************
*/
int    ReadUSHORT( USHORT *x, FILE* f )
{
    UCHAR little[ 
2 ];    /* BMPs use 16 bit shorts */

    
if ( x == NULL || f == NULL )
    {
        
return 0;
    }

    
if ( fread( little, 21, f ) != 1 )
    {
        
return 0;
    }

    
*= ( little[ 1 ] << 8 | little[ 0 ] );

    
return 1;
}


/**************************************************************
    Writes a little-endian unsigned int to the file.
    Returns non-zero on success.
*************************************************************
*/
int    WriteUINT( UINT x, FILE* f )
{
    UCHAR little[ 
4 ];    /* BMPs use 32 bit ints */

    little[ 
3 ] = (UCHAR)( ( x & 0xff000000 ) >> 24 );
    little[ 
2 ] = (UCHAR)( ( x & 0x00ff0000 ) >> 16 );
    little[ 
1 ] = (UCHAR)( ( x & 0x0000ff00 ) >> 8 );
    little[ 
0 ] = (UCHAR)( ( x & 0x000000ff ) >> 0 );

    
return ( f && fwrite( little, 41, f ) == 1 );
}


/**************************************************************
    Writes a little-endian unsigned short int to the file.
    Returns non-zero on success.
*************************************************************
*/
int    WriteUSHORT( USHORT x, FILE* f )
{
    UCHAR little[ 
2 ];    /* BMPs use 16 bit shorts */

    little[ 
1 ] = (UCHAR)( ( x & 0xff00 ) >> 8 );
    little[ 
0 ] = (UCHAR)( ( x & 0x00ff ) >> 0 );

    
return ( f && fwrite( little, 21, f ) == 1 );
}

 

 

 

 

 posted on 2009-12-22 00:38  清水湾  阅读(419)  评论(0)    收藏  举报