void ImagePreMultAlpha(Image *pImage) { // The per pixel alpha blending API for layered windows deals with // pre-multiplied alpha values in the RGB channels. For further details see // the MSDN documentation for the BLENDFUNCTION structure. It basically // means we have to multiply each red, green, and blue channel in our image // with the alpha value divided by 255. // // Notes: // 1. ImagePreMultAlpha() needs to be called before every call to // UpdateLayeredWindow() (in the RedrawLayeredWindow() function). // // 2. Must divide by 255.0 instead of 255 to prevent alpha values in range // [1, 254] from causing the pixel to become black. This will cause a // conversion from 'float' to 'BYTE' possible loss of data warning which // can be safely ignored. if (!pImage) return; BYTE *pPixel = NULL; if (pImage->width * 4 == pImage->pitch) { // This is a special case. When the image width is already a multiple // of 4 the image does not require any padding bytes at the end of each // scan line. Consequently we do not need to address each scan line // separately. This is much faster than the below case where the image // width is not a multiple of 4. int totalBytes = pImage->width * pImage->height * 4; for (int i = 0; i < totalBytes; i += 4) { pPixel = &pImage->pPixels[i]; pPixel[0] = (BYTE)(pPixel[0] * (float)pPixel[3] / 255.0f); pPixel[1] = (BYTE)(pPixel[1] * (float)pPixel[3] / 255.0f); pPixel[2] = (BYTE)(pPixel[2] * (float)pPixel[3] / 255.0f); } } else { // Width of the image is not a multiple of 4. So padding bytes have // been included in the DIB's pixel data. Need to address each scan // line separately. This is much slower than the above case where the // width of the image is already a multiple of 4. for (int y = 0; y < pImage->height; ++y) { for (int x = 0; x < pImage->width; ++x) { pPixel = &pImage->pPixels[(y * pImage->pitch) + (x * 4)]; pPixel[0] = (BYTE)(pPixel[0] * (float)pPixel[3] / 255.0f); pPixel[1] = (BYTE)(pPixel[1] * (float)pPixel[3] / 255.0f); pPixel[2] = (BYTE)(pPixel[2] * (float)pPixel[3] / 255.0f); } } } }