/* bmp_io.c 31 May 2000 */ #include "stdafx.h" #include #include #include "bmp_io.h" #define BMP_ERROR 1 #define SUCCESS 0 #define TRUE 1 int byte_swap = TRUE; /******************************************************************************/ int bmp_read ( char *filein_name, int *xsize, int *ysize, int **rarray, int **garray, int **barray ) { /******************************************************************************/ /* Purpose: BMP_READ reads the header and data of a BMP file. Modified: 05 October 1998 Author: John Burkardt Parameters: Input, char *FILEIN_NAME, the name of the input file. Output, int *XSIZE, *YSIZE, the X and Y dimensions of the image. Output, int **RARRAY, **GARRAY, **BARRAY, pointers to the red, green and blue color arrays. */ FILE *filein; int numbytes; int psize; int result; /* Open the input file. */ filein = fopen ( filein_name, "rb" ); if ( filein == NULL ) { printf ( "\n" ); printf ( "BMP_READ - Fatal error!\n" ); printf ( " Could not open the input file.\n" ); return BMP_ERROR; } /* Read the header. */ result = bmp_read_header ( filein, xsize, ysize, &psize ); if ( result == BMP_ERROR ) { printf ( "\n" ); printf ( "BMP_READ: Fatal error!\n" ); printf ( " BMP_READ_HEADER failed.\n" ); return BMP_ERROR; } /* Read the palette. */ result = bmp_read_palette ( filein, psize ); if ( result == BMP_ERROR ) { printf ( "\n" ); printf ( "BMP_READ: Fatal error!\n" ); printf ( " BMP_READ_PALETTE failed.\n" ); return BMP_ERROR; } /* Allocate storage. */ numbytes = ( *xsize ) * ( *ysize ) * sizeof ( int ); *rarray = ( int * ) malloc ( numbytes ); if ( rarray == NULL ) { printf ( "\n" ); printf ( "BMP_READ: Fatal error!\n" ); printf ( " Could not allocate data storage.\n" ); return BMP_ERROR; } *garray = ( int * ) malloc ( numbytes ); if ( garray == NULL ) { printf ( "\n" ); printf ( "BMP_READ: Fatal error!\n" ); printf ( " Could not allocate data storage.\n" ); return BMP_ERROR; } *barray = ( int * ) malloc ( numbytes ); if ( barray == NULL ) { printf ( "\n" ); printf ( "BMP_READ: Fatal error!\n" ); printf ( " Could not allocate data storage.\n" ); return BMP_ERROR; } /* Read the data. */ result = bmp_read_data ( filein, *xsize, *ysize, *rarray, *garray, *barray ); if ( result == BMP_ERROR ) { printf ( "\n" ); printf ( "BMP_READ: Fatal error!\n" ); printf ( " BMP_READ_DATA failed.\n" ); return BMP_ERROR; } /* Close the file. */ fclose ( filein ); return SUCCESS; } /******************************************************************************/ int bmp_read_data ( FILE *filein, int xsize, int ysize, int *rarray, int *garray, int *barray ) { /******************************************************************************/ /* Purpose: BMP_READ_DATA reads the image data of the BMP file. Discussion: On output, the RGB information in the file has been copied into the R, G and B arrays. Thanks to Peter Kionga-Kamau for pointing out an error in the previous implementation. Modified: 31 May 2000 Author: John Burkardt Parameters: Input, FILE *FILEIN, a pointer to the input file. Input, int XSIZE, YSIZE, the X and Y dimensions of the image. Input, int *RARRAY, *GARRAY, *BARRAY, pointers to the red, green and blue color arrays. */ int i; int *indexb; int *indexg; int *indexr; int j; int numbyte; indexr = rarray; indexg = garray; indexb = barray; numbyte = 0; for ( j = 0; j < ysize; j++ ) { for ( i = 0; i < xsize; i++ ) { *indexg = fgetc ( filein ); if ( *indexg == EOF ) { printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); return BMP_ERROR; } numbyte = numbyte + 1; indexg = indexg + 1; *indexr = fgetc ( filein ); if ( *indexr == EOF ) { printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); return BMP_ERROR; } numbyte = numbyte + 1; indexr = indexr + 1; *indexb = fgetc ( filein ); if ( *indexb == EOF ) { printf ( "BMP_READ_DATA: Failed reading data byte %d.\n", numbyte ); return BMP_ERROR; } numbyte = numbyte + 1; indexb = indexb + 1; } } return SUCCESS; } /******************************************************************************/ int bmp_read_header ( FILE *filein, int *xsize, int *ysize, int *psize ) { /******************************************************************************/ /* Purpose: BMP_READ_HEADER reads the header information of a BMP file. Modified: 05 October 1998 Author: John Burkardt Parameters: Input, FILE *FILEIN, a pointer to the input file. Output, int *XSIZE, *YSIZE, the X and Y dimensions of the image. Output, int *PSIZE, the number of colors in the palette. */ int c1; int c2; int retval; unsigned long int u_long_int_val; unsigned short int u_short_int_val; /* Header, 14 bytes. 16 bytes FileType; Magic number: "BM", 32 bytes FileSize; Size of file in 32 byte integers, 16 bytes Reserved1; Always 0, 16 bytes Reserved2; Always 0, 32 bytes BitmapOffset. Starting position of image data, in bytes. */ c1 = fgetc ( filein ); if ( c1 == EOF ) { return BMP_ERROR; } c2 = fgetc ( filein ); if ( c2 == EOF ) { return BMP_ERROR; } if ( c1 != 'B' || c2 != 'M' ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_short_int ( &u_short_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_short_int ( &u_short_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } /* The bitmap header is 40 bytes long. 32 bytes unsigned Size; Size of this header, in bytes. 32 bytes Width; Image width, in pixels. 32 bytes Height; Image height, in pixels. (Pos/Neg, origin at bottom, top) 16 bytes Planes; Number of color planes (always 1). 16 bytes BitsPerPixel; 1 to 24. 1, 4, 8 and 24 legal. 16 and 32 on Win95. 32 bytes unsigned Compression; 0, uncompressed; 1, 8 bit RLE; 2, 4 bit RLE; 3, bitfields. 32 bytes unsigned SizeOfBitmap; Size of bitmap in bytes. (0 if uncompressed). 32 bytes HorzResolution; Pixels per meter. (Can be zero) 32 bytes VertResolution; Pixels per meter. (Can be zero) 32 bytes unsigned ColorsUsed; Number of colors in palette. (Can be zero). 32 bytes unsigned ColorsImportant. Minimum number of important colors. (Can be zero). */ retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } *xsize = ( int ) u_long_int_val; retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } *ysize = ( int ) u_long_int_val; retval = read_u_short_int ( &u_short_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_short_int ( &u_short_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } *psize = ( int ) u_long_int_val; retval = read_u_long_int ( &u_long_int_val, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } return SUCCESS; } /******************************************************************************/ int bmp_read_palette ( FILE *filein, int psize ) { /******************************************************************************/ /* Purpose: BMP_READ_PALETTE reads the palette information of a BMP file. Note: There are PSIZE colors listed. For each color, the values of (B,G,R,A) are listed, where A is a quantity reserved for future use. Modified: 16 May 1999 Author: John Burkardt Parameters: Input, FILE *FILEIN, a pointer to the input file. Input, int PSIZE, the number of colors in the palette. */ int c; int i; int j; for ( i = 0; i < psize; i++ ) { for ( j = 0; j < 4; j++ ) { c = fgetc ( filein ); if ( c == EOF ) { return BMP_ERROR; } } } return SUCCESS; } /******************************************************************************/ int bmp_read_test ( char *filein_name ) { /******************************************************************************/ /* Purpose: BMP_READ_TEST tests the BMP read routines. Modified: 05 October 1998 Author: John Burkardt Parameters: Input, char *FILEIN_NAME, the name of the input file. */ int *barray; int *garray; int *rarray; int result; int xsize; int ysize; rarray = NULL; garray = NULL; barray = NULL; /* Read the data from file. */ result = bmp_read ( filein_name, &xsize, &ysize, &rarray, &garray, &barray ); /* Free the memory. */ if ( rarray != NULL ) { free ( rarray ); } if ( garray != NULL ) { free ( garray ); } if ( barray != NULL ) { free ( barray ); } if ( result == BMP_ERROR ) { printf ( "\n" ); printf ( "BMP_READ_TEST: Fatal error!\n" ); printf ( " BMP_READ failed.\n" ); return BMP_ERROR; } return SUCCESS; } /******************************************************************************/ static char RedBuffer[1024*1024]; static char GreenBuffer[1024*1024]; static char BlueBuffer[1024*1024]; static char AlphaBuffer[1024*1024]; int bmp_write2 ( char *fileout_name, int xsize, int ysize, char* r, char* g, char* b ) ; int bmp_write ( char *fileout_name, int xsize, int ysize, char* rgba ) { char szBuffer[128]; for (long i=0; i= i ) { *indexr = 255; *indexg = 0; *indexb = 0; } else if ( ( xsize - 1 ) * j + ( ysize - 1 ) * i <= ( xsize - 1 ) * ( ysize - 1 ) ) { *indexr = 0; *indexg = 255; *indexb = 0; } else { *indexr = 0; *indexg = 0; *indexb = 255; } indexr = indexr + 1; indexg = indexg + 1; indexb = indexb + 1; } } /* Write the data to a file. */ // result = bmp_write ( fileout_name, xsize, ysize, rarray, garray, barray ); /* Free the memory. */ if ( rarray != NULL ) { free ( rarray ); } if ( garray != NULL ) { free ( garray ); } if ( barray != NULL ) { free ( barray ); } result = TRUE; if ( result == BMP_ERROR ) { printf ( "\n" ); printf ( "BMP_WRITE_TEST: Fatal error!\n" ); printf ( " BMP_WRITE failed.\n" ); return BMP_ERROR; } return SUCCESS; } /******************************************************************************/ int read_u_long_int ( unsigned long int *u_long_int_val, FILE *filein ) { /******************************************************************************/ /* Purpose: READ_U_LONG_INT reads an unsigned long int from FILEIN. Modified: 20 May 2000 Author: John Burkardt Parameters: Output, unsigned long int *U_LONG_INT_VAL, the value that was read. Input, FILE *FILEIN, a pointer to the input file. */ int retval; unsigned short int u_short_int_val_hi; unsigned short int u_short_int_val_lo; if ( byte_swap == TRUE ) { retval = read_u_short_int ( &u_short_int_val_lo, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_short_int ( &u_short_int_val_hi, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } } else { retval = read_u_short_int ( &u_short_int_val_hi, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } retval = read_u_short_int ( &u_short_int_val_lo, filein ); if ( retval == BMP_ERROR ) { return BMP_ERROR; } } /* Acknowledgement: A correction to the following line was supplied by Peter Kionga-Kamau, 20 May 2000. */ *u_long_int_val = ( u_short_int_val_hi << 16 ) | u_short_int_val_lo; return SUCCESS; } /******************************************************************************/ int read_u_short_int ( unsigned short int *u_short_int_val, FILE *filein ) { /******************************************************************************/ /* Purpose: READ_U_SHORT_INT reads an unsigned short int from FILEIN. Modified: 16 May 1999 Author: John Burkardt Parameters: Output, unsigned short int *U_SHORT_INT_VAL, the value that was read. Input, FILE *FILEIN, a pointer to the input file. */ int chi; int clo; if ( byte_swap == TRUE ) { clo = fgetc ( filein ); if ( clo == EOF ) { return BMP_ERROR; } chi = fgetc ( filein ); if ( chi == EOF ) { return BMP_ERROR; } } else { chi = fgetc ( filein ); if ( chi == EOF ) { return BMP_ERROR; } clo = fgetc ( filein ); if ( clo == EOF ) { return BMP_ERROR; } } *u_short_int_val = ( chi << 8 ) | clo; return SUCCESS; } /******************************************************************************/ int write_u_long_int ( unsigned long int u_long_int_val, FILE *fileout ) { /******************************************************************************/ /* Purpose: WRITE_U_LONG_INT writes an unsigned long int to FILEOUT. Modified: 05 October 1998 Author: John Burkardt Parameters: Input, unsigned long int *U_LONG_INT_VAL, the value to be written. Input, FILE *FILEOUT, a pointer to the output file. */ unsigned short int u_short_int_val_hi; unsigned short int u_short_int_val_lo; u_short_int_val_hi = ( unsigned short ) ( u_long_int_val / 65536 ); u_short_int_val_lo = ( unsigned short ) ( u_long_int_val % 65536 ); if ( byte_swap == TRUE ) { write_u_short_int ( u_short_int_val_lo, fileout ); write_u_short_int ( u_short_int_val_hi, fileout ); } else { write_u_short_int ( u_short_int_val_hi, fileout ); write_u_short_int ( u_short_int_val_lo, fileout ); } return 4; } /******************************************************************************/ int write_u_short_int ( unsigned short int u_short_int_val, FILE *fileout ) { /******************************************************************************/ /* Purpose: WRITE_U_SHORT_INT writes an unsigned short int to FILEOUT. Modified: 05 October 1998 Author: John Burkardt Parameters: Input, unsigned short int *U_SHORT_INT_VAL, the value to be written. Input, FILE *FILEOUT, a pointer to the output file. */ unsigned char chi; unsigned char clo; chi = ( unsigned char ) ( u_short_int_val / 256 ); clo = ( unsigned char ) ( u_short_int_val % 256 ); if ( byte_swap == TRUE ) { fputc ( clo, fileout ); fputc ( chi, fileout ); } else { fputc ( chi, fileout ); fputc ( clo, fileout ); } return 2; }