A solution I got from a different thread has opened Pandora's Box for me. Now I'm going crazy trying to figure out a problem I'm having.

I have struggled to understand bitmaps for quite some time. Until now, I have heavily relied on MFC to do all the bitmap details, but now I want to understand more of what is happening. Specifically, I would like to create a function that loads a bitmap from a file using only C++ and the standard template library. Yes, I am aware this is reinventing the wheel, but until I understand what is happening with the load process, I will never be happy using code from another person or agency. I have tried finding this on the internet and through FAQs but have had marginal success in the process. If there is a place I should be looking, I would appreciate a pointer in the right direction.

The current version of the function I have is as follows. Its aim is to load the bitmap and then pass it to a CBitmap object. I am aware that CBitmap is used by MFC, but until I get this version to work, I will be hesitant to take further steps away from MFC.

Code:
// in CDynamicBitmapCreationDlg.h
class FileObject
{
    FILE* m_pFile;
    public:
        FileObject( FILE *pFile ) : m_pFile( pFile ) {}
        ~FileObject() { if (m_pFile) fclose(m_pFile); }
};


// in CDynamicBitmapCreationDlg.cpp
int CDynamicBitmapCreationDlg::load_bitmap_from_file(char* file, CBitmap* p_newbitmap)
{
	if(!p_newbitmap)
	{
		MessageBox("Error location 0");
		return 0;
	}

	//First we open the file the binary mode
    FILE* in = fopen(file,"rb");
	FileObject fObject( in );

	//Next we read the BITMAPFILEHEAR. . .
	BITMAPFILEHEADER bmfh;
	size_t result = fread(&bmfh,sizeof(BITMAPFILEHEADER),1,in);
	if(result < 1)
	{
		MessageBox("Error location 1");
		return 0;
	}

	if(bmfh.bfType != 19778)
	{
		MessageBox("Error location 2");
		return 0;
	}

	//Then the BITMAPINFOHEADER. . .
	BITMAPINFOHEADER bmih;
	result = fread(&bmih,sizeof(BITMAPINFOHEADER),1,in);
	if(result < 1)
	{
		MessageBox("Error location 3");
		return 0;
	}

	//Next comes the palette	
	std::vector<RGBQUAD> colors;

	//set the number of colours
	int number_of_colors = 1 << bmih.biBitCount;

	//load the palette if the bitmap has less than 24 bits per pixel
	if(bmih.biBitCount < 24)
	{
		colors.resize(number_of_colors);
		result = fread(&colors[0], sizeof(RGBQUAD), number_of_colors,in);
		if(result < number_of_colors)
		{
			MessageBox("Error location 4");
			return 0;
		}
	}

	//Now we read in the pixel data
	DWORD data_size = bmfh.bfSize - bmfh.bfOffBits;

	std::vector<BYTE> p_initialdata(data_size);
	result = fread(&p_initialdata[0],sizeof(BYTE),data_size,in);
	if(result < data_size)
	{
		MessageBox("Error location 6");
		return 0;
	}

	//The data has been read.  First, check if padding is needed

	//byteWidth is the width of the actual image in bytes
	//padWidth is the width of the image plus the extra padding
	LONG width_in_bytes = 0;
	LONG width_plus_padding = 0;
 
	width_in_bytes = width_plus_padding = (LONG)((float)bmih.biWidth*(float)bmih.biBitCount/8.0);
 
	//add any extra space to bring each line to a DWORD boundary
	while(width_plus_padding % 4 != 0) 
	{
	   width_plus_padding++;
	}

	//Second, we transfer the data from the temporary buffer to the final buffer,
	// adjusting for padding and inversion, if necessary

	DWORD actual_size;
	int offset;
 
	//set diff to the actual image size(no padding)
	actual_size = bmih.biHeight * width_in_bytes;
	//allocate memory for the image

	BYTE* p_finaldata = new BYTE[actual_size];
	if(bmih.biHeight > 0) 
	{
		// The bitmap is inverted, so we'll need to reverse the image and remove the padding

	    int j = data_size - 3;
	    offset = width_plus_padding - width_in_bytes;
	    for( int i = 0 ; i < data_size ; i += 3 ) 
		{
	        if( (i+offset) % width_plus_padding == 0 ) 
			{
	            i += offset;
	        }
			*(p_finaldata + j + 2) = p_initialdata[i];
			*(p_finaldata + j + 1) = p_initialdata[i + 1];
			*(p_finaldata + j) = p_initialdata[i + 2];
	        j -= 3;
	    }
	}
	else 
	{
		// The bitmap is not inverted.  We only need to remove the padding

		LONG height = bmih.biHeight * -1;
	    offset = 0;
	    do 
		{
	        memcpy((p_finaldata+(offset*width_in_bytes)),(&p_initialdata[0] + (offset*width_plus_padding)),width_in_bytes);
	        offset++;
	    } while(offset < height);
	}


/****************************************/
/* I BELIEVE THE PROBLEM IS HERE SOMEWHERE */
/****************************************/

	//Here we begin to construct the BITMAP object
	BITMAP bmp;
	bmp.bmBitsPixel = bmih.biBitCount;
	bmp.bmHeight = bmih.biHeight;
	bmp.bmWidth = bmih.biWidth;
	bmp.bmType = 0; 
	bmp.bmWidthBytes = width_in_bytes;
	bmp.bmPlanes = bmih.biPlanes;
	bmp.bmBits = p_finaldata;

	if((p_newbitmap->CreateBitmapIndirect(&bmp)) == 0)
	{
		delete [] p_finaldata;
		MessageBox("Error location 8");
		return 0;
	}

	return 1;
}
As far as I know, the bitmap data is properly handled up until the BITMAP structure is filled in. The problem, I think, is with CreateBitmapIndirect. When I run it, the 'if' statement does not trigger, but the bitmap still doesn't show up in my dialog. I can load the same bitmap from file using LoadImage and it appears in the dialog, so I know that part works. Here is how the two implementations look in CDynamicBitmapDialog::OnInitDialog():

Code:
// THIS WORKS
m_bitmap = (HBITMAP)::LoadImage(0 ,_T("C:\\4by4bitmap.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION );
MainImage.ModifyStyle(0,SS_BITMAP);
if(m_bitmap)
	MainImage.SetBitmap(m_bitmap);
versus. . .

Code:
// THIS DOES NOT WORK
CBitmap temp_bitmap;
load_bitmap_from_file(_T("C:\\4by4bitmap.bmp"),&temp_bitmap);
m_bitmap = (HBITMAP)temp_bitmap;
MainImage.ModifyStyle(0,SS_BITMAP);
if(m_bitmap)
	MainImage.SetBitmap(m_bitmap);
(I comment out one method while I test the other)

I have tried SetBitmapBits and that also does nothing.

I would be very grateful to anyone able to help. I always try to leave good reputation feedback.

The bitmap in question can be found here: http://www.codeguru.com/forum/showthread.php?t=514930