Revert "Bug 493455 - [win32] remove alpha and alphaData from Image"

This reverts commit 8d21781c6b65b49d2f30db28ada54be673b5925c.

Reason for revert: https://bugs.eclipse.org/bugs/show_bug.cgi?id=493455#c37

Change-Id: I0e2be7c4ea34bb85af029205a2fbc06ad46fee8a
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/190415
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/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
index ac2dfaf..6311b10 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
@@ -1220,8 +1220,8 @@
 			data.hNullBitmap = 0;
 		}
 	}
-	if (bm.bmPlanes * bm.bmBitsPixel == 32) {
-		drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
+	if (srcImage.alpha != -1 || srcImage.alphaData != null) {
+		drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight);
 	} else if (srcImage.transparentPixel != -1) {
 		drawBitmapTransparent(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
 	} else {
@@ -1233,47 +1233,22 @@
 	}
 }
 
-void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight) {
+	/* Simple cases */
+	if (srcImage.alpha == 0) return;
+	if (srcImage.alpha == 255) {
+		drawBitmapColor(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
+		return;
+	}
+
 	boolean alphaBlendSupport = true;
 	boolean isPrinter = OS.GetDeviceCaps(handle, OS.TECHNOLOGY) == OS.DT_RASPRINTER;
-	int sourceAlpha = -1;
 	if (isPrinter) {
 		int caps = OS.GetDeviceCaps(handle, OS.SHADEBLENDCAPS);
 		if (caps != 0) {
-			long srcHdc = OS.CreateCompatibleDC(handle);
-			long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
-			long memDib = Image.createDIB(srcWidth, srcHeight, 32);
-			if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
-			long memHdc = OS.CreateCompatibleDC(handle);
-			long oldMemBitmap = OS.SelectObject(memHdc, memDib);
-			BITMAP dibBM = new BITMAP();
-			OS.GetObject(memDib, BITMAP.sizeof, dibBM);
-			OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
-			byte[] srcData = new byte[dibBM.bmWidthBytes * dibBM.bmHeight];
-			OS.MoveMemory(srcData, dibBM.bmBits, srcData.length);
-			int size = srcData.length;
-			sourceAlpha = srcData[3] & 0xFF;
-			for (int sp = 7; sp < size; sp += 4) {
-				int currentAlpha = srcData[sp] & 0xFF;
-				if (sourceAlpha != currentAlpha) {
-					sourceAlpha = -1;
-					break;
-				}
-			}
-			OS.SelectObject(memHdc, oldMemBitmap);
-			OS.DeleteDC(memHdc);
-			OS.DeleteObject(memDib);
-			OS.SelectObject(srcHdc, oldSrcBitmap);
-			OS.DeleteDC(srcHdc);
-			if (sourceAlpha != -1) {
-				if (sourceAlpha == 0) return;
-				if (sourceAlpha == 255) {
-					drawBitmapColor(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
-					return;
-				}
+			if (srcImage.alpha != -1) {
 				alphaBlendSupport = (caps & OS.SB_CONST_ALPHA) != 0;
-			}
-			else {
+			} else {
 				alphaBlendSupport = (caps & OS.SB_PIXEL_ALPHA) != 0;
 			}
 		}
@@ -1283,9 +1258,47 @@
 		blend.BlendOp = OS.AC_SRC_OVER;
 		long srcHdc = OS.CreateCompatibleDC(handle);
 		long oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
-		blend.SourceConstantAlpha = (byte)sourceAlpha;
-		blend.AlphaFormat = OS.AC_SRC_ALPHA;
-		OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, srcHdc, 0, 0, srcWidth, srcHeight, blend);
+		if (srcImage.alpha != -1) {
+			blend.SourceConstantAlpha = (byte)srcImage.alpha;
+			OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, blend);
+		} else {
+			long memDib = Image.createDIB(srcWidth, srcHeight, 32);
+			if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+			long memHdc = OS.CreateCompatibleDC(handle);
+			long oldMemBitmap = OS.SelectObject(memHdc, memDib);
+			BITMAP dibBM = new BITMAP();
+			OS.GetObject(memDib, BITMAP.sizeof, dibBM);
+			OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
+			byte[] srcData = new byte[dibBM.bmWidthBytes * dibBM.bmHeight];
+			OS.MoveMemory(srcData, dibBM.bmBits, srcData.length);
+			final int apinc = imgWidth - srcWidth;
+			int ap = srcY * imgWidth + srcX, sp = 0;
+			byte[] alphaData = srcImage.alphaData;
+			for (int y = 0; y < srcHeight; ++y) {
+				for (int x = 0; x < srcWidth; ++x) {
+					int alpha = alphaData[ap++] & 0xff;
+					int r = ((srcData[sp + 0] & 0xFF) * alpha) + 128;
+					r = (r + (r >> 8)) >> 8;
+					int g = ((srcData[sp + 1] & 0xFF) * alpha) + 128;
+					g = (g + (g >> 8)) >> 8;
+					int b = ((srcData[sp + 2] & 0xFF) * alpha) + 128;
+					b = (b + (b >> 8)) >> 8;
+					srcData[sp+0] = (byte)r;
+					srcData[sp+1] = (byte)g;
+					srcData[sp+2] = (byte)b;
+					srcData[sp+3] = (byte)alpha;
+					sp += 4;
+				}
+				ap += apinc;
+			}
+			OS.MoveMemory(dibBM.bmBits, srcData, srcData.length);
+			blend.SourceConstantAlpha = (byte)0xff;
+			blend.AlphaFormat = OS.AC_SRC_ALPHA;
+			OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, blend);
+			OS.SelectObject(memHdc, oldMemBitmap);
+			OS.DeleteDC(memHdc);
+			OS.DeleteObject(memDib);
+		}
 		OS.SelectObject(srcHdc, oldSrcBitmap);
 		OS.DeleteDC(srcHdc);
 		return;
@@ -1335,6 +1348,26 @@
 	byte[] srcData = new byte[sizeInBytes];
 	OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
 
+	/* Merge the alpha channel in place */
+	int alpha = srcImage.alpha;
+	final boolean hasAlphaChannel = (srcImage.alpha == -1);
+	if (hasAlphaChannel) {
+		final int apinc = imgWidth - srcWidth;
+		final int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+		int ap = srcY * imgWidth + srcX, sp = 3;
+		byte[] alphaData = srcImage.alphaData;
+		for (int y = 0; y < srcHeight; ++y) {
+			for (int x = 0; x < srcWidth; ++x) {
+				srcData[sp] = alphaData[ap++];
+				sp += 4;
+			}
+			ap += apinc;
+			sp += spinc;
+		}
+	}
+
+	/* Scale the foreground pixels with alpha */
+	OS.MoveMemory(dibBM.bmBits, srcData, sizeInBytes);
 	/*
 	* When drawing to a printer, StretchBlt does not correctly stretch if
 	* the source and destination HDCs are the same.  The workaround is to
@@ -1370,10 +1403,10 @@
 	int dp = 0;
 	for (int y = 0; y < destHeight; ++y) {
 		for (int x = 0; x < destWidth; ++x) {
-			int alpha = srcData[dp + 3] & 0xFF;
-			destData[dp    ] += (srcData[dp    ] & 0xFF) - (destData[dp    ] & 0xFF) * alpha / 255;
-			destData[dp + 1] += (srcData[dp + 1] & 0xFF) - (destData[dp + 1] & 0xFF) * alpha / 255;
-			destData[dp + 2] += (srcData[dp + 2] & 0xFF) - (destData[dp + 2] & 0xFF) * alpha / 255;
+			if (hasAlphaChannel) alpha = srcData[dp + 3] & 0xff;
+			destData[dp] += ((srcData[dp] & 0xff) - (destData[dp] & 0xff)) * alpha / 255;
+			destData[dp + 1] += ((srcData[dp + 1] & 0xff) - (destData[dp + 1] & 0xff)) * alpha / 255;
+			destData[dp + 2] += ((srcData[dp + 2] & 0xff) - (destData[dp + 2] & 0xff)) * alpha / 255;
 			dp += 4;
 		}
 		dp += dpinc;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
index 17cc993..c0766cc 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
@@ -112,6 +112,16 @@
 	GC memGC;
 
 	/**
+	 * the alpha data for the image
+	 */
+	byte[] alphaData;
+
+	/**
+	 * the global alpha value to be used for every pixel
+	 */
+	int alpha = -1;
+
+	/**
 	 * ImageFileNameProvider to provide file names at various Zoom levels
 	 */
 	private ImageFileNameProvider imageFileNameProvider;
@@ -273,6 +283,11 @@
 					device.internal_dispose_GC(hDC, null);
 
 					transparentPixel = srcImage.transparentPixel;
+					alpha = srcImage.alpha;
+					if (srcImage.alphaData != null) {
+						alphaData = new byte[srcImage.alphaData.length];
+						System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
+					}
 					break;
 				case SWT.ICON:
 					handle = OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0);
@@ -962,10 +977,9 @@
 long [] createGdipImage() {
 	switch (type) {
 		case SWT.BITMAP: {
-			BITMAP bm = new BITMAP();
-			OS.GetObject(handle, BITMAP.sizeof, bm);
-			int depth = bm.bmPlanes * bm.bmBitsPixel;
-			if (depth == 32 || transparentPixel != -1) {
+			if (alpha != -1 || alphaData != null || transparentPixel != -1) {
+				BITMAP bm = new BITMAP();
+				OS.GetObject(handle, BITMAP.sizeof, bm);
 				int imgWidth = bm.bmWidth;
 				int imgHeight = bm.bmHeight;
 				long hDC = device.internal_new_GC(null);
@@ -979,14 +993,8 @@
 				OS.GetObject(memDib, BITMAP.sizeof, dibBM);
 				int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
 				OS.BitBlt(memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
-				long hHeap = OS.GetProcessHeap();
-				long pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, sizeInBytes);
-				if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES);
 				byte red = 0, green = 0, blue = 0;
-				if (depth == 32) {
-					OS.MoveMemory(pixels, bm.bmBits, sizeInBytes);
-				}
-				else {
+				if (transparentPixel != -1) {
 					if (bm.bmBitsPixel <= 8)  {
 						byte[] color = new byte[4];
 						OS.GetDIBColorTable(srcHdc, transparentPixel, 1, color);
@@ -1021,8 +1029,30 @@
 								break;
 						}
 					}
-					byte[] srcData = new byte[sizeInBytes];
-					OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
+				}
+				OS.SelectObject(srcHdc, oldSrcBitmap);
+				OS.SelectObject(memHdc, oldMemBitmap);
+				OS.DeleteObject(srcHdc);
+				OS.DeleteObject(memHdc);
+				byte[] srcData = new byte[sizeInBytes];
+				OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
+				OS.DeleteObject(memDib);
+				device.internal_dispose_GC(hDC, null);
+				if (alpha != -1) {
+					for (int y = 0, dp = 0; y < imgHeight; ++y) {
+						for (int x = 0; x < imgWidth; ++x) {
+							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) {
+							srcData[dp + 3] = alphaData[ap++];
+							dp += 4;
+						}
+					}
+				} else if (transparentPixel != -1) {
 					for (int y = 0, dp = 0; y < imgHeight; ++y) {
 						for (int x = 0; x < imgWidth; ++x) {
 							if (srcData[dp] == blue && srcData[dp + 1] == green && srcData[dp + 2] == red) {
@@ -1033,15 +1063,12 @@
 							dp += 4;
 						}
 					}
-					OS.MoveMemory(pixels, srcData, sizeInBytes);
 				}
-				OS.SelectObject(srcHdc, oldSrcBitmap);
-				OS.SelectObject(memHdc, oldMemBitmap);
-				OS.DeleteObject(srcHdc);
-				OS.DeleteObject(memHdc);
-				OS.DeleteObject(memDib);
-				int pixelFormat = depth == 32 ? Gdip.PixelFormat32bppPARGB : Gdip.PixelFormat32bppARGB;
-				return new long []{Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, pixelFormat, pixels), pixels};
+				long hHeap = OS.GetProcessHeap();
+				long pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length);
+				if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+				OS.MoveMemory(pixels, srcData, sizeInBytes);
+				return new long []{Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels), pixels};
 			}
 			return new long []{Gdip.Bitmap_new(handle, 0), 0};
 		}
@@ -1606,32 +1633,10 @@
 			/* Construct and return the ImageData */
 			ImageData imageData = new ImageData(width, height, depth, palette, 4, data);
 			imageData.transparentPixel = this.transparentPixel;
-			if (depth == 32) {
-				byte straightData[] = new byte[imageSize];
-				byte alphaData[] = new byte[width * height];
-				boolean validAlpha = true;
-				for (int ap = 0, dp = 0; validAlpha && ap < alphaData.length; ap++, dp += 4) {
-					int b = data[dp    ] & 0xFF;
-					int g = data[dp + 1] & 0xFF;
-					int r = data[dp + 2] & 0xFF;
-					int a = data[dp + 3] & 0xFF;
-					alphaData[ap] = (byte) a;
-					validAlpha = validAlpha && b <= a && g <= a && r <= a;
-					if (a != 0) {
-						straightData[dp    ] = (byte) (((b * 0xFF) + a / 2) / a);
-						straightData[dp + 1] = (byte) (((g * 0xFF) + a / 2) / a);
-						straightData[dp + 2] = (byte) (((r * 0xFF) + a / 2) / a);
-					}
-				}
-				if (validAlpha) {
-					imageData.data = straightData;
-					imageData.alphaData = alphaData;
-				}
-				else {
-					for (int dp = 3; dp < imageSize; dp += 4) {
-						data[dp] = (byte) 0xFF;
-					}
-				}
+			imageData.alpha = alpha;
+			if (alpha == -1 && alphaData != null) {
+				imageData.alphaData = new byte[alphaData.length];
+				System.arraycopy(alphaData, 0, imageData.alphaData, 0, alphaData.length);
 			}
 			return imageData;
 		}
@@ -1724,9 +1729,6 @@
 		img.alphaData = i.alphaData;
 		i = img;
 	}
-
-	boolean hasAlpha = i.alpha != -1 || i.alphaData != null;
-
 	/*
 	 * Windows supports 16-bit mask of (0x7C00, 0x3E0, 0x1F),
 	 * 24-bit mask of (0xFF0000, 0xFF00, 0xFF) and 32-bit mask
@@ -1743,56 +1745,51 @@
 		int newOrder = ImageData.MSB_FIRST;
 		PaletteData newPalette = null;
 
-		if (hasAlpha) {
-			newDepth = 32;
-			newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
-		}
-		else {
-			switch (i.depth) {
-				case 8:
-					/*
-					 * Bug 566545. Usually each color mask selects a different part of the pixel
-					 * value to encode the according color. In this common case it is rather trivial
-					 * to convert an 8-bit direct color image to the Windows supported 16-bit image.
-					 * However there is no enforcement for the color masks to be disjunct. For
-					 * example an 8-bit image where all color masks select the same 8-bit of pixel
-					 * value (mask = 0xFF and shift = 0 for all colors) results in a very efficient
-					 * 8-bit gray-scale image without the need of defining a color table.
-					 *
-					 * That's why we need to calculate the actual required depth if all colors are
-					 * stored non-overlapping which might require 24-bit instead of the usual
-					 * expected 16-bit.
-					 */
-					int minDepth = ImageData.getChannelWidth(redMask, palette.redShift)
-							+ ImageData.getChannelWidth(greenMask, palette.greenShift)
-							+ ImageData.getChannelWidth(blueMask, palette.blueShift);
-					if (minDepth <= 16) {
-						newDepth = 16;
-						newOrder = ImageData.LSB_FIRST;
-						newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
-					} else {
-						newDepth = 24;
-						newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
-					}
-					break;
-				case 16:
+		switch (i.depth) {
+			case 8:
+				/*
+				 * Bug 566545. Usually each color mask selects a different part of the pixel
+				 * value to encode the according color. In this common case it is rather trivial
+				 * to convert an 8-bit direct color image to the Windows supported 16-bit image.
+				 * However there is no enforcement for the color masks to be disjunct. For
+				 * example an 8-bit image where all color masks select the same 8-bit of pixel
+				 * value (mask = 0xFF and shift = 0 for all colors) results in a very efficient
+				 * 8-bit gray-scale image without the need of defining a color table.
+				 *
+				 * That's why we need to calculate the actual required depth if all colors are
+				 * stored non-overlapping which might require 24-bit instead of the usual
+				 * expected 16-bit.
+				 */
+				int minDepth = ImageData.getChannelWidth(redMask, palette.redShift)
+						+ ImageData.getChannelWidth(greenMask, palette.greenShift)
+						+ ImageData.getChannelWidth(blueMask, palette.blueShift);
+				if (minDepth <= 16) {
+					newDepth = 16;
 					newOrder = ImageData.LSB_FIRST;
-					if (!(redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) {
-						newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
-					}
-					break;
-				case 24:
-					if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) {
-						newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
-					}
-					break;
-				case 32:
+					newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+				} else {
 					newDepth = 24;
 					newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
-					break;
-				default:
-					SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
-			}
+				}
+				break;
+			case 16:
+				newOrder = ImageData.LSB_FIRST;
+				if (!(redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) {
+					newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+				}
+				break;
+			case 24:
+				if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) {
+					newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+				}
+				break;
+			case 32:
+				if (!(redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
+					newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+				}
+				break;
+			default:
+				SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
 		}
 		if (newPalette != null) {
 			ImageData img = new ImageData(i.width, i.height, newDepth, newPalette);
@@ -1811,73 +1808,6 @@
 			i = img;
 		}
 	}
