/// <summary> /// Gets a transparent bitmap given two non-transparent bitmaps drawn against a white and black background respectively. /// </summary> /// <param name="whiteBmp">A non-transparent bitmap drawn against a white background.</param> /// <param name="blackBmp">A non-transparent bitmap drawn against a black background.</param> /// <returns>A 32-bit bitmap with an alpha channel values that are set based on white and black bitmap interpolation.</returns> /// <exception cref="ArgumentException">Bitmaps must be of the same size and their pixel format must be Format32bppArgb.</exception> public static Bitmap GetTransparentBitmap(Bitmap whiteBmp, Bitmap blackBmp) { if (whiteBmp.Size != blackBmp.Size && whiteBmp.PixelFormat != blackBmp.PixelFormat && whiteBmp.PixelFormat != PixelFormat.Format32bppArgb) { throw new ArgumentException("Bitmaps must be of the same size and their pixel format must be Format32bppArgb."); } var bmp = new Bitmap(whiteBmp.Width, whiteBmp.Height, whiteBmp.PixelFormat); using (SmartBitmapLock oVals = new SmartBitmapLock(bmp), wVals = new SmartBitmapLock(whiteBmp), bVals = new SmartBitmapLock(blackBmp)) { for (var i = 0; i < oVals.Length; i++) { Color b = bVals[i], w = wVals[i]; if (w == Color.White && b == Color.Black) { oVals[i] = Color.FromArgb(0); } else if (w != b) { double oc, op; if (b == Color.Black) { oVals[i] = Color.FromArgb(255 - w.R, 0, 0, 0); continue; } if (w.R != b.R && b.R != 0) { oc = CalcOrigColor(w.R, b.R); op = b.R / oc; } else if (w.G != b.G && b.G != 0) { oc = CalcOrigColor(w.G, b.G); op = b.G / oc; } else { oc = CalcOrigColor(w.B, b.B); op = b.B / oc; } oVals[i] = Color.FromArgb(RoundBound(op * 255.0), RoundBound(b.R / op), RoundBound(b.G / op), RoundBound(b.B / op)); } else { oVals[i] = bVals[i]; } } } return(bmp); int RoundBound(double v) => (int)Math.Round(Math.Min(255.0, Math.Max(0.0, v))); double CalcOrigColor(byte w, byte b) => 255.0 * b / (255.0 - w + b); }
public void Dispose() { bmpLock = null; }
internal Enumertor(SmartBitmapLock bmp) { bmpLock = bmp; }