Results 1 to 19 of 19

Thread: Stupid question about GetDIBits [resolved]

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662

    Stupid question about GetDIBits [resolved]

    I'm sure a similar question has been asked, but I wasn't able to find the answer to it. I'm trying to write a function similar to BitBlt in vc++ and I need to perform some calculations on each pixel of the Source DC. I breifly thought of using SetPixel but then realized that using a Dib would definitly be much faster (you directly modify the pixels in an array).

    Anyway, long story short, I'm new to c++. If a function is returning an array, how do I set up the buffer for that array? The size of the Dib may vary, therefore I need to dynamically create the array based on the dimensions of the image being modified.

    Do I need to allocate the entire array before calling the function, or will the function reallocate my array so the data will fit? Should the array be two dimensions or one?

    BTW, my native toungue in VB6.
    Last edited by agent; Jul 29th, 2003 at 11:28 PM.

  2. #2
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Dynamic arrays should be one-dimensional. For allocating, use new[]. And functions should never reallocate arrays, so the caller should allocate enough.

    What are you writing the function for?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    i'm writing a userinterface graphics function for use with a vb app. big project that involves mounting a computer in my car with some map software on it. custom ui for the computer for use with a touch screen adater...

  4. #4
    Hyperactive Member
    Join Date
    Sep 2001
    Posts
    396
    Here's 2 functions which wraps about GetDibBits() and SetDibBits()

    Code:
    pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight)
    {
      BITMAPINFO bi;
      BOOL bRes;
      pBGR buf;
    
      bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
      bi.bmiHeader.biWidth = nWidth;
      bi.bmiHeader.biHeight = - nHeight;
      bi.bmiHeader.biPlanes = 1;
      bi.bmiHeader.biBitCount = 32;
      bi.bmiHeader.biCompression = BI_RGB;
      bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
      bi.bmiHeader.biClrUsed = 0;
      bi.bmiHeader.biClrImportant = 0;
    
    //  buf = new sBGR[nWidth * nHeight];
      buf = (pBGR) malloc(nWidth * 4 * nHeight);
    
      bRes = GetDIBits(hdc, hBmp, 0, nHeight, buf, &bi, DIB_RGB_COLORS);
      if (!bRes) {
    //    delete [] buf;
        free(buf);
        buf = 0;
      }
      return buf;
    }
    Note:Please remember to delete the pointer away at the end of your program.

    Code:
    int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf)
    {
      BITMAPINFO bi;
    
      bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
      bi.bmiHeader.biWidth = nWidth ;
      bi.bmiHeader.biHeight = - nHeight ;
      bi.bmiHeader.biPlanes = 1;
      bi.bmiHeader.biBitCount = 32;
      bi.bmiHeader.biCompression = BI_RGB;
      bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
      bi.bmiHeader.biClrUsed = 0;
      bi.bmiHeader.biClrImportant = 0;
    
      return ( SetDIBits(hdc , hBmp ,0, nHeight ,buf,&bi,DIB_RGB_COLORS) );
    
    }

    This is the structure they uses (note they are incompatible with COLORREF)

    Code:
    // The Representation of a 32 bit color table entry
    #pragma pack(push)
    #pragma pack(1)
    typedef struct ssBGR {
      unsigned char b;
      unsigned char g;
      unsigned char r;
      unsigned char pad;
    } sBGR;
    
    typedef sBGR *pBGR;
    #pragma pack(pop)
    An example of how to use the array. The code below converts the pixels to greyscale

    Code:
    for(int y=0;y<height;++y)
    {
      for(int x=0;x<width;++x)
      {
        sBGR temp_col=pDIBbits[y * width+x];
    
        int OrigRed  =(int)(temp_col.r);
        int OrigGreen=(int)(temp_col.g);
        int OrigBlue =(int)(temp_col.b);
    
        OrigRed  =(int) ( (float)(OrigRed) * 0.299);
        OrigGreen=(int) ( (float)(OrigGreen) * 0.587);
        OrigBlue =(int)  ( (float)(OrigBlue) * 0.114);
            
        int Grey=OrigRed+OrigGreen+OrigBlue;
    
        if(Grey>255) Grey=255;
    
        sBGR tempBGR;
        tempBGR.r=Grey;
        tempBGR.g=Grey;
        tempBGR.b=Grey;
    
        pDIBbits[y * width+x]=tempBGR;
      }
    }

  5. #5
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    What's the problem with the BitBlt API?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  6. #6
    Hyperactive Member
    Join Date
    Sep 2001
    Posts
    396
    Originally posted by CornedBee
    What's the problem with the BitBlt API?
    Originally posted by agent

    ...and I need to perform some calculations on each pixel of the Source DC. I breifly thought of using SetPixel but then realized that using a Dib would definitly be much faster (you directly modify the pixels in an array).

  7. #7
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Oh, sorry.

    But isn't that a waste? Unless you are combining source and target somehow, wouldn't it be better to modify the image first and then simply blit it? Or if you are combining, have you looked if the blit modes satisfy your needs? Or maybe other blitting functions (e.g. AlphaBlend)?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    i'm combining the images using an 8-bit alphamask. here's the prototype so you can understand it a bit better.
    Code:
    BOOL AlphaBlit(
    HDC hDcDest,     //Destination (i.e. the Screen)
    int ix,          //Location on the Destination to blit
    int iy,
    int iWidth       //Size of blit
    int iHeight
    HDC hDcSource    //Source image
    HDC hDcMask      //Source image's mask (8-bits)
    DWORD dwRasterop //See bitblt
    );
    It will act similarly to BitBlt except that it combines the Destination and the Source using the Mask before using BitBlt to blit it to the Destination using the specified raster operation.

  9. #9
    Hyperactive Member
    Join Date
    Sep 2001
    Posts
    396
    FYI, there is a AlphaBlend Windows API. Have you taken a look at it?

  10. #10

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    the info i have on alphablend is that it does not support alphamasks. if you have any updated info on the function let me know where you got it from. otherwise, i'm happy to write the function myself

  11. #11
    Hyperactive Member
    Join Date
    Sep 2001
    Posts
    396
    Maybe I'm dumb. What is alphamask?

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    having some wierd effects with the graphics now. it started off by drawing only a black box where the image should be. i disabled the blending algorythm and it is supposed to emulate BitBlt now (copies the source to the dest at full opacity). unfortunatly, it's drawing from the upper right hand corner of the screen and in monochrome. maybe somebody could help me figure out why i can't get this to at least draw in color? I included the relevent source code.

    the behavior i'm looking for is to blit an image onto an existing image, varying the opacity based on the pixels in the mask image. this will be used in some interactive transparent user interface controls and possible a game or too.
    Code:
    #include "resource.h"
    #include <windows.h>
    
    // The Representation of a 32 bit color table entry
    #pragma pack(push)
    #pragma pack(1)
    typedef struct ssBGR {
      unsigned char b;
      unsigned char g;
      unsigned char r;
      unsigned char pad;
    } sBGR;
    
    typedef sBGR *pBGR;
    #pragma pack(pop)
    
    pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight);
    int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf);
    
    /*
    SoftBlt
       x and y on screen (point api)
       x, y, width, height of source (rect) (this param used for both Source and Mask)
       Screen (hDc)
       Source (hDc)
       SourceMask (hDc)
    
    
    Laymans translation of the following code
    	STEP 1 - get dib section of current screen (same size as source)	
    	STEP 2 - get dib section of source
    	STEP 3 - get dib section of mask
    	STEP 4 - combine all three dib sections' arrays using the blend algorythm
    	STEP 5 - create a temporary dc and create a bitmap of the correct size
    	STEP 6 - use SetDIBits to blit the image to the temporary dc
    	STEP 7 - BitBlt the contents of the temporary dc to hDcDest using the rasterop specified
        STEP 8 - Clean Up...
    
    	***work only within the bounds of the source rect***
    	MATH
    	
    	The following function is executed for each channel of each pixel
    	The mask's value is the same for each channel and is the average of the three channels.
    
        m = (mask.r + mask.g + mask.b) / 3
    
    	d is the destination pixel
    	s is the source pixel
    	m is the mask pixel
    
    		d = s * (m + ((1 - m) * d))
     
    */
    
    BOOL __stdcall SoftBlt(HDC hdcDest, int nLeft, int nTop, int nWidth, int nHeight, HDC hdcSrc, HDC hdcSrcMask)
    {	
    
    	//STEP 1 - 3
    	HDC hdcTMPDest = CreateCompatibleDC(hdcDest);
    	HBITMAP hbTMPDest = CreateCompatibleBitmap(hdcTMPDest, nWidth, nHeight);
    	SelectObject(hdcTMPDest, hbTMPDest);
    	BitBlt(hdcTMPDest, 0, 0, nWidth, nHeight, hdcDest, nLeft, nTop, SRCCOPY);
    
    	pBGR dibDest = MyGetDibBits(hdcTMPDest, (HBITMAP) GetCurrentObject(hdcTMPDest, OBJ_BITMAP), nWidth, nHeight);
    	pBGR dibSource = MyGetDibBits(hdcSrc, (HBITMAP) GetCurrentObject(hdcSrc, OBJ_BITMAP), nWidth, nHeight);
    	pBGR dibMask = MyGetDibBits(hdcSrcMask, (HBITMAP) GetCurrentObject(hdcSrcMask, OBJ_BITMAP), nWidth, nHeight);
    	
    	//STEP 4
    	for (int y = 0; y < nHeight; ++y)
    	{
    	  for (int x = 0; x < nWidth; ++x)
    	  {
    		sBGR bgrDest = dibDest[y * nWidth + x];
    		sBGR bgrSource = dibSource[y * nWidth + x];
    		sBGR bgrMask = dibMask[y * nWidth + x];
    		
    		unsigned char mask = (bgrMask.b + bgrMask.g + bgrMask.r) / 3;
    //Blend function
    /*
    		bgrDest.r = bgrSource.r * (mask + ((1 - mask) * bgrDest.r));
    		bgrDest.g = bgrSource.g * (mask + ((1 - mask) * bgrDest.g));
    		bgrDest.b = bgrSource.b * (mask + ((1 - mask) * bgrDest.b));
    */		
    
    		bgrDest = bgrSource; // <--- this is temporary, makes it act like bitblt
    
    		dibDest[y * nWidth + x] = bgrDest;
    	  }
    	}
    
    	//STEP 5
    
    	HDC hdcTmp = CreateCompatibleDC(hdcDest);
    	HBITMAP hbTmp = CreateCompatibleBitmap(hdcTmp, nWidth, nHeight);
    	SelectObject(hdcTmp, hbTmp);
    	
    	//STEP 6
    	MySetDibBits(hdcTmp, hbTmp, nWidth, nHeight, dibDest);
    
    	//STEP 7
    	BitBlt(hdcDest, nLeft, nTop, nWidth, nHeight, hdcTmp, 0, 0, SRCCOPY);
    
    	//Step 8
    	DeleteObject(hbTMPDest);
    	DeleteObject(hbTmp);
    	
    	DeleteDC(hdcTMPDest);
    	DeleteDC(hdcTmp);
    
    	free(dibDest);
    	free(dibSource);
    	free(dibMask);
    
    	return 1;
    }
    
    
    
    
    
    pBGR MyGetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight)
    {
      BITMAPINFO bi;
      BOOL bRes;
      pBGR buf;
    
      bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
      bi.bmiHeader.biWidth = nWidth;
      bi.bmiHeader.biHeight = - nHeight;
      bi.bmiHeader.biPlanes = 1;
      bi.bmiHeader.biBitCount = 32;
      bi.bmiHeader.biCompression = BI_RGB;
      bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
      bi.bmiHeader.biClrUsed = 0;
      bi.bmiHeader.biClrImportant = 0;
    
    //  buf = new sBGR[nWidth * nHeight];
      buf = (pBGR) malloc(nWidth * 4 * nHeight);
    
      bRes = GetDIBits(hdc, hBmp, 0, nHeight, buf, &bi, DIB_RGB_COLORS);
      if (!bRes) {
    //    delete [] buf;
        free(buf);
        buf = 0;
      }
      return buf;
    }
    
    int MySetDibBits(HDC hdc, HBITMAP hBmp, int nWidth, int nHeight, pBGR buf)
    {
      BITMAPINFO bi;
    
      bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
      bi.bmiHeader.biWidth = nWidth ;
      bi.bmiHeader.biHeight = - nHeight ;
      bi.bmiHeader.biPlanes = 1;
      bi.bmiHeader.biBitCount = 32;
      bi.bmiHeader.biCompression = BI_RGB;
      bi.bmiHeader.biSizeImage = nWidth * 4 * nHeight;
      bi.bmiHeader.biClrUsed = 0;
      bi.bmiHeader.biClrImportant = 0;
    
      return ( SetDIBits(hdc , hBmp ,0, nHeight ,buf,&bi,DIB_RGB_COLORS) );
    
    }
    Last edited by agent; Jul 24th, 2003 at 12:38 AM.

  13. #13
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Sorry, no idea where that particular problem is.

    Have you considered combining the alpha mask with the image and then AlphaBlending it?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  14. #14
    Hyperactive Member
    Join Date
    Sep 2001
    Posts
    396
    Color in red is what I change.

    The arguement I used for hdcDest parameter is the hDC I get from GetDC();

    As a thumb of rule, always use the main DC (from GetDC() ) for CreateCompatibleDC() and CreateCompatibleBitmap().
    Code:
    BOOL __stdcall SoftBlt(HDC hdcDest, int nLeft, int nTop, int nWidth, int nHeight, HDC hdcSrc, HDC hdcSrcMask)
    {	
    	//STEP 1 - 3
    	HDC hdcTMPDest = CreateCompatibleDC(hdcDest);
    	HBITMAP hbTMPDest = CreateCompatibleBitmap(hdcTMPDest, nWidth, nHeight);
    	SelectObject(hdcTMPDest, hbTMPDest);
    	BitBlt(hdcTMPDest, 0, 0, nWidth, nHeight, hdcDest, nLeft, nTop, SRCCOPY);
    
    	pBGR dibDest = MyGetDibBits(hdcTMPDest, (HBITMAP) GetCurrentObject(hdcTMPDest, OBJ_BITMAP), nWidth, nHeight);
    	pBGR dibSource = MyGetDibBits(hdcSrc, (HBITMAP) GetCurrentObject(hdcSrc, OBJ_BITMAP), nWidth, nHeight);
    	pBGR dibMask = MyGetDibBits(hdcSrcMask, (HBITMAP) GetCurrentObject(hdcSrcMask, OBJ_BITMAP), nWidth, nHeight);
    	
    	//STEP 4
    	for (int y = 0; y < nHeight; ++y)
    	{
    	  for (int x = 0; x < nWidth; ++x)
    	  {
    		sBGR bgrDest = dibDest[y * nWidth + x];
    		sBGR bgrSource = dibSource[y * nWidth + x];
    		sBGR bgrMask = dibMask[y * nWidth + x];
    		
    		unsigned char mask = (bgrMask.b + bgrMask.g + bgrMask.r) / 3;
    //Blend function
    /*
    		bgrDest.r = bgrSource.r * (mask + ((1 - mask) * bgrDest.r));
    		bgrDest.g = bgrSource.g * (mask + ((1 - mask) * bgrDest.g));
    		bgrDest.b = bgrSource.b * (mask + ((1 - mask) * bgrDest.b));
    */		
    
    		bgrDest = bgrSource; // <--- this is temporary, makes it act like bitblt
    
    		dibDest[y * nWidth + x] = bgrDest;
    	  }
    	}
    
    	//STEP 5
    
    	HDC hdcTmp = CreateCompatibleDC(hdcDest);
    	HBITMAP hbTmp = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
    	SelectObject(hdcTmp, hbTmp);
    	
    	//STEP 6
    	MySetDibBits(hdcTmp, hbTmp, nWidth, nHeight, dibDest);
    
    	//STEP 7
    	BitBlt(hdcDest, nLeft, nTop, nWidth, nHeight, hdcTmp, 0, 0, SRCCOPY);
    
    	//Step 8
    	DeleteObject(hbTMPDest);
    	DeleteObject(hbTmp);
    	
    	DeleteDC(hdcTMPDest);
    	DeleteDC(hdcTmp);
    
    	free(dibDest);
    	free(dibSource);
    	free(dibMask);
    
    	return 1;
    
    }

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    well now it in color, but it's still blitting from the upper left corner of the screen instead of from the picturebox's hDC in vb.

    also, would you be able to tell me if i have the right formula for alpha bleneding? if not, do you know what it is?

    Originally posted by transcendental
    Maybe I'm dumb. What is alphamask?
    an alphamask is a separate image that maps the opacity of each pixel it lines up with in the first image using the grey value of each pixel (0 through 255)

    my function averages the three channels for each pixel to get a decent grey value (works good even if the image is already greyscale)

  16. #16
    Hyperactive Member
    Join Date
    Sep 2001
    Posts
    396
    well now it in color, but it's still blitting from the upper left corner of the screen instead of from the picturebox's hDC in vb.
    Use the picturebox's hDC then. I have never used picturebox control so can't help you much.

    The below is the MyAlphablend function(it calls the pixelate() function). All the parameters are self-explanatory. As for the 'Alpha' parameter, 0 means the source bitmap is fully transparent, 255 means the source is opaque. In other words, Alpha is the Alpha level.
    Code:
    void MyAlphaBlend(pBGR pDest, int nWidth, int nHeight, pBGR pSrc, BYTE Alpha)
    {
      for(int y=0;y<nHeight;++y)
      {
        for(int x=0;x<nWidth;++x)
        {
          int i =y *nWidth+x;
          pDest[i]=Pixelate(pDest[i],pSrc[i],Alpha);
        }
      }
    }
    
    
    sBGR Pixelate(sBGR dest,sBGR source,BYTE Alpha)
    {
    
      float FinalRed,FinalGreen,FinalBlue;
    
      FinalRed  = (Alpha/255.0f*(float)source.r) + ((1.0f-Alpha/255.0f)*(float)dest.r);
      FinalGreen= (Alpha/255.0f*(float)source.g) + ((1.0f-Alpha/255.0f)*(float)dest.g);
      FinalBlue = (Alpha/255.0f*(float)source.b) + ((1.0f-Alpha/255.0f)*(float)dest.b);
      
      int nFinalRed,nFinalGreen,nFinalBlue;
      
      if(FinalRed>=FinalGreen && FinalRed>=FinalBlue)
      {
        if(FinalRed>255.0f)
        {
          nFinalRed=255;
          nFinalGreen=(int)(FinalGreen/FinalRed*255.0f);
          nFinalBlue =(int)(FinalBlue/FinalRed*255.0f);
        }
        else
        {
          nFinalRed  =(int)(FinalRed);
          nFinalGreen=(int)(FinalGreen);
          nFinalBlue =(int)(FinalBlue);
        }
      }
      else if(FinalGreen>=FinalRed && FinalGreen>=FinalBlue)
      {
        if(FinalGreen>255.0f)
        {
          nFinalRed  =(int)(FinalRed/FinalGreen*255.0f);
          nFinalGreen=255;
          nFinalBlue =(int)(FinalBlue/FinalGreen*255.0f);
        }
        else
        {
          nFinalRed  =(int)(FinalRed);
          nFinalGreen=(int)(FinalGreen);
          nFinalBlue =(int)(FinalBlue);
        }
      }
      else if(FinalBlue>=FinalRed && FinalBlue>=FinalGreen)
      {
        if(FinalBlue>255.0f)
        {
          nFinalRed  =(int)(FinalRed/FinalBlue*255.0f);
          nFinalGreen=(int)(FinalGreen/FinalBlue*255.0f);
          nFinalBlue=255;
        }
        else
        {
          nFinalRed  =(int)(FinalRed);
          nFinalGreen=(int)(FinalGreen);
          nFinalBlue =(int)(FinalBlue);
        }
      }
      sBGR tempBGR;
      tempBGR.r=nFinalRed;
      tempBGR.g=nFinalGreen;
      tempBGR.b=nFinalBlue;
      return tempBGR;
    }

  17. #17

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    your function applies the transparancy to the whole image. my function needs to have per-pixel transparancy. i'll post a separate question about the math behind the blend function.

    also, i fixed the picturebox problem. turned out to be on VB's side (what else is new...) If the AutoRedraw property is false, then the hDC property of the box returns the screen's hDC. kinda stupid, but...

  18. #18
    Hyperactive Member
    Join Date
    Sep 2001
    Posts
    396
    Well, that's for you to modify to your needs. That AlphaBlend function had served my purpose and I'm not going to touch it anymore.

  19. #19

    Thread Starter
    Fanatic Member
    Join Date
    Jun 1999
    Location
    California, USA
    Posts
    662
    Originally posted by transcendental
    Well, that's for you to modify to your needs. That AlphaBlend function had served my purpose and I'm not going to touch it anymore.;)
    thanks very much. i ended up using it and it solved my problem. for more info, see also http://www.vbforums.com/showthread.php?threadid=255453

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width