Display 8bit image data in a window

Hi All,

I need to display some data in the View of an MFC application.

The data i have has come from a camera and is 8 bit data with each bit representing one grey scale pixel value.

I'm having problems display the data at the moment.  With the code i have the image is the correct size but the image within it seems to repeat itself four times.

My current solution involves trying to create a CBitmap object out of the data using CreateCompatibleBitmap and SetBitmapBits.

I have very little experience of palettes and CBitmaps so any help would be appreciated.

This is the code I currently have in OnDraw:  (pImage->GetData returns the raw data)

ImageData* pImage = pDoc->GetImage();

CDC dcMem;

CBitmap bitmap;
bitmap.CreateCompatibleBitmap(pDC, pImage->GetWidth(), pImage->GetHeight());
bitmap.SetBitmapBits(pImage->GetNumberOfBytes(), pImage->GetData());
CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap);
pDC->BitBlt(0, 0, pImage->GetWidth(), pImage->GetHeight(), &dcMem, 0, 0,SRCCOPY);

Maybe i need to do something with the palette?

Who is Participating?
mahesh1402Connect With a Mentor Commented:
It seems you have 8 bit 'Raw' data obtained from camera..I will suggest you to convert this 8-bit data to bitmap using code something like following :

// Allocate bitmap header structure
BITMAPINFO * BMI = (BITMAPINFO*)new unsigned char[sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 256)];

// Fill the greyscale palette
for (int GenPal = 0; GenPal < 256; GenPal++)
    *(int*)(&BMI->bmiColors[GenPal]) = GenPal * 0x10101;

// Fill in some information about the image we'll be creating
BMI->bmiHeader.biSize = sizeof(BMI->bmiHeader);
BMI->bmiHeader.biWidth = 128;   // here specify image width
BMI->bmiHeader.biHeight = 128; // here specify image height
BMI->bmiHeader.biPlanes = 1;
BMI->bmiHeader.biBitCount = 8;
BMI->bmiHeader.biCompression = BI_RGB;
BMI->bmiHeader.biXPelsPerMeter = 0;
BMI->bmiHeader.biYPelsPerMeter = 0;
BMI->bmiHeader.biClrUsed = 256;
BMI->bmiHeader.biClrImportant = 256;

// Get the DWord aligned scanline width
int ScanLine = (BMI->bmiHeader.biWidth + 3) & 0xFFFFFFFC;

// Fill in the image data size in the header
BMI->bmiHeader.biSizeImage = ScanLine * BMI->bmiHeader.biHeight;

// Create a New DC
HDC DrawDC = CreateCompatibleDC(NULL);

unsigned char * DataPtr; // <===== This is the pointer to the raw image data

// Create a new DIBSection
HBITMAP DrawBMP = CreateDIBSection(DrawDC, BMI, DIB_RGB_COLORS, (void**)&DataPtr, NULL, NULL);

// Select DIBSection into DC
HBITMAP OldBMP = (HBITMAP)SelectObject(DrawDC, DrawBMP);

if (OldBMP != NULL) { // Write image data (You would just copy your data in here)
    for (int DoY = 0; DoY < BMI->bmiHeader.biHeight; DoY++)
        for (int DoX = 0; DoX < BMI->bmiHeader.biWidth; DoX++)
            DataPtr[(DoY * ScanLine) + DoX] = DoX + DoY;

    // Draw the image to the screen (Assuming "hdc" holds the device context of your viewport)
    BitBlt(hdc, 0, 0, BMI->bmiHeader.biWidth,  BMI->bmiHeader.biHeight, DrawDC, 0, 0, SRCCOPY);

    // De-select DIBSection from the DC
    SelectObject(DrawDC, OldBMP);
// Clean up GDI objects

// Clean up header structure
delete BMI;

Hope this helps
you can also use SetDIBitsToDevice for this purpose

   LPBITMAPINFO bitinfo;
    unsigned char image[ImgHeight][ImgWidth];
    FILE *fp;

    fp = fopen("hands.raw", "rb");  // open raw file.. this is your 8 bit raw file received from camera
    if( fp == NULL ) return;

    bitinfo = (LPBITMAPINFO)new char[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];
    bitinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitinfo->bmiHeader.biWidth = ImgWidth;
    bitinfo->bmiHeader.biHeight = ImgHeight;
    bitinfo->bmiHeader.biPlanes = 1;
    bitinfo->bmiHeader.biBitCount = 8;                  
    bitinfo->bmiHeader.biCompression = BI_RGB;
    bitinfo->bmiHeader.biSizeImage = 0;
    bitinfo->bmiHeader.biXPelsPerMeter = 0;
    bitinfo->bmiHeader.biYPelsPerMeter = 0;
    bitinfo->bmiHeader.biClrUsed = 256;
    bitinfo->bmiHeader.biClrImportant = 256;

    // gray palette
    for(int i = 0; i < 256; i++)
      bitinfo->bmiColors[i].rgbRed = char(i);
      bitinfo->bmiColors[i].rgbBlue = char(i);
      bitinfo->bmiColors[i].rgbGreen = char(i);
      bitinfo->bmiColors[i].rgbReserved = 0;

    for( int i=0; i<ImgHeight; i++)
        fread( image[i], 1, ImgWidth, fp );

// Create DC goes here

    ::SetDIBitsToDevice( hDC,0,0,ImgWidth,ImgHeight,0,0, 0,ImgHeight,image,bitinfo, DIB_RGB_COLORS);

    fclose( fp );
    delete[] bitinfo;
NOTE : If the width of a scanline is not divisible by 4, you must change the code to pad each line.  refer prev src code for ScanLIne calculation

othewise if you dont want to go as above simply :

1) Get *.raw filesize [file_size]

2) Create an array unsigned char* lpBits = new unsigned char[file_size];

3) Read the data from the file to lpBits

4) Create CBitmap from this data:
    CBitmap bm;
    bm.CreateBitmap( width, height, 1, 8, lpBits ); // you should know width height of raw image, and bits-per-pixel=8

5) Initialize PictureHolder with this bitmap:

6) Display bitmap:

7) Clean up:
    delete [] lpBits;

spforemanAuthor Commented:
Thanks for the help MAHESH

All three solutions were spot on.

I had spent a day trying to do this and was so close.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.