Click here to Skip to main content
15,895,011 members
Articles / Desktop Programming / Win32

RGB to YUV conversion with different chroma sampling using C++,

Rate me:
Please Sign up or sign in to vote.
4.67/5 (15 votes)
10 Jul 2012CPOL4 min read 120.2K   8.7K   49  
RGB to YUV conversion with different chroma sampling using C++.
// BitmapClass.cpp: implementation of the BitmapClass class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "BitmapClass.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

BitmapClass::BitmapClass():
m_pbyPixelData( NULL ),
m_pby32PixelData( NULL )
{
    ZeroMemory( &m_BMPFileHeader, sizeof( BITMAPFILEHEADER ));
    ZeroMemory( &m_BMPInfoHeader, sizeof( BITMAPINFOHEADER ));
}

BitmapClass::~BitmapClass()
{
    delete[] m_pbyPixelData;
}

bool BitmapClass::Open( CString cFilePath_i)
{
    FILE* fp = NULL;
    fp = _wfopen( cFilePath_i, L"rb" );
    if( NULL == fp )
    {
        AfxMessageBox( L"Invalid File ");
        return false;
    }

    if( !ReadBMPFileHeaderInformations( fp ))
    {
        AfxMessageBox( L"Failed to read BMPHeader Informations ");
        return false;
    }

    fseek( fp, 14, 0 ); // size of BITMAPFILEHEADER

    if( !ReadBMPInfoHeaderInformations( fp ))
    {
        AfxMessageBox( L"Failed to read BMPInfoHeader Informations ");
        return false;
    }

    fseek( fp, 0, 0 ); // Seek to origin;
    ReadPixelData( fp );
    //Create32BitData();
    return true;
}

bool BitmapClass::ReadBMPFileHeaderInformations( const void* ptr_i )
{
    FILE* pData = (FILE*)ptr_i;

    int nSeek  = 0;
    // Signature 2Byte Long
    fread( &m_BMPFileHeader.bfType, 2, 1, pData );

    // Total File size 4Byte Long
    fread( &m_BMPFileHeader.bfSize, 4, 1, pData );

    // 2 Reserved field of 2Bytes[ total 4Byte] Long
    fread( &m_BMPFileHeader.bfReserved1, 2, 1, pData );
    fread( &m_BMPFileHeader.bfReserved2, 2, 1, pData );

    // Read the offset to pixel data 4 Bytes Long
    fread( &m_BMPFileHeader.bfOffBits, 4, 1, pData );

    return true;
}

bool BitmapClass::ReadBMPInfoHeaderInformations( const void* ptr_i )
{
    FILE* pData = (FILE*)ptr_i;

    int nSeek  = 0;

    // BMPINFOHEADER structure size 4Byte Long
    fread( &m_BMPInfoHeader.biSize, 4, 1, pData );

    // Image Width 4Byte Long
    fread( &m_BMPInfoHeader.biWidth, 4, 1, pData );

    // Image Height 4Byte Long
    fread( &m_BMPInfoHeader.biHeight, 4, 1, pData );

    // Number of clolr planes 2Byte Long :- Must be set to 1
    fread( &m_BMPInfoHeader.biPlanes, 2, 1, pData );

    // Number of bits per pixel 2Byte Long
    fread( &m_BMPInfoHeader.biBitCount, 2, 1, pData );

    // Compression method 4Byte Long : 0  for BI_RGB is common
    fread( &m_BMPInfoHeader.biCompression, 4, 1, pData );

    // Image Size 4Byte Long
    fread( &m_BMPInfoHeader.biSizeImage, 4, 1, pData );

    // Horizontal resolution 4Byte Long
    fread( &m_BMPInfoHeader.biXPelsPerMeter, 4, 1, pData );

    // Vertical resolution 4Byte Long
    fread( &m_BMPInfoHeader.biYPelsPerMeter, 4, 1, pData );

    // the number of colors in the color palette, or 0 to default to 2 toth power of n,  4Byte Long
    fread( &m_BMPInfoHeader.biClrUsed, 4, 1, pData );

    // the number of important colors used, or 0 when every color is important; generally ignored. 4Byte Long
    fread( &m_BMPInfoHeader.biClrImportant, 4, 1, pData );
    return true;

}

void BitmapClass::ReadPixelData( const void* ptr_i )
{
    FILE* pData = (FILE*)ptr_i;
    fseek( pData, m_BMPFileHeader.bfOffBits, 0 );

    delete[] m_pbyPixelData;
    int nSize = m_BMPInfoHeader.biSizeImage;

    if( 0 == nSize )
    {
        nSize = m_BMPInfoHeader.biWidth * m_BMPInfoHeader.biHeight * m_BMPInfoHeader.biBitCount /8;
    }
    m_pbyPixelData = new byte[nSize];
    ZeroMemory( m_pbyPixelData, nSize );

    fread( m_pbyPixelData, nSize, 1, pData );

    /*FILE* Fp = NULL;
    Fp = fopen( "c:\\test.bin", "wb" );
    fwrite( m_pbyPixelData, nSize, 1, Fp );
    fclose( Fp );*/
}

