1

I have a 32-bit png file with an alpha (transparent) layer. I want to change the color of some pixels on a per-pixel basis using MFC. Performance isn't an issue (although faster is better).

I wrote code to call CImage::GetPixel() tweak the returned COLORREF, and SetPixel() the new color, but the entire image was transparent. So I wrote the following block which simply gets and sets the original color. The resulting image is entirely transparent. I also tried simply using SetPixel(x, y, RGB(255, 0, 0)) to set all pixels to red. Any advice to resolve this?

CImage image;
if(image.Load(sFilename) == S_OK)
{
    TRACE(L"IsTransparencySupported %d", image.IsTransparencySupported()); // Returns 1.
    TRACE(L"IsDIBSection %d", image.IsDIBSection()); // Returns 1.
    TRACE(L"Size %dx%d", image.GetWidth(), image.GetHeight()); // Displays 141x165.
    TRACE(L"BPP %d", image.GetBPP()); // Returns 32.
    TRACE(L"Pitch %d", image.GetPitch()); // Returns -564.

    COLORREF color;
    for(int x = 0; x < image.GetWidth(); x++)
    {
        for(int y = 0; y < image.GetHeight(); y++)
        {
            color = image.GetPixel(x, y); 
            image.SetPixel(x, y, color);
        }
    }

    if(image.Save(sFilenameNew, Gdiplus::ImageFormatPNG) != S_OK)
        TRACE(L"Error saving %s.", sFilenameNew);
}
else
    TRACE(L"Error loading png %s.", sFilename);

Thanks!

Steve A
  • 1,798
  • 4
  • 16
  • 34
  • 2
    The `COLORREF` macros don't seem to support alpha, and as a result the alpha is always zero. Try `SetPixel(x, y, color | 0xff000000)`. If that works, you might want to make your own macros for defining color constants with non-zero alpha. If it doesn't work, it may be that `SetPixel` is just too stupid, and you may want to consider setting pixels in the buffer returned by [GetBits](https://learn.microsoft.com/en-us/cpp/atl-mfc-shared/reference/cimage-class?view=vs-2019#getbits) – paddy Jul 17 '20 at 00:59
  • 1
    @pad `COLORREF` is perfectly capable of representing an alpha channel. It's the GDI that - for the most part - isn't prepared to support alpha transparency. Like [GetPixel](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getpixel), that doesn't (and cannot be changed to) return alpha transparency information, because it reserved `0xFFFFFFFF` (`CLR_INVALID`) as a special error value. I'm not sure `SetPixel` supports alpha transparency for the same reason, although [SetPixelV](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixelv) might. – IInspectable Jul 17 '20 at 13:33

1 Answers1

1
CImage image;
for (int i=0;i<image.ImgHeight;i++)
{
    for (int j=0;j<image.ImgWidth;j++)
    {
        int index = i*image.ImgWidth+j;
        unsigned char* pucColor = reinterpret_cast<unsigned char *>      (image.GetPixelAddress(j , i)); 
        pucColor[0] = bValues[index];   
        pucColor[1] = gValues[index];   
        pucColor[2] = rValues[index];  
    }
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Chan Xiang
  • 56
  • 3