Solved

Show Image on screen from Byte data!!

Posted on 2003-12-02
10
527 Views
Last Modified: 2007-12-19
Hello,
      I have image data in byte stream format.Now i don't know how to show them on screen or window?I had tried it to first convert it into bitmap format.but i don't want to do like this way.Is there any other way to show them on window without loosing any color information.It is 16-bit and 8- bit type image data.For any type of format it is welcome.
I just want the way.Does any body show me the correct path??I will be really very greateful to you...
  I am making MFC Dialog base application.
0
Comment
Question by:pmukti
10 Comments
 
LVL 13

Accepted Solution

by:
SteH earned 125 total points
ID: 9857406
Could you tell us why you don't want to convert the data to a bitmap first? Showing a bitmap, or another image format, has the advantage that redrawing is done automatically when the window was hidden and comes back to front.

Did you have problems with loosing color information? This sounds more like the screen color depth is not suited for the color information of the data you got.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9858051
Check out MFC FIRE sample. This sample shows 8 bpp palette image on the screen. Image is generated as memory array and drawn on the screen using device-independent bitmap (DIB).
If you need to show monochrome 8 bits per pixels image, use monocrome palette: (0, 0, 0) ... (255, 255, 255).
The only way to show 16 bpp grayscale images in Windows is converting them to 8 bpp. This may be done by simple way (using only high 8 bits of each pixel) or applying some optimization. For example, if 16 bpp image contains pixels in interval from 3000 to 4000, only this interval may be mapped to 0-255 interval.
0
 

Author Comment

by:pmukti
ID: 9866164
Thanx for your interest.

I have no problem to convert the data into bitmap but the color information should not be lose. The way i do is first i put one by one pixel color information from buffer to device context by setpixel method.which will slow down the process for large file size.so do u have any otherway to show the image data on device context?

I had seen the MFC Fire sample.but in that i am not getting from where it is taking the image data color information.
whether it is taking from palette array or from image buffer.Do you have any other simple example by that i can know it better.


0
 
LVL 13

Expert Comment

by:SteH
ID: 9866272
Why do you think to loose color information? What type of bitmap do you use?

A poblem could be the mapping of colors from your data (file/DIB/etc) to display. To display 8bit greyscale images you need at least 24 bits color depth for the display. All 3 colors are identical so 8 bit would be sufficient but when the graphics card uses a 16 bit color depth you have 5/6/5 bits per color. And that is not sufficient for displaying your data. So I guess your color information is lost only during displaying. It will stay correct in the bitmap/DIB but can't be displayed correctly.

But to give better help you need to tell us the color depth setting of the display and the type of image data. 8bit could be 256 colors or 256 greyscales. And a snippet of code could be very helpful as well.


And for 16bit greyscales
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:pmukti
ID: 9872575
I am not getting this point ->what type of bitmap do you use?

May be you are right.here I tell you my actual problem.I have one camera source which give me 8 bit grayscale buffer and unfortunetaly 14-bit gray scale buffer.when i get 8 bit grayscale buffer.i can handle it and display it succesfully on the screen. but when the case come with 14-bit i am not able to display it in correct manner.even i am not able to make succesfull bmp from that data buffer.I had tried by many ways but not succeeded in this.i had search many topics on net about 16 bit grayscale bitmap information.but not get proper information.even i am not sure about whether i had made the perfact bmp file from data buffer and only problem is in displaying it on screen which is due to color depth of card or monitor.here i am providing you as much i am knowing.i am using normal 17'' IBM monitor and used graphics card modal number is ASUS V9280 S2 super fast 600 Mhz.I am not sure whether it is supperting colordepth of 16  bit.
              if you know much detail about all these please explain it breifly to me.I am a simple programmer and i don't have more knowledge on this.if you have some good link on these.give it to me.I want to know more about this.

