i have these code for get image pixel data:

typedef std::vector<BYTE> pixeldata;
pixeldata GetImagePixel(HDC hdcImage)
{
    BITMAP bmp = {0};
    BITMAPINFO Info = {0};
    memset( &bmp, 0, sizeof(BITMAP) );
    HBITMAP hBitmap =(HBITMAP) GetCurrentObject(hdcImage, OBJ_BITMAP);
    GetObject(hBitmap, sizeof(BITMAP), &bmp);

    BITMAPINFO info { };
    info.bmiHeader.biSize = sizeof(info.bmiHeader);
    info.bmiHeader.biWidth = bmp.bmWidth;
    // pay attention to the sign, you most likely want a
    // top-down pixel array as it's easier to use
    info.bmiHeader.biHeight = -bmp.bmHeight;
    info.bmiHeader.biPlanes = 1;
    info.bmiHeader.biBitCount = 32;
    info.bmiHeader.biCompression = BI_RGB;

    // the following calculations work for 16/24/32 bits bitmaps
    // but assume a byte pixel array
    size_t pixelSize = info.bmiHeader.biBitCount / 8;
    // the + 3 ) & ~3 part is there to ensure that each
    // scan line is 4 byte aligned
    size_t scanlineSize = (pixelSize * info.bmiHeader.biWidth + 3) & ~3;
    size_t bitmapSize = bmp.bmHeight * scanlineSize;

    pixeldata pixels(bitmapSize);
    GetDIBits(hdcImage, hBitmap, 0, bmp.bmHeight, &pixels[0], &info, DIB_RGB_COLORS);
    bmp.bmHeight = std::abs(bmp.bmHeight);
    return pixels;
}

void SetImageData(HDC hdcDestination, pixeldata pixels)
{
    BITMAP bmp = {0};
    BITMAPINFO Info = {0};
    memset( &bmp, 0, sizeof(BITMAP) );
    HBITMAP hBitmap =(HBITMAP) GetCurrentObject(hdcDestination, OBJ_BITMAP);
    GetObject(hBitmap, sizeof(BITMAP), &bmp);
    BITMAPINFO info { };
    info.bmiHeader.biSize = sizeof(info.bmiHeader);
    info.bmiHeader.biWidth = bmp.bmWidth;
    // pay attention to the sign, you most likely want a
    // top-down pixel array as it's easier to use
    info.bmiHeader.biHeight = -bmp.bmHeight;
    info.bmiHeader.biPlanes = 1;
    info.bmiHeader.biBitCount = 32;
    info.bmiHeader.biCompression = BI_RGB;

    SetDIBits(hdcDestination, hBitmap, 0, bmp.bmHeight, &pixels[0], &info, DIB_RGB_COLORS);
}
//how use it
/*pixeldata pixels=GetImagePixel(imgImage);

size_t pixelSize = bm.bmBitsPixel / 8;
size_t scanlineSize = (pixelSize * bm.bmWidth + 3) & ~3;

int x=0, y=0;
for(y=0; y<imgImage.height(); y++)
{
    for(x=0; x<imgImage.width(); x++)
    {
        size_t pixelOffset = y * scanlineSize + x * pixelSize;

        COLORREF clrActualColor=RGB(pixels[pixelOffset+2],pixels[pixelOffset+1],pixels[pixelOffset+ 0]);
        if(clrActualColor ==RGB(0,0,0))
        {
            pixels[pixelOffset+2]=GetRValue(GetSysColor(COLOR_MENU));
            pixels[pixelOffset+1]=GetGValue(GetSysColor(COLOR_MENU));
            pixels[pixelOffset+0]=GetBValue(GetSysColor(COLOR_MENU));
        }
    }
}
SetImageData(hMemDC,pixels);*/

from these functions, i did my own shadow effect:

void Shadow(int PosX=0, int PosY=0)
    {
        pixeldata pixels=GetImagePixel(HBitmap);

        size_t pixelSize = HBitmap.bitperpixel() / 8;
        size_t scanlineSize = (pixelSize * HBitmap.Width() + 3) & ~3;

        int x=0, y=0;
        COLORREF BackColor;
        for(y=0; y<HBitmap.Height(); y++)
        {
            for(x=0; x<HBitmap.Width(); x++)
            {
                //getting pixel and drawed pixel positions:
                size_t pixelOffset = y * scanlineSize + x * pixelSize;//actual pixel position
                size_t pixelOffset2 = (y+PosY) * scanlineSize + (x+PosX) * pixelSize; //the position where the shadow pixel is drawed

                //gettin backcolor:
                if(x==0 && y==0)
                    BackColor=RGB(pixels[pixelOffset+2],pixels[pixelOffset+1],pixels[pixelOffset+ 0]);

                //getting actual color:
                COLORREF clrActualColor=RGB(pixels[pixelOffset+2],pixels[pixelOffset+1],pixels[pixelOffset+ 0]);
                if(clrActualColor !=BackColor)//if the actual color is diferent of backcolor then:
                {
                    //if the drawed pixel position is backcolor pixel, then draw it:
                    if(RGB(pixels[pixelOffset2+2],pixels[pixelOffset2+1],pixels[pixelOffset2+0])==BackColor && RGB(pixels[pixelOffset2+2],pixels[pixelOffset2+1],pixels[pixelOffset2+0])!=CLR_INVALID)
                    {
                        pixels[pixelOffset2+2]=GetRValue(0);
                        pixels[pixelOffset2+1]=GetGValue(0);
                        pixels[pixelOffset2+0]=GetBValue(0);
                    }

                }
            }
        }
        SetImageData(HBitmap,pixels);
    }

