从文件c ++加载后绘制位图

时间:2013-06-03 02:31:01

标签: c++ bitmap bmp

我刚刚阅读了一个从文件中加载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;

}

有人可以举例说明如何以这种方式加载到屏幕上。

任何帮助都将不胜感激。

0 个答案:

没有答案