我刚刚阅读了一个从文件中加载bmp图像的教程。它包括从文件加载bmp图像以及将位图数据转换为RGB数组,保存位图以及将RGB数据转换为可保存的bmp数据。不幸的是,它没有提到在加载它们之后将它们绘制到屏幕上的任何事情,这就是我需要弄清楚如何做的事情。
BYTE* Sprite2::LoadBMP(int* width, int* height, long* size, LPCTSTR bmpfile )
{
BITMAPFILEHEADER bmpheader;
BITMAPINFOHEADER bmpinfo;
DWORD bytesread;
HANDLE file = CreateFile(bmpfile,GENERIC_READ, FILE_SHARE_READ,
0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
if(0 == file)
return 0;
if(ReadFile ( file, &bmpheader, sizeof( BITMAPFILEHEADER),
&bytesread, 0 ) == false )
{
CloseHandle (file );
return 0;
}
if( ReadFile ( file, &bmpinfo, sizeof ( BITMAPINFOHEADER ),
&bytesread, 0 ) == false )
{
CloseHandle ( file );
return 0;
}
if( bmpheader.bfType != 'MB' )
{
CloseHandle( file );
return 0;
}
if( bmpinfo.biCompression != BI_RGB )
{
CloseHandle( file );
return 0;
}
if( bmpinfo.biBitCount != 24 )
{
CloseHandle( file );
return 0;
}
*width = bmpinfo.biWidth;
*height = abs (bmpinfo.biHeight);
*size = bmpheader.bfSize - bmpheader.bfOffBits;
BYTE* Buffer = new BYTE[ *size ];
SetFilePointer ( file, bmpheader.bfOffBits, 0, FILE_BEGIN );
if( ReadFile (file, Buffer, *size, &bytesread, 0 ) == false)
{
delete [] Buffer;
CloseHandle( file );
return 0;
}
CloseHandle( file );
return Buffer;
}
BYTE* Sprite2::ConvertBMPToRGBBuffer(BYTE* Buffer, int width, int height)
{
if ( ( 0 == Buffer ) || ( width == 0 ) || ( height == 0 ) )
return 0;
int padding = 0;
int scanlinebytes = width * 3;
while ( ( scanlinebytes + padding ) % 4 != 0 )
padding++;
int psw = scanlinebytes + padding;
BYTE* newbuff = new BYTE[width*height*3];
long bufpos = 0;
long newpos = 0;
for(int y = 0; y < height; ++y)
for(int x = 0; x < 3 * width; x += 3 )
{
newpos = y * 3 * width + x;
bufpos = ( height - y - 1 ) * psw + x;
newbuff[newpos] = Buffer[bufpos + 2];
newbuff[newpos + 1] = Buffer[bufpos + 1];
newbuff[newpos + 2] = Buffer[bufpos];
}
return newbuff;
}
bool Sprite2::SaveBMP( BYTE* Buffer, int width, int height, long paddedsize, LPCSTR bmpfile)
{
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER info;
memset ( &bmfh, 0, sizeof (BITMAPFILEHEADER ) );
memset ( &info, 0, sizeof (BITMAPINFOHEADER ) );
bmfh.bfType = 0x4d42;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfSize = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) + paddedsize;
bmfh.bfOffBits = 0x36;
info.biSize = sizeof(BITMAPINFOHEADER);
info.biWidth = width;
info.biHeight = height;
info.biPlanes = 1;
info.biBitCount = 24;
info.biCompression = BI_RGB;
info.biSizeImage = 0;
info.biXPelsPerMeter = 0x0ec4;
info.biYPelsPerMeter = 0x0ec4;
info.biClrUsed = 0;
info.biClrImportant = 0;
HANDLE file = CreateFile (bmpfile, GENERIC_WRITE, FILE_SHARE_READ,
0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if( 0 == file )
{
CloseHandle ( file );
return false;
}
unsigned long bwritten;
if(WriteFile ( file, &bmfh, sizeof ( BITMAPFILEHEADER ),
&bwritten, 0 ) == false)
{
CloseHandle ( file );
return false;
}
if(WriteFile ( file, &info, sizeof( BITMAPINFOHEADER ),
&bwritten, 0 ) == false )
{
CloseHandle ( file );
return false;
}
if(WriteFile ( file, Buffer, paddedsize, &bwritten, 0 ) == false )
{
CloseHandle ( file );
return false;
}
CloseHandle ( file );
return true;
}
BYTE* Sprite2::ConvertRGBToBMPBuffer( BYTE* Buffer, int width, int height, long* newsize )
{
if ( ( NULL == Buffer ) || ( width == 0 ) || ( height == 0 ) )
return NULL;
int padding = 0;
int scanlinebytes = width * 3;
while ( ( scanlinebytes + padding ) % 4 != 0 )
padding++;
int psw = scanlinebytes + padding;
*newsize = height * psw;
BYTE* newbuf = new BYTE[*newsize];
memset ( newbuf, 0, *newsize );
long bufpos = 0;
long newpos = 0;
for ( int y = 0; y < height; y++ )
for ( int x = 0; x < 3 * width; x+=3 )
{
bufpos = y * 3 * width + x; // position in original buffer
newpos = ( height - y - 1 ) * psw + x; // position in padded buffer
newbuf[newpos] = Buffer[bufpos+2]; // swap r and b
newbuf[newpos + 1] = Buffer[bufpos + 1]; // g stays
newbuf[newpos + 2] = Buffer[bufpos]; // swap b and r
}
return newbuf;
}
有人可以举例说明如何以这种方式加载到屏幕上。
任何帮助都将不胜感激。