(objective: these function just add some black pixels to the image, for do a shadow effect)
but or i miss understood how can i calculate the next pixel position(depending on PosX and PosY), or i don't know(the pixelOffset2):(
the image show us the results :(
shadow_problem2.png

Dani AI

Generated

Nice progress — already found the two biggest mistakes (missing bounds checks and the color tests). A few small, targeted changes will make the routine robust and avoid subtle bugs that show up later.

First, be explicit about stride, height and byte order. Compute the absolute image height once and use it for buffer size and for GetDIBits/GetDIBits calls. Make the scanline size the bitmap-aligned stride (round the row up to a 32‑bit boundary). Remember that 32‑bpp memory is stored as B,G,R,[reserved], not R,G,B, so comparisons and copies must match that layout.

Second, always validate target coordinates before turning them into an unsigned offset. A common trap is letting (x + PosX) become negative and then casting to size_t — that wraps to a huge index. Do this in signed arithmetic: compute tx = x + PosX; ty = y + PosY; if (tx < 0 || ty < 0 || tx >= width || ty >= height) continue; only then compute offset = tystride + txpixelBytes.

Third, avoid in‑place read/write surprises. Either copy the original pixel buffer to a read-only source and write into the destination buffer, or choose an iteration order that guarantees you never read a pixel you already overwrote (e.g., reverse rows/cols when PosX/PosY are positive). Also handle the fourth byte in 32‑bit images (set it to 0xFF if you want an opaque shadow), since leaving it undefined can give unexpected blending.

Finally, use signed ints for coordinates and size_t for offsets, and consider packing BGRA into a uint32_t for faster equality checks. With these checks your shadow routine will be predictable for negative offsets, different bit depths, and edge cases.

after several tests, i fixed the function:

void Shadow(int PosX=0, int PosY=0, COLORREF ShadowColor=RGB(0,0,0))
    {
        pixeldata pixels=GetImagePixel(HBitmap);

        size_t pixelSize = HBitmap.bitperpixel() / 8;
        size_t scanlineSize = (pixelSize * HBitmap.Width() + 3) & ~3;

        int x=0, y=0;
        COLORREF BackColor;
        for(y=0; y<HBitmap.Height(); y++)
        {
            for(x=0; x<HBitmap.Width(); x++)
            {
                if((y+PosY)>=HBitmap.Height() || (x+PosX)>=HBitmap.Width())
                    continue;
                //getting pixel and drawed pixel positions:
                size_t pixelOffset = y * scanlineSize + x * pixelSize;//actual pixel position
                size_t pixelOffset2 =(y+PosY) * scanlineSize + (x+PosX) * pixelSize; //the position where the shadow pixel is drawed

                //gettin backcolor:
                if(x==0 && y==0)
                {
                   BackColor=RGB(pixels[pixelOffset+2],pixels[pixelOffset+1],pixels[pixelOffset+ 0]);
                }


                //getting actual color:
                COLORREF clrActualColor=RGB(pixels[pixelOffset+2],pixels[pixelOffset+1],pixels[pixelOffset+ 0]);
                COLORREF clrActualColor2=RGB(pixels[pixelOffset2+2],pixels[pixelOffset2+1],pixels[pixelOffset2+ 0]);
                if((clrActualColor!=BackColor && clrActualColor!=ShadowColor)&& clrActualColor2==BackColor)//if the actual color is diferent of backcolor then:
                {
                    pixels[pixelOffset2+2]=GetRValue(ShadowColor);
                    pixels[pixelOffset2+1]=GetGValue(ShadowColor);
                    pixels[pixelOffset2+0]=GetBValue(ShadowColor);
                }
            }
        }
        SetImageData(HBitmap,pixels);
    }

i did several mistakes:
1 - i didn't tested the x+PosX and y+PosY limits;
2 - i was not testing, correctly, the clrActualColor.
i hope these topic make the readers thinking where i did the mistakes and why ;)
shadow_effect.png

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.