CCDiaImage::WriteBMP(BYTE *imgData, CString FileName)
{

      HANDLE hFile;
      BITMAPFILEHEADER bmpfHeader;
      PBITMAPINFO pbmpInfo;  
      DWORD dwtotImgData;


      // Create the .BMP file.
      //_T("C:\\testbmp.bmp"
      hFile = CreateFile(FileName,
                           GENERIC_READ | GENERIC_WRITE,
                           (DWORD) 0,
                              NULL,
                           CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,
                           (HANDLE) NULL);
      bmpfHeader.bfReserved1=0;
      bmpfHeader.bfReserved2=0;

      // Compute the offset to the array of color indices.
      if(MaxImgByte==1){//this is for 8-bit image
            bmpfHeader.bfOffBits =(DWORD) (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+(256*sizeof(RGBQUAD)) );
      }
      else{//this is for 16-bit image
            bmpfHeader.bfOffBits =(DWORD) (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
      }
      bmpfHeader.bfType=0x4d42;       // 0x42 = "B" 0x4d = "M"

      // Compute the size of the entire file.
      //pbih->biSizeImage =imageWidth*imageHeight*(BitsPerPixel/8)
      bmpfHeader.bfSize = (DWORD) ((512*512*MaxImgByte)+ bmpfHeader.bfOffBits);

      //first write BMPFILEHEADER
      // Copy the BITMAPFILEHEADER into the .BMP file.
      DWORD dwbytret;

      if (!WriteFile(hFile,(LPVOID) &bmpfHeader,sizeof(BITMAPFILEHEADER),(LPDWORD) &dwbytret,  NULL))
      {
            MessageBox(_T("Can't write BMPFileHeader into File"));
      }

      pbmpInfo=CreateBitmapInfoStruct();

      if (MaxImgByte==1){//this is for 8-Bit image
            for(int i=0;i<=255;i++){
                  pbmpInfo->bmiColors[i].rgbBlue=i;
                  pbmpInfo->bmiColors[i].rgbRed=i;
                  pbmpInfo->bmiColors[i].rgbGreen=i;
                  pbmpInfo->bmiColors[i].rgbReserved=0;
            }
      }
      else{//this is for 16-Bit Image
            pbmpInfo->bmiColors[0].rgbBlue=0;
            pbmpInfo->bmiColors[0].rgbRed=0;
            pbmpInfo->bmiColors[0].rgbGreen=0;
            pbmpInfo->bmiColors[0].rgbReserved=0;
      }
      pbmpInfo->bmiHeader.biXPelsPerMeter=0;
      pbmpInfo->bmiHeader.biYPelsPerMeter=0;
      //pbi->bmiHeader=pbih;  
      // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
      //secondly write BMPINFOHEADER
      if (MaxImgByte==1){//this is for 8-Bit image
            if (!WriteFile(hFile, (LPVOID) pbmpInfo, sizeof(BITMAPINFOHEADER) +(256*sizeof(RGBQUAD)) ,
                                (LPDWORD) &dwbytret, ( NULL)))
            {
                  MessageBox(_T("error in writing BMP fileinformation Header"));
            }
      }
      else
      {//this is for 16-Bit Image
            if (!WriteFile(hFile, (LPVOID) pbmpInfo, sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) ,
                                (LPDWORD) &dwbytret, ( NULL)))
            {
                  MessageBox(_T("error in writing BMP fileinformation Header"));
            }
      }
      //BYTE *tmp_ptr=(BYTE *)malloc(pbmpInfo->bmiHeader.biSizeImage);
      //memcpy(tmp_ptr,imgData,pbmpInfo->bmiHeader.biSizeImage);
      dwtotImgData=pbmpInfo->bmiHeader.biSizeImage;

      //manupulate image data
      //hp=byte_data;
      if(MaxImgByte!=1){ //i.e 16-Bit BMP file
            BYTE *tmp_ptr=(BYTE *)malloc(dwtotImgData);
            short rpart,gpart,bpart;
            short tot16bit;
            for(int i=dwtotImgData-2;i>0;i-=2){
                  /*this i have done it for all the 6 bit
                  so i am getting white color instead of gray color
                  */
                  gpart=imgData[i+1]&63;
                  rpart=(gpart<<9);
                  bpart=gpart&31;
                  gpart=gpart<<5;
                  
                  /* this is just for trial to make the image gray color but not working!!!
                  gpart=imgData[i+1]&15;
                  rpart=(gpart<<9);
                  bpart=gpart&7;
                  gpart=gpart<<5;
                  */

                  tot16bit=rpart|gpart|bpart;
                  tmp_ptr[(dwtotImgData)-i]=tot16bit&65280>>8;//|bpart|gpart);//&32767;
                  rpart=imgData[i]&31;
                  tmp_ptr[(dwtotImgData)-(i+1)]=tot16bit&255;//|bpart|gpart);//&32767;
                  //img_ptr[i]=img_ptr[i];
                  //newUPart;//|
            }
            memcpy(imgData,tmp_ptr,dwtotImgData);
            free(tmp_ptr);
      }
      
      //Thirdly write ImgData
      if (!WriteFile(hFile, imgData,  dwtotImgData, (LPDWORD) &dwbytret,NULL))
      {
            MessageBox(_T("write image data Error"));
      }

      if(!CloseHandle(hFile)){
            MessageBox(_T("Error in Closing .BMP File"));
      }
      
      //MessageBox(_T("SuccessFully Copy Image File"));
      
}





 
0
 