void BitmapClass::Create32BitData()
{
    delete[] m_pby32PixelData;
    int nMultiple = 8;

    switch( m_BMPInfoHeader.biBitCount )
    {
        case 32:
            nMultiple = 0;
            break;

        case 24:
            nMultiple = 8;
            break;

        case 16:
            nMultiple = 16;
            break;

        case  8:
            nMultiple = 24;
            break;
    }

    int nSize = m_BMPInfoHeader.biSizeImage * nMultiple;
    if( 0 == nSize )
    {
        nSize = m_BMPInfoHeader.biWidth * m_BMPInfoHeader.biHeight * nMultiple;
    }

    m_pby32PixelData = new byte[nSize];
    ZeroMemory( m_pby32PixelData, nSize );

    int nOutCount = 0;
    for( int nHeight = m_BMPInfoHeader.biHeight; nHeight > 0; nHeight-- )
    {
        nOutCount= (m_BMPInfoHeader.biHeight - nHeight ) * m_BMPInfoHeader.biWidth * 4;
        int nCount = ( nHeight * m_BMPInfoHeader.biWidth * 3 );
        for( int nWidth = 0 ; nWidth <  m_BMPInfoHeader.biWidth; nWidth += 3 )
        {
            m_pby32PixelData[nOutCount++] = m_pbyPixelData[nCount++];
            m_pby32PixelData[nOutCount++] = m_pbyPixelData[nCount++];
            m_pby32PixelData[nOutCount++] = m_pbyPixelData[nCount++];
            m_pby32PixelData[nOutCount++] = 0;
        }
    }
}

void BitmapClass::Draw( HWND hwnd, int nXStart_i, int nYStart_i, int nWidth_i, int nHeight_i )
{

    RECT Rect; // just a simple rect to hold the size of our window

    HDC hdc = ::GetDC( hwnd ); 

    if( 0 == m_BMPInfoHeader.biHeight )
    {
        m_BMPInfoHeader.biPlanes = 1;
        m_BMPInfoHeader.biSize = sizeof(m_BMPInfoHeader); // size of this struct
        m_BMPInfoHeader.biHeight = nHeight_i - 3;
        m_BMPInfoHeader.biWidth  = nWidth_i - 3;
        m_BMPInfoHeader.biBitCount = 24;
        m_BMPInfoHeader.biCompression = BI_RGB;

        delete[] m_pbyPixelData;
        int nSize = m_BMPInfoHeader.biWidth * m_BMPInfoHeader.biHeight * m_BMPInfoHeader.biBitCount/8;
        m_pbyPixelData = new byte[nSize];
        memset( m_pbyPixelData, 100, nSize );
    }
    BITMAPINFO biBitMapInfo; // We set this up to grab what we want
    biBitMapInfo.bmiHeader = m_BMPInfoHeader;

    HDC iDC = CreateCompatibleDC(0); // create dc to store the image

    HBITMAP iBitmap = CreateDIBSection( iDC, &biBitMapInfo, DIB_RGB_COLORS, 0, 0, 0); // create a dib section for the dc
    SelectObject(iDC, iBitmap); // assign the dib section to the dc

    SetDIBitsToDevice( iDC, 0, 0, biBitMapInfo.bmiHeader.biWidth, biBitMapInfo.bmiHeader.biHeight,
                       0, 0, 0, biBitMapInfo.bmiHeader.biHeight, &m_pbyPixelData[0], &biBitMapInfo,
                       DIB_RGB_COLORS); // set the new dibs to the dc

  //  if((( nWidth_i - 3)  < biBitMapInfo.bmiHeader.biWidth ) ||
    //   (( nHeight_i - 3 ) < biBitMapInfo.bmiHeader.biHeight ))
    {
       // StretchBlt( hdc, 0, 0, nWidth_i - 3, nHeight_i - 3, iDC, 0, 0,
              //  biBitMapInfo.bmiHeader.biWidth, biBitMapInfo.bmiHeader.biHeight, SRCCOPY );
    }
   // else
    {
        BitBlt( hdc, nXStart_i, nYStart_i, nWidth_i - 3, nHeight_i + 3, iDC, 0, 0, SRCCOPY); // copy hdc to their hdc
    }

    DeleteDC( iDC ); // delete dc
    DeleteObject( iBitmap ); // delete object
    ::ReleaseDC( hwnd, hdc );
}

void BitmapClass::ResetDisplay( HWND hwnd, int nXStart_i, int nYStart_i, int nWidth_i, int nHeight_i )
{
    m_BMPInfoHeader.biHeight = 0;
    Draw( hwnd, nXStart_i, nYStart_i, nWidth_i, nHeight_i );
}

void BitmapClass::CreateBitmap( const byte* ptr_i, int& nWidth_i, int& nHeight_i, IMAGE_TYPE eImageType_i )
{
    delete[] m_pbyPixelData;
    int nBitCount = 0;

    if( BMP_24 == eImageType_i )
    {
        m_BMPInfoHeader.biCompression = BI_RGB;
        nBitCount = 3;
    }
    else if( BMP_32 == eImageType_i )
    {
       // m_BMPInfoHeader.biCompression = BI_RGBA;
        nBitCount = 4;
    }

    int nSize = nWidth_i * nHeight_i * nBitCount;

    m_pbyPixelData = new byte[nSize];
    ZeroMemory( m_pbyPixelData, nSize );

    memcpy( m_pbyPixelData, ptr_i, nSize );

    m_BMPInfoHeader.biPlanes = 1;
    m_BMPInfoHeader.biSize = sizeof(m_BMPInfoHeader); // size of this struct
    m_BMPInfoHeader.biHeight = nHeight_i;
    m_BMPInfoHeader.biWidth  = nWidth_i;
    m_BMPInfoHeader.biBitCount = nBitCount * 8;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions