diff options
Diffstat (limited to 'Software/Visual_Studio/Tango.RemoteDesktop/Comparers/VectorBitmapComparer.cs')
| -rw-r--r-- | Software/Visual_Studio/Tango.RemoteDesktop/Comparers/VectorBitmapComparer.cs | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Comparers/VectorBitmapComparer.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Comparers/VectorBitmapComparer.cs new file mode 100644 index 000000000..2500e8ac7 --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Comparers/VectorBitmapComparer.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Tango.RemoteDesktop.Frames; + +namespace Tango.RemoteDesktop.Comparers +{ + /// <summary> + /// Represents a vector <see cref="IBitmapComparer{TFrame}"/> comparer which will compare and return a <see cref="VectorFrame"/> difference. + /// </summary> + /// <seealso cref="Tango.RemoteDesktop.IBitmapComparer{Tango.RemoteDesktop.Frames.VectorFrame}" /> + public class VectorBitmapComparer : IBitmapComparer<VectorFrame> + { + /// <summary> + /// Creates the difference as <see cref="VectorFrame"/>. + /// </summary> + /// <param name="previousBitmap">The previous bitmap.</param> + /// <param name="currentBitmap">The current bitmap.</param> + /// <returns></returns> + /// <exception cref="InvalidOperationException"> + /// Cannot compare image. They are the same instance + /// or + /// Cannot compare image of different size. + /// </exception> + public unsafe BitmapComparerResult<VectorFrame> CreateDifference(Bitmap previousBitmap, Bitmap currentBitmap) + { + VectorFrame vector = new VectorFrame(previousBitmap.Width, previousBitmap.Height); + + bool hasDifference = false; + + if (previousBitmap == null | currentBitmap == null) + throw new InvalidOperationException("Cannot compare image. They are the same instance"); + + if (previousBitmap.Height != currentBitmap.Height || previousBitmap.Width != currentBitmap.Width) + throw new InvalidOperationException("Cannot compare image of different size."); + + int height = previousBitmap.Height; + int width = previousBitmap.Width; + + BitmapData data1 = previousBitmap.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + BitmapData data2 = currentBitmap.LockBits(new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + byte* data1Ptr = (byte*)data1.Scan0; + byte* data2Ptr = (byte*)data2.Scan0; + + int rowPadding = data1.Stride - (previousBitmap.Width * 4); + + // iterate over height (rows) + for (int i = 0; i < height; i++) + { + // iterate over width (columns) + for (int j = 0; j < width; j++) + { + int same = 0; + + byte[] tmp = new byte[4]; + + // compare pixels and copy new values into temporary array + for (int x = 0; x < 4; x++) + { + tmp[x] = data2Ptr[0]; + if (data1Ptr[0] == data2Ptr[0]) + { + same++; + } + data1Ptr++; // advance image1 ptr + data2Ptr++; // advance image2 ptr + } + + if (same != 4) + { + int colorIndex = vector.Colors.Count; + + VectorFrameColor color = new VectorFrameColor() + { + B = tmp[0], + G = tmp[1], + R = tmp[2], + Index = colorIndex + }; + + VectorFrameColor existingColor; + + if (vector.Colors.TryGetValue(color.ToInt32(), out existingColor)) + { + colorIndex = existingColor.Index; + } + else + { + vector.Colors.Add(color.ToInt32(), color); + } + + vector.Pixels.Add(new VectorFramePixel() + { + X = j, + Y = i, + ColorIndex = colorIndex, + Color = color + }); + + hasDifference = true; + } + } + + // at the end of each column, skip extra padding + if (rowPadding > 0) + { + data1Ptr += rowPadding; + data2Ptr += rowPadding; + } + } + + previousBitmap.UnlockBits(data1); + currentBitmap.UnlockBits(data2); + + return new BitmapComparerResult<VectorFrame>() + { + Frame = vector, + ContainsDifference = hasDifference + }; + } + } +} |
