Solved

Display 8bit image data in a window

Posted on 2006-07-21
4
411 Views
Last Modified: 2013-11-20
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;
dcMem.CreateCompatibleDC(pDC);

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);
dcMem.SelectObject(pOldBitmap);

Maybe i need to do something with the palette?

Thanks
0
Comment
Question by:spforeman
  • 3
4 Comments
 
LVL 22

Accepted Solution

by:
mahesh1402 earned 500 total points
ID: 17152599
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
DeleteObject(DrawBMP);
DeleteDC(DrawDC);

// Clean up header structure
delete BMI;

Hope this helps
-MAHESH
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17152667
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

-MAHESH
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17153931
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:
    CPictureHolder::CreateFromBitmap((HBITMAP)bm);

6) Display bitmap:
    CPictureHolder::Render(...);

7) Clean up:
    delete [] lpBits;

-MAHESH
0
 

Author Comment

by:spforeman
ID: 17154490
Thanks for the help MAHESH

All three solutions were spot on.

I had spent a day trying to do this and was so close.
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Expand data scrubbing tool 13 35
ASCII Non-Printable characters/codes and their HTML equivalents 6 130
Path of Workbook 3 86
Excel file not created as expected 7 79
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question