public static Bitmap ForEachPixel(this Bitmap bitmapToModify, Action<PixelColor> colorModifier) { bitmapToModify.SafeLockBits(ImageLockMode.ReadWrite, bitmapData => { var bytesPerPixel = Image.GetPixelFormatSize(bitmapData.PixelFormat) / 8; var stride = bitmapData.Stride; unsafe { var ptrPixels = (byte*)(void*)bitmapData.Scan0; var offset = stride - bitmapToModify.Width * bytesPerPixel; var color1 = new PixelColor(); for (var y = 0; y < bitmapToModify.Height; y++) { for (var x = 0; x < bitmapToModify.Width; x++) { color1.FillTransportColor(ptrPixels) .Modify(colorModifier) .FillBitmapColor(ptrPixels); ptrPixels += bytesPerPixel; } ptrPixels += offset; } } }); return bitmapToModify; }
public static Bitmap ModifyColorsUsingBitmap(this Bitmap bitmapToModify, Bitmap sourceBitmap, Func<PixelColor, PixelColor, PixelColor> colorsMergeFunc) { bitmapToModify.SafeLockBits(ImageLockMode.ReadWrite, bitmapData => { sourceBitmap.SafeLockBits(ImageLockMode.ReadOnly, bitmapDataSrc => { var bytesPerPixel = Image.GetPixelFormatSize(bitmapDataSrc.PixelFormat) / 8; var stride = bitmapData.Stride; unsafe { var ptrPixels = (byte*)(void*)bitmapData.Scan0; var ptrPixelsSrc = (byte*)(void*)bitmapDataSrc.Scan0; var offset = stride - bitmapToModify.Width * bytesPerPixel; var color1 = new PixelColor(); var color2 = new PixelColor(); for (var y = 0; y < bitmapToModify.Height; y++) { for (var x = 0; x < bitmapToModify.Width; x++) { color1.FillTransportColor(ptrPixels); color2.FillTransportColor(ptrPixelsSrc); colorsMergeFunc(color1, color2).FillBitmapColor(ptrPixels); ptrPixels += bytesPerPixel; ptrPixelsSrc += bytesPerPixel; } ptrPixels += offset; ptrPixelsSrc += offset; } } }); }); return bitmapToModify; }