Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. SetBitmapBits not Working as Expected

SetBitmapBits not Working as Expected

Scheduled Pinned Locked Moved C / C++ / MFC
performancegraphicstoolsquestion
7 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    walter76
    wrote on last edited by
    #1

    Hi there, i have written this function to draw a image held in raw pixel data in my own class to a window. It is not working as expected, say it doesn't draw a single pixel. Where is the fault? I am trying to solve this for days now and can't see where i made the mistake. Here comes the code.

    void CImageViewerView::drawImage(CDC* pDC, CpilImage* pImage) {
    // create compatible memory dc
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);

    // draw image into the bitmap
    CBitmap imageBitmap;
    BITMAP bmp;
    BYTE\* imageBits;
    BYTE\* pImageBits;
    
    imageBitmap.CreateBitmap(pImage->getWidth(), pImage->getHeight(), 1, 24, NULL);
    imageBitmap.GetBitmap(&bmp);
    imageBits = (BYTE\*) GlobalAlloc(GPTR, bmp.bmHeight \* bmp.bmWidthBytes);
    
    for (unsigned int y = 0; y < pImage->getHeight(); y++) {
        unsigned int\* line = pImage->getPixelRegion(0, y, pImage->getWidth(), 1);
        unsigned int\* pLine = line;
    
        pImageBits = imageBits + (bmp.bmWidthBytes \* y);
        for (unsigned int x = 0; x < pImage->getWidth(); x++) {
            pImageBits\[0\] = getRedValue(pLine);
            pImageBits\[1\] = getGreenValue(pLine);
            pImageBits\[2\] = getBlueValue(pLine);
            pImageBits += 3;
            pLine++;
        }
    }
    if (imageBitmap.SetBitmapBits(bmp.bmHeight \* bmp.bmWidthBytes, imageBits) == 0) {
        AfxMessageBox("Could not set bitmap bits.");
    }
    
    GlobalFree((HGLOBAL) imageBits);
    
    // draw bitmap
    CBitmap\* pOldBitmap = memDC.SelectObject(&imageBitmap);
    if (pDC->BitBlt(0, 0, pImage->getWidth(), pImage->getHeight(), &memDC, 0, 0, SRCCOPY) ==0) {
        AfxMessageBox("BitBlt failed.");
    }
    memDC.SelectObject(pOldBitmap);
    

    }

    CpilImage is a class which stores a image plus the pixel data in rgb-quads. The getXXXValue()-functions are utility functions which extract the red, green and blue values from the quads. The class and functions are working, cause if i alter the function to work with CDC::SetPixelV() the image is drawn. But as this is very slow i tryed to speed it up with SetBitmapBits() and BitBlt() which seems to not work. Walter

    I R 3 Replies Last reply
    0
    • W walter76

      Hi there, i have written this function to draw a image held in raw pixel data in my own class to a window. It is not working as expected, say it doesn't draw a single pixel. Where is the fault? I am trying to solve this for days now and can't see where i made the mistake. Here comes the code.

      void CImageViewerView::drawImage(CDC* pDC, CpilImage* pImage) {
      // create compatible memory dc
      CDC memDC;
      memDC.CreateCompatibleDC(pDC);

      // draw image into the bitmap
      CBitmap imageBitmap;
      BITMAP bmp;
      BYTE\* imageBits;
      BYTE\* pImageBits;
      
      imageBitmap.CreateBitmap(pImage->getWidth(), pImage->getHeight(), 1, 24, NULL);
      imageBitmap.GetBitmap(&bmp);
      imageBits = (BYTE\*) GlobalAlloc(GPTR, bmp.bmHeight \* bmp.bmWidthBytes);
      
      for (unsigned int y = 0; y < pImage->getHeight(); y++) {
          unsigned int\* line = pImage->getPixelRegion(0, y, pImage->getWidth(), 1);
          unsigned int\* pLine = line;
      
          pImageBits = imageBits + (bmp.bmWidthBytes \* y);
          for (unsigned int x = 0; x < pImage->getWidth(); x++) {
              pImageBits\[0\] = getRedValue(pLine);
              pImageBits\[1\] = getGreenValue(pLine);
              pImageBits\[2\] = getBlueValue(pLine);
              pImageBits += 3;
              pLine++;
          }
      }
      if (imageBitmap.SetBitmapBits(bmp.bmHeight \* bmp.bmWidthBytes, imageBits) == 0) {
          AfxMessageBox("Could not set bitmap bits.");
      }
      
      GlobalFree((HGLOBAL) imageBits);
      
      // draw bitmap
      CBitmap\* pOldBitmap = memDC.SelectObject(&imageBitmap);
      if (pDC->BitBlt(0, 0, pImage->getWidth(), pImage->getHeight(), &memDC, 0, 0, SRCCOPY) ==0) {
          AfxMessageBox("BitBlt failed.");
      }
      memDC.SelectObject(pOldBitmap);
      

      }

      CpilImage is a class which stores a image plus the pixel data in rgb-quads. The getXXXValue()-functions are utility functions which extract the red, green and blue values from the quads. The class and functions are working, cause if i alter the function to work with CDC::SetPixelV() the image is drawn. But as this is very slow i tryed to speed it up with SetBitmapBits() and BitBlt() which seems to not work. Walter

      I Offline
      I Offline
      includeh10
      wrote on last edited by
      #2

      i am prety sure no one wants to read long code as in ur post. 1. bitmap width must be aligned with 2 or 4 bytes. 2. bottom-up or top-down bitmap is determined by BITMAPINFIHEADER.dbHeight.


      A nice tool for optimizing your Microsoft html-help contents. Includeh10 -- modified at 8:12 Wednesday 1st March, 2006

      W 1 Reply Last reply
      0
      • I includeh10

        i am prety sure no one wants to read long code as in ur post. 1. bitmap width must be aligned with 2 or 4 bytes. 2. bottom-up or top-down bitmap is determined by BITMAPINFIHEADER.dbHeight.


        A nice tool for optimizing your Microsoft html-help contents. Includeh10 -- modified at 8:12 Wednesday 1st March, 2006

        W Offline
        W Offline
        walter76
        wrote on last edited by
        #3

        I tryed to cut it down, but i thought everything could be important. But your post shows that you haven't read the code, either. I use the calculated width from the bitmap info header bmWidthBytes. This is calculated by windows and 4 bytes aligned. I put traces in there and the height is calculated correct. If any of this values would be false there should be something on the screen at last and if it is only crap. But there is nothing, not a single pixel. I try to break the code down a bit:

        // create compatible memory dc
        CDC memDC;
        memDC.CreateCompatibleDC(pDC);
        
        // draw image into the bitmap
        CBitmap imageBitmap;
        BITMAP bmp;
        BYTE\* imageBits;
        BYTE\* pImageBits;
        
        imageBitmap.CreateBitmap(pImage->getWidth(), pImage->getHeight(), 1, 24, NULL);
        imageBitmap.GetBitmap(&bmp);
        imageBits = (BYTE\*) GlobalAlloc(GPTR, bmp.bmHeight \* bmp.bmWidthBytes);
        
        //... doing some pixel transform stuff
        
        if (imageBitmap.SetBitmapBits(bmp.bmHeight \* bmp.bmWidthBytes, imageBits) == 0) {
            AfxMessageBox("Could not set bitmap bits.");
        }
        
        GlobalFree((HGLOBAL) imageBits);
        
        // draw bitmap
        CBitmap\* pOldBitmap = memDC.SelectObject(&imageBitmap);
        if (pDC->BitBlt(0, 0, pImage->getWidth(), pImage->getHeight(), &memDC, 0, 0, SRCCOPY) ==0) {
            AfxMessageBox("BitBlt failed.");
        }
        memDC.SelectObject(pOldBitmap);
        
        1 Reply Last reply
        0
        • W walter76

          Hi there, i have written this function to draw a image held in raw pixel data in my own class to a window. It is not working as expected, say it doesn't draw a single pixel. Where is the fault? I am trying to solve this for days now and can't see where i made the mistake. Here comes the code.

          void CImageViewerView::drawImage(CDC* pDC, CpilImage* pImage) {
          // create compatible memory dc
          CDC memDC;
          memDC.CreateCompatibleDC(pDC);

          // draw image into the bitmap
          CBitmap imageBitmap;
          BITMAP bmp;
          BYTE\* imageBits;
          BYTE\* pImageBits;
          
          imageBitmap.CreateBitmap(pImage->getWidth(), pImage->getHeight(), 1, 24, NULL);
          imageBitmap.GetBitmap(&bmp);
          imageBits = (BYTE\*) GlobalAlloc(GPTR, bmp.bmHeight \* bmp.bmWidthBytes);
          
          for (unsigned int y = 0; y < pImage->getHeight(); y++) {
              unsigned int\* line = pImage->getPixelRegion(0, y, pImage->getWidth(), 1);
              unsigned int\* pLine = line;
          
              pImageBits = imageBits + (bmp.bmWidthBytes \* y);
              for (unsigned int x = 0; x < pImage->getWidth(); x++) {
                  pImageBits\[0\] = getRedValue(pLine);
                  pImageBits\[1\] = getGreenValue(pLine);
                  pImageBits\[2\] = getBlueValue(pLine);
                  pImageBits += 3;
                  pLine++;
              }
          }
          if (imageBitmap.SetBitmapBits(bmp.bmHeight \* bmp.bmWidthBytes, imageBits) == 0) {
              AfxMessageBox("Could not set bitmap bits.");
          }
          
          GlobalFree((HGLOBAL) imageBits);
          
          // draw bitmap
          CBitmap\* pOldBitmap = memDC.SelectObject(&imageBitmap);
          if (pDC->BitBlt(0, 0, pImage->getWidth(), pImage->getHeight(), &memDC, 0, 0, SRCCOPY) ==0) {
              AfxMessageBox("BitBlt failed.");
          }
          memDC.SelectObject(pOldBitmap);
          

          }

          CpilImage is a class which stores a image plus the pixel data in rgb-quads. The getXXXValue()-functions are utility functions which extract the red, green and blue values from the quads. The class and functions are working, cause if i alter the function to work with CDC::SetPixelV() the image is drawn. But as this is very slow i tryed to speed it up with SetBitmapBits() and BitBlt() which seems to not work. Walter

          R Offline
          R Offline
          Ryan Binns
          wrote on last edited by
          #4

          Instead of using CreateBitmap(), use CreateCompatibleBitmap() passing pDC as the DC parameter, and then use the contents of the BITMAP structure to determine what format the bitmap is in. You may very well find that it's a 32-bpp bitmap, not a 24-bpp bitmap. Remember BitBlt() only works if the source bitmap is monochrome or in the same format as the device context - hence the CreateCompatibleBitmap() function.

          Ryan

          "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

          W 1 Reply Last reply
          0
          • W walter76

            Hi there, i have written this function to draw a image held in raw pixel data in my own class to a window. It is not working as expected, say it doesn't draw a single pixel. Where is the fault? I am trying to solve this for days now and can't see where i made the mistake. Here comes the code.

            void CImageViewerView::drawImage(CDC* pDC, CpilImage* pImage) {
            // create compatible memory dc
            CDC memDC;
            memDC.CreateCompatibleDC(pDC);

            // draw image into the bitmap
            CBitmap imageBitmap;
            BITMAP bmp;
            BYTE\* imageBits;
            BYTE\* pImageBits;
            
            imageBitmap.CreateBitmap(pImage->getWidth(), pImage->getHeight(), 1, 24, NULL);
            imageBitmap.GetBitmap(&bmp);
            imageBits = (BYTE\*) GlobalAlloc(GPTR, bmp.bmHeight \* bmp.bmWidthBytes);
            
            for (unsigned int y = 0; y < pImage->getHeight(); y++) {
                unsigned int\* line = pImage->getPixelRegion(0, y, pImage->getWidth(), 1);
                unsigned int\* pLine = line;
            
                pImageBits = imageBits + (bmp.bmWidthBytes \* y);
                for (unsigned int x = 0; x < pImage->getWidth(); x++) {
                    pImageBits\[0\] = getRedValue(pLine);
                    pImageBits\[1\] = getGreenValue(pLine);
                    pImageBits\[2\] = getBlueValue(pLine);
                    pImageBits += 3;
                    pLine++;
                }
            }
            if (imageBitmap.SetBitmapBits(bmp.bmHeight \* bmp.bmWidthBytes, imageBits) == 0) {
                AfxMessageBox("Could not set bitmap bits.");
            }
            
            GlobalFree((HGLOBAL) imageBits);
            
            // draw bitmap
            CBitmap\* pOldBitmap = memDC.SelectObject(&imageBitmap);
            if (pDC->BitBlt(0, 0, pImage->getWidth(), pImage->getHeight(), &memDC, 0, 0, SRCCOPY) ==0) {
                AfxMessageBox("BitBlt failed.");
            }
            memDC.SelectObject(pOldBitmap);
            

            }

            CpilImage is a class which stores a image plus the pixel data in rgb-quads. The getXXXValue()-functions are utility functions which extract the red, green and blue values from the quads. The class and functions are working, cause if i alter the function to work with CDC::SetPixelV() the image is drawn. But as this is very slow i tryed to speed it up with SetBitmapBits() and BitBlt() which seems to not work. Walter

            R Offline
            R Offline
            Ryan Binns
            wrote on last edited by
            #5

            I just noticed what you're trying to do :-O Have a look at CreateDIBitmap() and SetDIBitsToDevice(). They will work with any bitmap format and will convert between them when displaying the bitmap. Slower than BitBlt(), but the performance will be substantially quicker than what you are doing here.

            Ryan

            "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

            W 1 Reply Last reply
            0
            • R Ryan Binns

              Instead of using CreateBitmap(), use CreateCompatibleBitmap() passing pDC as the DC parameter, and then use the contents of the BITMAP structure to determine what format the bitmap is in. You may very well find that it's a 32-bpp bitmap, not a 24-bpp bitmap. Remember BitBlt() only works if the source bitmap is monochrome or in the same format as the device context - hence the CreateCompatibleBitmap() function.

              Ryan

              "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

              W Offline
              W Offline
              walter76
              wrote on last edited by
              #6

              Yeah! Just found out that this is the problem. It seems SelectObject() for the bitmap is returning an error, because of the bitmap is not compatible with the device context. I think i change my strategy and have a look into device independent bitmaps (DIB). Maybe this solves my problem. Programming Windows API can be frustrating sometimes. The only thing i want to do is to put some raw 24bit RGB pixel data fast on to the screen. This can't be that difficult. Thanks for your help!

              1 Reply Last reply
              0
              • R Ryan Binns

                I just noticed what you're trying to do :-O Have a look at CreateDIBitmap() and SetDIBitsToDevice(). They will work with any bitmap format and will convert between them when displaying the bitmap. Slower than BitBlt(), but the performance will be substantially quicker than what you are doing here.

                Ryan

                "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

                W Offline
                W Offline
                walter76
                wrote on last edited by
                #7

                Looks like i am on the right way now. Thanks again.

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups