这是个很古老的问题,因为游戏编程常常需要载入bmp图像到屏幕中,虽然对位图的载入函数有很多版本,但是大体操作都一样,会用到一般的文件操作如open,read,wirte,seek。而在VS2005中,编译这种带lseek的函数,常常出现如下错误对话框:
图1断言错误
下面是《游戏脚本高级编程》的载入bmp位图的函数版本:
/**************************************************************************************
*
* W_LoadImage ()
*
* Loads a BMP file to a Wrappuh image.
*/
bool W_LoadImage ( char * pstrBMPFilename, W_Image * Image )
{
HFILE hFile;
OFSTRUCT FileData;
BITMAPFILEHEADER BMPFileHeader;
BITMAPINFOHEADER BMPImageHeader;
if ( ( hFile = OpenFile ( pstrBMPFilename, & FileData, OF_READ ) ) == -1 )
return FALSE;
_lread ( hFile, & BMPFileHeader, sizeof ( BITMAPFILEHEADER ) );
if ( BMPFileHeader.bfType != 0x4D42 )
{
_lclose ( hFile );
return FALSE;
}
_lread ( hFile, & BMPImageHeader, sizeof ( BITMAPINFOHEADER ) );
if ( BMPImageHeader.biBitCount != 24 )
{
_lclose ( hFile );
return FALSE;
}
int iScanlineByteSize = BMPImageHeader.biWidth * 3;
GetNextMul4 ( iScanlineByteSize );
int iScanlinePad = iScanlineByteSize - ( BMPImageHeader.biWidth * 3 );
int iBMPFileImageByteSize = ( BMPImageHeader.biWidth * 3 + iScanlinePad ) * BMPImageHeader.biHeight;
_lseek ( hFile, BMPFileHeader.bfOffBits, SEEK_SET );
UCHAR * pImageBuffer = NULL;
if ( ! ( pImageBuffer = ( UCHAR * ) malloc ( iBMPFileImageByteSize ) ) )
{
_lclose ( hFile );
return FALSE;
}
_lread ( hFile, pImageBuffer, iBMPFileImageByteSize );
int iCurrSourcePixelOffs = 0;
RGBTriad CurrSourcePixelTriad;
InitWin32Struct ( g_DDSrfcDesc );
g_DDSrfcDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT;
int iXRes = BMPImageHeader.biWidth;
GetNextMul4 ( iXRes );
g_DDSrfcDesc.dwWidth = iXRes;
g_DDSrfcDesc.dwHeight = BMPImageHeader.biHeight;
switch ( g_VideoContext.iColorDepth )
{
case 15:
{
g_DDSrfcDesc.ddckCKSrcBlt.dwColorSpaceLowValue = DEF_IMAGE_MASK_COLOR_15;
g_DDSrfcDesc.ddckCKSrcBlt.dwColorSpaceHighValue = DEF_IMAGE_MASK_COLOR_15;
break;
}
case 16:
{
g_DDSrfcDesc.ddckCKSrcBlt.dwColorSpaceLowValue = DEF_IMAGE_MASK_COLOR_16;
g_DDSrfcDesc.ddckCKSrcBlt.dwColorSpaceHighValue = DEF_IMAGE_MASK_COLOR_16;
break;
}
case 32:
{
g_DDSrfcDesc.ddckCKSrcBlt.dwColorSpaceLowValue = DEF_IMAGE_MASK_COLOR_32;
g_DDSrfcDesc.ddckCKSrcBlt.dwColorSpaceHighValue = DEF_IMAGE_MASK_COLOR_32;
break;
}
}
Image->iXRes = BMPImageHeader.biWidth;
Image->iYRes = g_DDSrfcDesc.dwHeight;
Image->iXMax = Image->iXRes - 1;
Image->iYMax = Image->iYRes - 1;
g_DDSrfcDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
if ( FAILED ( g_pDDIntrfc4->CreateSurface ( & g_DDSrfcDesc, & Image->pDDSrfc, NULL ) ) )
return FALSE;
InitWin32Struct ( g_DDSrfcDesc );
if ( FAILED ( Image->pDDSrfc->Lock ( NULL, & g_DDSrfcDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ) ) )
return FALSE;
Image->iPitch = g_DDSrfcDesc.lPitch;
Pixel15 * pSrfcBuffer15 = ( Pixel15 * ) g_DDSrfcDesc.lpSurface;
Pixel16 * pSrfcBuffer16 = ( Pixel16 * ) g_DDSrfcDesc.lpSurface;
Pixel32 * pSrfcBuffer32 = ( Pixel32 * ) g_DDSrfcDesc.lpSurface;
int iX,
iY;
for ( iY = BMPImageHeader.biHeight - 1; iY >= 0; -- iY )
{
for ( iX = 0; iX < BMPImageHeader.biWidth; ++ iX )
{
CurrSourcePixelTriad.R = pImageBuffer [ iCurrSourcePixelOffs + 2 ];
CurrSourcePixelTriad.G = pImageBuffer [ iCurrSourcePixelOffs + 1 ];
CurrSourcePixelTriad.B = pImageBuffer [ iCurrSourcePixelOffs ];
if ( EncodePixel32 ( CurrSourcePixelTriad.R, CurrSourcePixelTriad.G, CurrSourcePixelTriad.B ) == DEF_IMAGE_MASK_COLOR_32 )
{
switch ( g_VideoContext.iColorDepth )
{
case 15:
pSrfcBuffer15 [ iY * ( g_DDSrfcDesc.lPitch >> 1 ) + iX ] = ( Pixel15 ) DEF_IMAGE_MASK_COLOR_15;
break;
case 16:
pSrfcBuffer16 [ iY * ( g_DDSrfcDesc.lPitch >> 1 ) + iX ] = ( Pixel16 ) DEF_IMAGE_MASK_COLOR_16;
break;
case 32:
pSrfcBuffer32 [ iY * ( g_DDSrfcDesc.lPitch >> 2 ) + iX ] = ( Pixel32 ) DEF_IMAGE_MASK_COLOR_32;
break;
}
}
else
{
switch ( g_VideoContext.iColorDepth )
{
case 15:
CurrSourcePixelTriad.R >>= 3;
CurrSourcePixelTriad.G >>= 3;
CurrSourcePixelTriad.B >>= 3;
pSrfcBuffer15 [ iY * ( g_DDSrfcDesc.lPitch >> 1 ) + iX ] = ( Pixel15 ) EncodePixel15 ( CurrSourcePixelTriad.R, CurrSourcePixelTriad.G, CurrSourcePixelTriad.B );
break;
case 16:
CurrSourcePixelTriad.R >>= 3;
CurrSourcePixelTriad.G >>= 3;
CurrSourcePixelTriad.B >>= 3;
pSrfcBuffer16 [ iY * ( g_DDSrfcDesc.lPitch >> 1 ) + iX ] = ( Pixel16 ) EncodePixel16 ( CurrSourcePixelTriad.R, CurrSourcePixelTriad.G, CurrSourcePixelTriad.B );
break;
case 32:
pSrfcBuffer32 [ iY * ( g_DDSrfcDesc.lPitch >> 2 ) + iX ] = ( Pixel32 ) EncodePixel32 ( CurrSourcePixelTriad.R, CurrSourcePixelTriad.G, CurrSourcePixelTriad.B );
break;
}
}
iCurrSourcePixelOffs += 3;
}
iCurrSourcePixelOffs += iScanlinePad;
}
int iClipFound;
W_Rect ClipRect;
ClipRect.iX0 = 0;
ClipRect.iY0 = 0;
ClipRect.iX1 = Image->iXMax;
ClipRect.iY1 = Image->iYMax;