// Given three images, return an image that highlights the differences in common betwen the main image and the first image // and the main image and a second image. public static unsafe WriteableBitmap CombinedDifference(this WriteableBitmap unaltered, WriteableBitmap previous, WriteableBitmap next, byte threshold) { // Check the arguments for null ThrowIf.IsNullArgument(unaltered, nameof(unaltered)); ThrowIf.IsNullArgument(previous, nameof(previous)); ThrowIf.IsNullArgument(next, nameof(next)); if (WriteableBitmapExtensions.BitmapsMismatched(unaltered, previous) || WriteableBitmapExtensions.BitmapsMismatched(unaltered, next)) { return(null); } WriteableBitmapExtensions.GetColorOffsets(unaltered, out int blueOffset, out int greenOffset, out int redOffset); int totalPixels = unaltered.PixelWidth * unaltered.PixelHeight; int pixelSizeInBytes = unaltered.Format.BitsPerPixel / 8; byte *unalteredIndex = (byte *)unaltered.BackBuffer.ToPointer(); byte *previousIndex = (byte *)previous.BackBuffer.ToPointer(); byte *nextIndex = (byte *)next.BackBuffer.ToPointer(); byte[] differencePixels = new byte[totalPixels * pixelSizeInBytes]; int differenceIndex = 0; for (int pixel = 0; pixel < totalPixels; ++pixel) { byte b1 = (byte)Math.Abs(*(unalteredIndex + blueOffset) - *(previousIndex + blueOffset)); byte g1 = (byte)Math.Abs(*(unalteredIndex + greenOffset) - *(previousIndex + greenOffset)); byte r1 = (byte)Math.Abs(*(unalteredIndex + redOffset) - *(previousIndex + redOffset)); byte b2 = (byte)Math.Abs(*(unalteredIndex + blueOffset) - *(nextIndex + blueOffset)); byte g2 = (byte)Math.Abs(*(unalteredIndex + greenOffset) - *(nextIndex + greenOffset)); byte r2 = (byte)Math.Abs(*(unalteredIndex + redOffset) - *(nextIndex + redOffset)); byte b = WriteableBitmapExtensions.DifferenceIfAboveThreshold(threshold, b1, b2); byte g = WriteableBitmapExtensions.DifferenceIfAboveThreshold(threshold, g1, g2); byte r = WriteableBitmapExtensions.DifferenceIfAboveThreshold(threshold, r1, r2); byte averageDifference = (byte)((b + g + r) / 3); differencePixels[differenceIndex + blueOffset] = averageDifference; differencePixels[differenceIndex + greenOffset] = averageDifference; differencePixels[differenceIndex + redOffset] = averageDifference; unalteredIndex += pixelSizeInBytes; previousIndex += pixelSizeInBytes; nextIndex += pixelSizeInBytes; differenceIndex += pixelSizeInBytes; } WriteableBitmap difference = new WriteableBitmap(BitmapSource.Create(unaltered.PixelWidth, unaltered.PixelHeight, unaltered.DpiX, unaltered.DpiY, unaltered.Format, unaltered.Palette, differencePixels, unaltered.BackBufferStride)); return(difference); }
// Given two images, return an image containing the visual difference between them public static unsafe WriteableBitmap Subtract(this WriteableBitmap image1, WriteableBitmap image2) { // Check the arguments for null ThrowIf.IsNullArgument(image1, nameof(image1)); ThrowIf.IsNullArgument(image2, nameof(image2)); if (WriteableBitmapExtensions.BitmapsMismatched(image1, image2)) { return(null); } WriteableBitmapExtensions.GetColorOffsets(image1, out int blueOffset, out int greenOffset, out int redOffset); int totalPixels = image1.PixelWidth * image1.PixelHeight; int pixelSizeInBytes = image1.Format.BitsPerPixel / 8; byte *image1Index = (byte *)image1.BackBuffer.ToPointer(); byte *image2Index = (byte *)image2.BackBuffer.ToPointer(); byte[] differencePixels = new byte[totalPixels * pixelSizeInBytes]; int differenceIndex = 0; for (int pixel = 0; pixel < totalPixels; ++pixel) { byte b = (byte)Math.Abs(*(image1Index + blueOffset) - *(image2Index + blueOffset)); byte g = (byte)Math.Abs(*(image1Index + greenOffset) - *(image2Index + greenOffset)); byte r = (byte)Math.Abs(*(image1Index + redOffset) - *(image2Index + redOffset)); byte averageDifference = (byte)((b + g + r) / 3); differencePixels[differenceIndex + blueOffset] = averageDifference; differencePixels[differenceIndex + greenOffset] = averageDifference; differencePixels[differenceIndex + redOffset] = averageDifference; image1Index += pixelSizeInBytes; image2Index += pixelSizeInBytes; differenceIndex += pixelSizeInBytes; } WriteableBitmap difference = new WriteableBitmap(BitmapSource.Create(image1.PixelWidth, image1.PixelHeight, image1.DpiX, image1.DpiY, image1.Format, image1.Palette, differencePixels, image1.BackBufferStride)); return(difference); }