-	else if (hasAlpha) {
-		int newDepth = 32;
-		PaletteData newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
-		int newOrder = ImageData.MSB_FIRST;
-		RGB[] rgbs = i.palette.getRGBs();
-		int length = rgbs.length;
-		byte[] srcReds = new byte[length];
-		byte[] srcGreens = new byte[length];
-		byte[] srcBlues = new byte[length];
-		for (int j = 0; j < rgbs.length; j++) {
-			RGB rgb = rgbs[j];
-			if (rgb == null) continue;
-			srcReds[j] = (byte)rgb.red;
-			srcGreens[j] = (byte)rgb.green;
-			srcBlues[j] = (byte)rgb.blue;
-		}
-		ImageData img = new ImageData(i.width, i.height, newDepth, newPalette);
-		ImageData.blit(ImageData.BLIT_SRC,
-				i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, srcReds, srcGreens, srcBlues,
-				ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
-				img.data, img.depth, img.bytesPerLine, newOrder, 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
-				false, false);
-
-		if (i.transparentPixel != -1) {
-			img.transparentPixel = newPalette.getPixel(i.palette.getRGB(i.transparentPixel));
-		}
-		img.maskPad = i.maskPad;
-		img.maskData = i.maskData;
-		img.alpha = i.alpha;
-		img.alphaData = i.alphaData;
-		i = img;
-	}
-	if (i.alpha != -1) {
-		int alpha = i.alpha & 0xFF;
-		byte[] data = i.data;
-		for (int dp = 0; dp < i.data.length; dp += 4) {
-			/* pre-multiplied alpha */
-			int r = ((data[dp    ] & 0xFF) * alpha) + 128;
-			r = (r + (r >> 8)) >> 8;
-			int g = ((data[dp + 1] & 0xFF) * alpha) + 128;
-			g = (g + (g >> 8)) >> 8;
-			int b = ((data[dp + 2] & 0xFF) * alpha) + 128;
-			b = (b + (b >> 8)) >> 8;
-			data[dp    ] = (byte) b;
-			data[dp + 1] = (byte) g;
-			data[dp + 2] = (byte) r;
-			data[dp + 3] = (byte) alpha;
-		}
-	}
-	else if (i.alphaData != null) {
-		byte[] data = i.data;
-		for (int ap = 0, dp = 0; dp < i.data.length; ap++, dp += 4) {
-			/* pre-multiplied alpha */
-			int a = i.alphaData[ap] & 0xFF;
-			int r = ((data[dp    ] & 0xFF) * a) + 128;
-			r = (r + (r >> 8)) >> 8;
-			int g = ((data[dp + 1] & 0xFF) * a) + 128;
-			g = (g + (g >> 8)) >> 8;
-			int b = ((data[dp + 2] & 0xFF) * a) + 128;
-			b = (b + (b >> 8)) >> 8;
-			data[dp    ] = (byte) r;
-			data[dp + 1] = (byte) g;
-			data[dp + 2] = (byte) b;
-			data[dp + 3] = (byte) a;
-		}
-	}
-
 	/* Construct bitmap info header by hand */
 	RGB[] rgbs = i.palette.getRGBs();
 	BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
@@ -1964,6 +1894,14 @@
 			image.handle = hDib;
 			image.type = SWT.BITMAP;
 			image.transparentPixel = i.transparentPixel;
+			if (image.transparentPixel == -1) {
+				image.alpha = i.alpha;
+				if (i.alpha == -1 && i.alphaData != null) {
+					int length = i.alphaData.length;
+					image.alphaData = new byte[length];
+					System.arraycopy(i.alphaData, 0, image.alphaData, 0, length);
+				}
+			}
 		}
 	}
 	return result;