dolphin/Source/Plugins/Plugin_VideoDX9/Src/bmp_io.cpp
2008-12-08 05:25:12 +00:00

1039 lines
23 KiB
C++

/* bmp_io.c 31 May 2000 */
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#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<xsize*ysize;i++)
{
RedBuffer[i] = rgba[i*4+0];
GreenBuffer[i] = rgba[i*4+1];
BlueBuffer[i] = rgba[i*4+2];
AlphaBuffer[i] = rgba[i*4+3];
}
sprintf(szBuffer,"%s.bmp", fileout_name);
bmp_write2(szBuffer, xsize, ysize, (char*)RedBuffer, (char*)GreenBuffer, (char*)BlueBuffer);
// sprintf(szBuffer,"%sm.bmp", fileout_name);
// bmp_write2(szBuffer, xsize, ysize, (char*)AlphaBuffer, (char*)AlphaBuffer, (char*)AlphaBuffer);
return 0;
}
int bmp_write2 ( char *fileout_name, int xsize, int ysize, char* r, char* g, char* b )
{
/******************************************************************************/
/*
Purpose:
BMP_WRITE writes the header and data for a BMP file.
Modified:
02 October 1998
Author:
John Burkardt
Parameters:
Input, char *FILEOUT_NAME, the name of the output 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.
*/
FILE *fileout;
int result;
/*
Open the output file.
*/
fileout = fopen ( fileout_name, "wb" );
if ( fileout == NULL ) {
printf ( "\n" );
printf ( "BMP_WRITE - Fatal error!\n" );
printf ( " Could not open the output file.\n" );
return BMP_ERROR;
}
/*
Write the header.
*/
result = bmp_write_header ( fileout, xsize, ysize );
if ( result == BMP_ERROR ) {
printf ( "\n" );
printf ( "BMP_WRITE: Fatal error!\n" );
printf ( " BMP_WRITE_HEADER failed.\n" );
return BMP_ERROR;
}
/*
Write the data.
*/
result = bmp_write_data ( fileout, xsize, ysize, (char*)r, (char*)g, (char*)b);
if ( result == BMP_ERROR ) {
printf ( "\n" );
printf ( "BMP_WRITE: Fatal error!\n" );
printf ( " BMP_WRITE_DATA failed.\n" );
return BMP_ERROR;
}
/*
Close the file.
*/
fclose ( fileout );
return SUCCESS;
}
/******************************************************************************/
int bmp_write_data ( FILE *fileout, int xsize, int ysize, char *rarray,
char *garray, char *barray ) {
/******************************************************************************/
/*
Purpose:
BMP_WRITE_DATA writes the image data to the BMP file.
Modified:
02 October 1998
Author:
John Burkardt
Parameters:
Input, FILE *FILEOUT, a pointer to the output 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.
*/
long i;
char *indexb;
char *indexg;
char *indexr;
long j;
indexr = rarray;
indexg = garray;
indexb = barray;
for ( j = 0; j < ysize; j++ ) {
for ( i = 0; i < xsize; i++ ) {
fputc ( *indexg, fileout );
fputc ( *indexr, fileout );
fputc ( *indexb, fileout );
indexr = indexr + 1;
indexg = indexg + 1;
indexb = indexb + 1;
}
}
return SUCCESS;
}
/******************************************************************************/
int bmp_write_header ( FILE *fileout, int xsize, int ysize ) {
/******************************************************************************/
/*
Purpose:
BMP_WRITE_HEADER writes the header information to a BMP file.
Modified:
02 October 1998
Author:
John Burkardt
Parameters:
Input, FILE *FILEOUT, a pointer to the output file.
Input, int XSIZE, YSIZE, the X and Y dimensions of the image.
*/
int i;
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 bytes,
16 bytes Reserved1; Always 0,
16 bytes Reserved2; Always 0,
32 bytes BitmapOffset. Starting position of image data, in bytes.
*/
fputc ( 'B', fileout );
fputc ( 'M', fileout );
u_long_int_val = 3 * xsize * ysize + 54;
write_u_long_int ( u_long_int_val, fileout );
u_short_int_val = 0;
write_u_short_int ( u_short_int_val, fileout );
u_short_int_val = 0;
write_u_short_int ( u_short_int_val, fileout );
u_long_int_val = 54;
write_u_long_int ( u_long_int_val, fileout );
/*
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).
*/
u_long_int_val = 40;
write_u_long_int ( u_long_int_val, fileout );
write_u_long_int ( xsize, fileout );
write_u_long_int ( ysize, fileout );
u_short_int_val = 1;
write_u_short_int ( u_short_int_val, fileout );
u_short_int_val = 24;
write_u_short_int ( u_short_int_val, fileout );
for ( i = 0; i <= 6; i++ ) {
u_long_int_val = 0;
write_u_long_int ( u_long_int_val, fileout );
}
return SUCCESS;
}
/******************************************************************************/
int bmp_write_test ( char *fileout_name ) {
/******************************************************************************/
/*
Purpose:
BMP_WRITE_TEST tests the BMP write routines.
Modified:
02 October 1998
Author:
John Burkardt
Parameters:
Input, char *FILEOUT_NAME, the name of the output file.
*/
int *barray;
int *garray;
int i;
int *indexb;
int *indexg;
int *indexr;
int j;
int j2;
int numbytes;
int *rarray;
int result;
int xsize;
int ysize;
xsize = 200;
ysize = 200;
/*
Allocate the memory.
*/
rarray = NULL;
garray = NULL;
barray = NULL;
numbytes = xsize * ysize * sizeof ( int );
rarray = ( int * ) malloc ( numbytes );
if ( rarray == NULL ) {
printf ( "\n" );
printf ( "BMP_WRITE_TEST: Fatal error!\n" );
printf ( " Unable to allocate memory for data.\n" );
return BMP_ERROR;
}
garray = ( int * ) malloc ( numbytes );
if ( garray == NULL ) {
printf ( "\n" );
printf ( "BMP_WRITE_TEST: Fatal error!\n" );
printf ( " Unable to allocate memory for data.\n" );
return BMP_ERROR;
}
barray = ( int * ) malloc ( numbytes );
if ( barray == NULL ) {
printf ( "\n" );
printf ( "BMP_WRITE_TEST: Fatal error!\n" );
printf ( " Unable to allocate memory for data.\n" );
return BMP_ERROR;
}
/*
Set the data.
Note that BMP files go from "bottom" up, so we'll reverse the
sense of "J" here to get what we want.
*/
indexr = rarray;
indexg = garray;
indexb = barray;
for ( j2 = 0; j2 < ysize; j2++ ) {
j = ysize - j2;
for ( i = 0; i < xsize; i++ ) {
if ( j >= 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;
}