2010年2月18日 星期四

CuImageLoaderBMP



//

class CuImageLoaderBMP : public IuImageLoaderBMP  
{


public:
    CuImageLoaderBMP();
    virtual ~CuImageLoaderBMP();

    //////////////////////////////////////////////////////////////////
    // IuUnknown 公開虛擬界面 
    virtual ULONG Release();

    //////////////////////////////////////////////////////////////////
    // IuImageLoader 公開虛擬界面 
    virtual BOOL LoadFile(IuImageEx *pImageEx, LPCTSTR lpszResourceName);

    enum BMPFORMAT { BMP1555, BMP565};

    void SetBmpFormat(BMPFORMAT bmpFormat);

private:

    BOOL _Load565Bmp(BYTE * pbits);
    BOOL _Load1555Bmp(BYTE * pbits);


//  BOOL _Load565Bmp16(BYTE * pbits);
    BOOL _Load565Bmp24(BYTE * pbits);


    BOOL _Load1555Bmp24(BYTE * ptr);
    BOOL _Load1555Bmp16(BYTE * ptr);
    BOOL _Load1555Bmp8(BYTE * ptr);

private:

    IuImageEx *m_tempImageEx;

    BMPFORMAT m_bmpFormat;
    BITMAPFILEHEADER m_bmfh;
    BITMAPINFOHEADER *m_pInfo;


};


//


CuImageLoaderBMP::CuImageLoaderBMP()
:m_bmpFormat(BMP1555)
,m_pInfo(NULL)
{

}

CuImageLoaderBMP::~CuImageLoaderBMP()
{
    delete [] m_pInfo;
}

ULONG CuImageLoaderBMP::Release()
{
    delete this;
    return 0;
}

void CuImageLoaderBMP::SetBmpFormat(BMPFORMAT bmpFormat)
{
    m_bmpFormat = bmpFormat;
}


BOOL CuImageLoaderBMP::LoadFile(IuImageEx *pImageEx, LPCTSTR lpszResourceName)
{

    delete [] m_pInfo;
    m_pInfo = NULL;

    m_tempImageEx = pImageEx;

    // 需要 Bits 只支援 24 & 16 BIT bmp 圖
    /////////////////////////////////////////////////////////////////////////////////////////////
//  BITMAPINFOHEADER *pInfo = NULL;
    BYTE *pbits;

    CuFile File; 

    if( !File.Open(lpszResourceName, L"rb") )
    {
        Assert(0, L"CuBitmap::LoadFile /n can't open the file");
        return FALSE;
    }


    DWORD readed;
//  BITMAPFILEHEADER bmfh;


    int size = File.GetFileSize();
    if( size > sizeof(BITMAPFILEHEADER) )
    {

        //ReadFile( hfile, &m_bmfh, sizeof(BITMAPFILEHEADER), &readed, 0 );
        readed = File.Read( &m_bmfh,  sizeof(BITMAPFILEHEADER) );

        if(( readed == sizeof(BITMAPFILEHEADER) ) && ( m_bmfh.bfType == 0x4d42 ))
        {

            m_pInfo = (BITMAPINFOHEADER*)(new BYTE[ size - sizeof(BITMAPFILEHEADER) ]);

            Assert(m_pInfo, L"CuBitmap::LoadFile /n not enough memory.");

            File.Read(  m_pInfo, size - sizeof(BITMAPFILEHEADER) );

            // the pInfo type is BITMAPINFOHEADER, 
            // if pInfo add 1 that mean pInfo jump sizeof(BITMAPINFOHEADER)
            pbits = (BYTE*)(m_pInfo+1);

        }
        else
        {
            return FALSE;
        }


    }

    // use Create allocate memory   
    pImageEx->Create(m_pInfo->biWidth, m_pInfo->biHeight, 16);

//  WORD &biBitCount = m_pInfo->biBitCount;

    BOOL bResult = false;

    switch( m_bmpFormat )
    {
    case BMP1555:
        return _Load1555Bmp(pbits);
        break;
    case BMP565:
        return _Load565Bmp(pbits);
        break;
    
    }

    delete [] m_pInfo;
    m_pInfo = NULL;

    return bResult;

}
BOOL CuImageLoaderBMP::_Load565Bmp(BYTE * pbits)
{
    BOOL bResult = false;

    switch( m_pInfo->biBitCount )
    {
    case 24:
        bResult = this->_Load565Bmp24(pbits);
        break;
    case 16:
//      bResult = this->_Load565Bmp16(pbits);
        break;
    case 8:
//      bResult = this->_Load565Bmp8(pbits);
        break;
    default:
        {
            Assert(0, L"CuBitmap::LoadFile /n biBitCount not support.");
        }
        break;
    }

    return bResult;
}
// 
// BOOL CuImageLoaderBMP::_Load565Bmp16(BYTE * pbits)
// {
//  return FALSE;
// }