LVL 3

Expert Comment

by:RJSoft
ID: 9874980
SetDIBits

RJ
0
 
LVL 49

Assisted Solution

by:DanRollins
DanRollins earned 125 total points
ID: 9879286
I have never heard of a 14-bit grayscale image.  Do you have any documentation about this?

If each 14-bit value is a simple intensity level, then maybe it can be converted to a 8-bit value without losing much information.  To do that, take each 14-bit value and shift it right by 6 and then pretend that you got an 8-bit value.

But if the grayscale values are palette indexes, then there is much work to do.  Does the image data provide a palette that contains about 16,000 entries?

Anyway, the first step would be to try treating the values as 8-bit grayscale.  Here is how I would do this:

1) Add a STATIC control to the dialog.  Set its ID to IDST_MyPicture and type to "Bitmap"
2) Press Ctrl+W and in the Variables tabl, select IDST_MyPicture
3) Click [Add variable] and set Name to "m_ctlMyPicture" and  Category to "Control"

Now in your program, if you have an HBITMAP you can quickly an easily display it by using:
     m_ctlMyPicture.SetBitmap( hbmp );

So all that is left to do is create the HBITMAP.  As a first step, use code like this:

void CD19Dlg::OnButton1()
{
      int nWide= 100;
      int nHigh= 100;
   
      HDC     hdcWnd=  ::GetWindowDC( m_hWnd );
      HBITMAP hbmDest= ::CreateCompatibleBitmap( hdcWnd, nWide, nHigh );
      HDC     hdcMem=  ::CreateCompatibleDC( hdcWnd );   // match screen settings
      
      // testing: here's how to load a bitmap from a resource
      // HINSTANCE hInst = AfxGetInstanceHandle();
      // hbmDest= LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_Test) );
      
      HBITMAP hbmOld=  (HBITMAP)SelectObject ( hdcMem, hbmDest ); // will draw on hbmDest

      for (int y=0; y<nHigh; y++ ) {
            for (int x=0; x<nWide; x++ ) {
                  UINT nValueFromGrayScaleArray= 0x2F21; // whatever??? get a 14-bit value
                  UINT nLevel= nValueFromGrayScaleArray >> 6; // discard lo bits of level
                  ::SetPixel( hdcMem, x,y, RGB(nLevel,nLevel,nLevel ) );
            }
      }
      SelectObject( hdcMem, hbmOld ); // put the old bmp back before cleanup

      ::ReleaseDC( m_hWnd, hdcWnd );
      ::DeleteDC( hdcMem );

      m_ctlMyPicture.SetBitmap( hbmDest );  // display the bitmap in the static control
}

=-==-=-=-=-=-=-=-=-=-
In the above code, I could not show how to process the 14-bit pixel stream... I just set all pixels to the same value.  You will need to get the grayscale image data, one pixel at a time and use SetPixel as shown.

When you get that that, I can show you how to speed it up by placing pixel data directly into a DIBSection.

-- Dan
0
 
LVL 13

Expert Comment

by:SteH
ID: 9881257
Quote from MSDN:

[quote]
16 The bitmap has a maximum of 2^16 colors. If the biCompression member of the BITMAPINFOHEADER is BI_RGB, the bmiColors member is NULL. Each WORD in the bitmap array represents a single pixel. The relative intensities of red, green, and blue are represented with 5 bits for each color component. The value for blue is in the least significant 5 bits, followed by 5 bits each for green and red. The most significant bit is not used. The bmiColors color table is used for optimizing colors used on palette-based devices, and must contain the number of entries specified by the biClrUsed member of the BITMAPINFOHEADER.  
[/quote]

So this assumes a 16 bit COLOR image. You have 14bit grayscale. Thus it will appear completly different after loading since for a 16 bit image windows uses bits 0-4 for blue, 5-9 for green and 10-14 for red. Which is not the case for you. Some programs support 16bit grayscales. Perhaps you can decipher how this changes the header when writing to file.

If you use the 16bit bitmap as defined you only have 5 bits left since all colors are the same. This leaves you with less resolution than a 8 bit grayscale image.

If you use it in your own way be sure to remember it is your very own format windows won't handle correctly for you.

Andnow comes the problem for displaying. A 24bit color depth of the monitor allows to show 8bit grayscales and not more. The rest can be used internally for image analysis but won't be displayed anyhow. Perhaps you make your choice whether you really need the 14bit mode at all.
0
 
LVL 5

Expert Comment

by:migoEX
ID: 10331467
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Split between SteH and DanRollins.

Please leave any comments here within the next four days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

migoEX
EE Cleanup Volunteer
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

707 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now