Thread: Create 24 bits bitmap in memory

  1. #1
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158

    Create 24 bits bitmap in memory

    Hello. I'm trying to generate a 24-bits bitmap and loop through each pixel, calulate the new pixel value. I read somewhere that when the scan line byte count is odd, it must be padded with zeros. I'm trying to implement this correctly but i don't seem to manage.
    rcFill is the rectangle I want to fill with the generated bitmap. When I make the right value 400, it works. With 401, it also works. But with 402 the bitmap looks distorted as if it were on a grayscale tv screen showing the contents of a broken VHS tape. Can anyone see what's wrong in my algorithm? I previously used 32 bits bitmaps, so I didn't have to pad the scan lines, and that worked fine, so the problem isn't in my calcuations.
    Below is my code and two screenshots respectively of the result when specifying 401 as the right value of the RECT (so cx is 361), and the result with 402.

    Code:
    static RECT rcFill = { 40, 40, 402, 400 };    //rectangle we want to fill with a fancy gradient
    
    // ...
    
                int cx = (rcFill.right-rcFill.left);       //width of the rectangle
                int cy = (rcFill.bottom-rcFill.top);   //height of the rectangle
                int cScan = cx * 3;                     //number of bytes in a scan line
                bool fOddScanWidth = (cScan%2);  
                if(fOddScanWidth) cScan++;     //if cScan is odd add an extra byte
                int bytes = cScan * cy;         //allocate memory block for pixel data:
                unsigned char* puc = new unsigned char[bytes], *p = puc;  //p is the pointer we use for our loop
                memset(puc, 0, bytes);
                for(int y=0; y<cy; ++y)
                {
                    for(int x=0; x<cx; ++x)
                    {
                        unsigned char R = 0, G = 0, B = 0;
    
                        // calculations...
    
                        *p = B;
                        p[1] = G;
                        p[2] = R;
                        
                        p += 3;
                    }    
                    if(fOddScanWidth) ++p;
                }    
                
                BITMAPINFO bmi = 
                {
                    {
                        sizeof (BITMAPINFOHEADER),
                        cx, -cy,
                        1, 24, 
                    },
                };        
                SetDIBits(NULL, hMemBmp, 0, rcFill.bottom - rcFill.top, puc, &bmi, DIB_RGB_COLORS);
                delete [] puc;
    Last edited by pronecracker; 05-05-2007 at 09:26 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    I thought each bitmap row was supposed to be a multiple of 4 bytes long, not 2.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    oops, gotta try that

  4. #4
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    Thanks Salem, it works now for every value. What a simple answer to such a large post
    Gotta develop my program further.

  5. #5
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    My
    new
    Code:
                int cx = (rcFill.right-rcFill.left);
                int cy = (rcFill.bottom-rcFill.top);
                int cScan = cx * 3;
                int pad = 4-(cScan&#37;4);
                if(pad==4) pad=0;
                cScan += pad;
                int bytes = cScan * cy;
                unsigned char* puc = new unsigned char[bytes], *p = puc;
                memset(puc, 0, bytes);
                for(int y=0; y<cy; ++y)
                {
                    for(int x=0; x<cx; ++x)
                    {
    ///...
                        p += 3;
                    }    
                    p += pad;
                }
    Last edited by pronecracker; 05-05-2007 at 11:46 AM.

  6. #6
    Registered User pronecracker's Avatar
    Join Date
    Oct 2006
    Location
    netherlands
    Posts
    158
    Quote Originally Posted by Charles Petzold
    However, when Windows allocates memory for the bitmap each row has an even number of bytes.
    Although Salems suggestion proves to be true, I can hardly imagine that Petzold makes a mistake here...
    Last edited by pronecracker; 05-05-2007 at 10:57 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. tools for finding memory leaks
    By stanlvw in forum C++ Programming
    Replies: 4
    Last Post: 04-03-2009, 11:41 AM
  2. Cannot create shared memory
    By Phoenix_Rebirth in forum C Programming
    Replies: 3
    Last Post: 11-07-2008, 11:32 AM
  3. MSVC++ allegro tutorial
    By bobish in forum Game Programming
    Replies: 5
    Last Post: 02-13-2002, 04:11 PM
  4. FAQ: MSVC++ allegro tutorial
    By bobish in forum FAQ Board
    Replies: 3
    Last Post: 02-09-2002, 07:48 PM
  5. Allegro tutorials
    By valar_king in forum Game Programming
    Replies: 6
    Last Post: 12-27-2001, 12:44 PM