BOOL CuImageLoaderBMP::_Load565Bmp24(BYTE * pbits)
{

    int nSrcTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 3;
    int nDescTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;


    // our copy pointer
    WORD *ptr = (WORD *)m_tempImageEx->Data();

    BYTE r, g, b;

    // Convert From BGR To RGB Format And Copy over
    for( long i = 0; i < nSrcTotalByte; i += 3 ) // Loop Through All Of The Pixels
    {

        BYTE* pPixel=&pbits[i];                 // Grab The Current Pixel

        r = pPixel[2];//br;                                 // copy red
        g = pPixel[1];//bg;                                 // copy green
        b = pPixel[0];//bb;                                 // copy blue

        *(ptr++) = (WORD)( ( r >> 3 << 11) | 
            ( g >> 2 << 5) | 
            ( b >> 3 ) );

    }

    return TRUE;

}


BOOL CuImageLoaderBMP::_Load1555Bmp(BYTE * pbits)
{
    BOOL bResult = false;

    switch( m_pInfo->biBitCount )
    {
    case 24:
        bResult = this->_Load1555Bmp24(pbits);
        break;
    case 16:
        bResult = this->_Load1555Bmp16(pbits);
        break;
    case 8:
        bResult = this->_Load1555Bmp8(pbits);
        break;
    default:
        {
            Assert(0, L"CuBitmap::LoadFile /n biBitCount not support.");
        }
        break;
    }

    return bResult;
}

BOOL CuImageLoaderBMP::_Load1555Bmp8(BYTE * pbits)
{
    int nSrcTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height();
    int nDescTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;


    RGBQUAD *pPalette = (RGBQUAD*)(pbits);

    pbits += m_bmfh.bfOffBits - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER);

    // 來源圖 做 4byte 對齊
    int nSrcJumpByte = 4 - (m_tempImageEx->Width() % 4);
    if( nSrcJumpByte == 4 )
        nSrcJumpByte = 0;

    int nDescJumpByte = 2 - ( (m_tempImageEx->Width() ) % 2 );
    if( nDescJumpByte == 2 )
        nDescJumpByte = 0;

//  nDescJumpByte = 1;


    // our copy pointer
    WORD *ptr = (WORD *)m_tempImageEx->Data();//_bits;

//  BYTE r, g, b;

    // Convert From BGR To RGB Format And Copy over
    //for( long i = 0; i < nSrcTotalByte; i += 1 )   // Loop Through All Of The Pixels

    int i = 0;
    for( int nHeight = 0 ; nHeight < m_tempImageEx->Height() ; nHeight += 1 )
    {
        for( int nWidth = 0 ; nWidth < m_tempImageEx->Width() ; nWidth += 1)
        {

            int nColorIndex = pbits[i++];                   // Grab The Current Pixel
            RGBQUAD Color = pPalette[nColorIndex];

            *(ptr++) = (WORD)( ( Color.rgbRed >> 3 << 10) | 
                                ( Color.rgbGreen >> 3 << 5) | 
                                ( Color.rgbBlue >> 3 ) );

        }
        i += nSrcJumpByte; 
        ptr += nDescJumpByte;

    }



    return TRUE;
}


BOOL CuImageLoaderBMP::_Load1555Bmp16(BYTE * pbits)
{

    int nTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;
    BYTE *pData = m_tempImageEx->Data();
    memcpy( pData, pbits, nTotalByte);
    return TRUE;

}

BOOL CuImageLoaderBMP::_Load1555Bmp24(BYTE * pbits)
{

        int nSrcTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 3;
        int nDescTotalByte = m_tempImageEx->Width() * m_tempImageEx->Height() * 2;


        // our copy pointer
        WORD *ptr = (WORD *)m_tempImageEx->Data();

        BYTE r, g, b;

        // Convert From BGR To RGB Format And Copy over
        for( long i = 0; i < nSrcTotalByte; i += 3 ) // Loop Through All Of The Pixels
        {

            BYTE* pPixel=&pbits[i];                 // Grab The Current Pixel
            
            r = pPixel[2];//br;                                 // copy red
            g = pPixel[1];//bg;                                 // copy green
            b = pPixel[0];//bb;                                 // copy blue

            *(ptr++) = (WORD)( ( r >> 3 << 10) | 
                                      ( g >> 3 << 5) | 
                                      ( b >> 3 ) );

        }

    return TRUE;

}


功能複合的太多就會像上面這樣, 整個看起來好像很好用, 但真的要改的時後, 會有點頭大的感覺

沒有留言:

張貼留言