/// <summary> /// Iterate over each pixel of <paramref name="bitmap"/> and passes the pixel values to <paramref name="currPixelAction"/> /// </summary> /// <param name="bitmap">The bitmap to modify</param> /// <param name="softwareBitmap">the reference bitmap</param> /// <param name="currPixelAction">The pixel action which should be called</param> /// <param name="editPixelOperatorsList">edit pixels instance</param> public static unsafe void EditPixels(this SoftwareBitmap bitmap, SoftwareBitmap softwareBitmap, ActionRefs <byte> currPixelAction = null, IEnumerable <IEditPixelOperator> editPixelOperatorsList = null) { if (bitmap == null) { throw new ArgumentException(nameof(currPixelAction)); } if (softwareBitmap == null) { throw new ArgumentException(nameof(softwareBitmap)); } if (bitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8) { throw new ArgumentException(nameof(bitmap), $"{BitmapPixelFormat.Bgra8} expected"); } if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8) { throw new ArgumentException(nameof(softwareBitmap), $"{BitmapPixelFormat.Bgra8} expected"); } if (editPixelOperatorsList == null) { editPixelOperatorsList = new List <IEditPixelOperators>(); } // Effect is hard-coded to operate on BGRA8 format only if (bitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8 && softwareBitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8) { // In BGRA8 format, each pixel is defined by 4 bytes const int BYTES_PER_PIXEL = 4; using (BitmapBuffer bufferBitmap = bitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite)) using (IMemoryBufferReference referenceBitmap = bufferBitmap.CreateReference()) using (BitmapBuffer bufferSoftwareBitmap = softwareBitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite)) using (IMemoryBufferReference referenceSoftwareBitmap = bufferSoftwareBitmap.CreateReference()) { // Get a pointer to the pixel buffer byte *dataBitmap; uint capacityBitmap; ((IMemoryBufferByteAccess)referenceBitmap).GetBuffer(out dataBitmap, out capacityBitmap); byte *dataSoftwareBitmap; uint capacitySoftwareBitmap; ((IMemoryBufferByteAccess)referenceSoftwareBitmap).GetBuffer(out dataSoftwareBitmap, out capacitySoftwareBitmap); // Get information about the BitmapBuffer BitmapPlaneDescription descBitmap = bufferBitmap.GetPlaneDescription(0); BitmapPlaneDescription descSoftwarebitmap = bufferSoftwareBitmap.GetPlaneDescription(0); if (descBitmap.Width != descSoftwarebitmap.Width || descBitmap.Height != descSoftwarebitmap.Height) { throw new ArgumentException(nameof(descSoftwarebitmap), $"Diffrent {nameof(descBitmap.Width)} or {nameof(descBitmap.Height)}"); } // Iterate over all pixels for (uint row = 0; row < descBitmap.Height; row++) { for (uint col = 0; col < descBitmap.Width; col++) { // 8 bit or 1 byte for one data field 0... 255 // Index of the current pixel in the buffer (defined by the next 4 bytes, BGRA8) long currPixelBitmap = descBitmap.StartIndex + descBitmap.Stride * row + BYTES_PER_PIXEL * col; long currPixelSoftwareBitmap = descSoftwarebitmap.StartIndex + descSoftwarebitmap.Stride * row + BYTES_PER_PIXEL * col; // Read the current pixel information into b,g,r channels (leave out alpha channel) currPixelAction?.Invoke( //bitmap ref dataBitmap[currPixelBitmap + 0], ref dataBitmap[currPixelBitmap + 1], ref dataBitmap[currPixelBitmap + 2], ref dataBitmap[currPixelBitmap + 3], //softwareBitmap ref dataSoftwareBitmap[currPixelSoftwareBitmap + 0], ref dataSoftwareBitmap[currPixelSoftwareBitmap + 1], ref dataSoftwareBitmap[currPixelSoftwareBitmap + 2], ref dataSoftwareBitmap[currPixelSoftwareBitmap + 3] ); foreach (IEditPixelOperator editPixelOperators in editPixelOperatorsList) { if (editPixelOperators is IEditPixelOperators pixelOperators) { pixelOperators.EditPixels( //bitmap ref dataBitmap[currPixelBitmap + 0], ref dataBitmap[currPixelBitmap + 1], ref dataBitmap[currPixelBitmap + 2], ref dataBitmap[currPixelBitmap + 3], //softwareBitmap ref dataSoftwareBitmap[currPixelSoftwareBitmap + 0], ref dataSoftwareBitmap[currPixelSoftwareBitmap + 1], ref dataSoftwareBitmap[currPixelSoftwareBitmap + 2], ref dataSoftwareBitmap[currPixelSoftwareBitmap + 3] ); } else { editPixelOperators.EditPixel( //bitmap ref dataBitmap[currPixelBitmap + 0], ref dataBitmap[currPixelBitmap + 1], ref dataBitmap[currPixelBitmap + 2], ref dataBitmap[currPixelBitmap + 3]); } } } } foreach (IEditPixelOperator editPixelOperators in editPixelOperatorsList) { editPixelOperators.SetResult(); } } } }
public static unsafe void EditPixels(this SoftwareBitmap bitmap, SoftwareBitmap softwareBitmap, ActionRefs <byte> currPixelAction) { EditPixels(bitmap, softwareBitmap, currPixelAction, null); }