Bug 493455 - [win32] wrong transparency for some icons and images

Almost all win32 APIs working with transparent bitmaps expect them to
be in premultiplied alpha format. Notable exceptions are bitmaps used
to create icons and the ImageList API. Therefore, transparent images
switched from being stored in straight alpha format to premultiplied
alpha format in commit 8d21781c6b65b49d2f30db28ada54be673b5925c.

This was not properly reflected in Display.create32BitDIB(Image image)
that now wrongly applied the alpha multiplication again to already pre-
multiplied RGB values. Moreover, both Display.create32BitDIB taking a
native bitmap and converting it to a 32-bit bitmap that is then used to
create an icon as well as ImageList.set are expected to produce bitmaps
in straight alpha format. However, they now failed to properly convert
back from premultiplied alpha format.

Change-Id: I0cfa74161227bfd9204b531e9c7d028c1a5bcc82
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/190757
Tested-by: Niraj Modi <niraj.modi@in.ibm.com>
Reviewed-by: Niraj Modi <niraj.modi@in.ibm.com>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java
index ff2a39f..34ccb92 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java
@@ -151,10 +151,16 @@
 	/* Merge the alpha channel in place */
 	if (alphaData != null) {
 		int spinc = dibBM.bmWidthBytes - srcWidth * 4;
-		int ap = 0, sp = 3;
+		int ap = 0, sp = 0;
 		for (int y = 0; y < srcHeight; ++y) {
 			for (int x = 0; x < srcWidth; ++x) {
-				srcData [sp] = alphaData [ap++];
+				int a = alphaData [ap++] & 0xFF;
+				if (a != 0) {
+					srcData [sp    ] = (byte)((((srcData [sp    ] & 0xFF) * 0xFF) + a / 2) / a);
+					srcData [sp + 1] = (byte)((((srcData [sp + 1] & 0xFF) * 0xFF) + a / 2) / a);
+					srcData [sp + 2] = (byte)((((srcData [sp + 2] & 0xFF) * 0xFF) + a / 2) / a);
+				}
+				srcData [sp + 3] = (byte)a;
 				sp += 4;
 			}
 			sp += spinc;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
index 151be72..2e71ec1 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
@@ -991,39 +991,6 @@
 				dp += 4;
 			}
 		}
-	} else if (alpha != -1) {
-		for (int y = 0, dp = 0; y < imgHeight; ++y) {
-			for (int x = 0; x < imgWidth; ++x) {
-				int r = ((srcData[dp + 0] & 0xFF) * alpha) + 128;
-				r = (r + (r >> 8)) >> 8;
-				int g = ((srcData[dp + 1] & 0xFF) * alpha) + 128;
-				g = (g + (g >> 8)) >> 8;
-				int b = ((srcData[dp + 2] & 0xFF) * alpha) + 128;
-				b = (b + (b >> 8)) >> 8;
-				srcData[dp+0] = (byte)r;
-				srcData[dp+1] = (byte)g;
-				srcData[dp+2] = (byte)b;
-				srcData[dp+3] = (byte)alpha;
-				dp += 4;
-			}
-		}
-	} else if (alphaData != null) {
-		for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
-			for (int x = 0; x < imgWidth; ++x) {
-				int a = alphaData[ap++] & 0xFF;
-				int r = ((srcData[dp + 0] & 0xFF) * a) + 128;
-				r = (r + (r >> 8)) >> 8;
-				int g = ((srcData[dp + 1] & 0xFF) * a) + 128;
-				g = (g + (g >> 8)) >> 8;
-				int b = ((srcData[dp + 2] & 0xFF) * a) + 128;
-				b = (b + (b >> 8)) >> 8;
-				srcData[dp+0] = (byte)r;
-				srcData[dp+1] = (byte)g;
-				srcData[dp+2] = (byte)b;
-				srcData[dp+3] = (byte)a;
-				dp += 4;
-			}
-		}
 	} else if (transparentPixel != -1) {
 		for (int y = 0, dp = 0; y < imgHeight; ++y) {
 			for (int x = 0; x < imgWidth; ++x) {
@@ -1035,7 +1002,7 @@
 				dp += 4;
 			}
 		}
-	} else {
+	} else if (alpha == -1 && alphaData == null) {
 		for (int y = 0, dp = 0; y < imgHeight; ++y) {
 			for (int x = 0; x < imgWidth; ++x) {
 				srcData [dp + 3] = (byte)0xFF;
@@ -1117,6 +1084,11 @@
 	if (alpha != -1) {
 		for (int y = 0, dp = 0; y < imgHeight; ++y) {
 			for (int x = 0; x < imgWidth; ++x) {
+				if (alpha != 0) {
+					srcData [dp    ] = (byte)((((srcData[dp    ] & 0xFF) * 0xFF) + alpha / 2) / alpha);
+					srcData [dp + 1] = (byte)((((srcData[dp + 1] & 0xFF) * 0xFF) + alpha / 2) / alpha);
+					srcData [dp + 2] = (byte)((((srcData[dp + 2] & 0xFF) * 0xFF) + alpha / 2) / alpha);
+				}
 				srcData [dp + 3] = (byte)alpha;
 				dp += 4;
 			}
@@ -1124,7 +1096,13 @@
 	} else if (alphaData != null) {
 		for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
 			for (int x = 0; x < imgWidth; ++x) {
-				srcData [dp + 3] = alphaData [ap++];
+				int a = alphaData [ap++] & 0xFF;
+				if (a != 0) {
+					srcData [dp    ] = (byte)((((srcData[dp    ] & 0xFF) * 0xFF) + a / 2) / a);
+					srcData [dp + 1] = (byte)((((srcData[dp + 1] & 0xFF) * 0xFF) + a / 2) / a);
+					srcData [dp + 2] = (byte)((((srcData[dp + 2] & 0xFF) * 0xFF) + a / 2) / a);
+				}
+				srcData [dp + 3] = (byte)a;
 				dp += 4;
 			}
 		}