I have something that may be useful for you. The idea is save only the differences between the images and, with that, recreate later all images from starting image and saved changes.
To do this, you only need make a XOR operation in the image bytes. This method allow you get the difference (the array
parameter) between two images:
protected void ApplyXor(Bitmap img1, Bitmap img2, byte[] array)
{
const ImageLockMode rw = ImageLockMode.ReadWrite;
const PixelFormat argb = PixelFormat.Format32bppArgb;
var locked1 = img1.LockBits(new Rectangle(0, 0, img1.Width, img1.Height), rw, argb);
var locked2 = img2.LockBits(new Rectangle(0, 0, img2.Width, img2.Height), rw, argb);
try
{
ApplyXor(locked2, locked1, array);
}
finally
{
img1.UnlockBits(locked1);
img2.UnlockBits(locked2);
}
}
With the previous img1
bitmap and the array
returned, you can get the img2
with this method:
protected void ApplyXor(Bitmap img1, byte[] array, Bitmap img2)
{
const ImageLockMode rw = ImageLockMode.ReadWrite;
const PixelFormat argb = PixelFormat.Format32bppArgb;
var locked1 = img1.LockBits(new Rectangle(0, 0, img1.Width, img1.Height), rw, argb);
var locked2 = img2.LockBits(new Rectangle(0, 0, img2.Width, img2.Height), rw, argb);
try
{
ApplyXor(locked1, array, locked2);
}
finally
{
img1.UnlockBits(locked1);
img2.UnlockBits(locked2);
}
}
And here the other required methods:
private unsafe void ApplyXor(BitmapData img1, BitmapData img2, byte[] array)
{
byte* prev0 = (byte*)img1.Scan0.ToPointer();
byte* cur0 = (byte*)img2.Scan0.ToPointer();
int height = img1.Height;
int width = img1.Width;
int halfwidth = width / 2;
fixed (byte* target = array)
{
ulong* dst = (ulong*)target;
for (int y = 0; y < height; ++y)
{
ulong* prevRow = (ulong*)(prev0 + img1.Stride * y);
ulong* curRow = (ulong*)(cur0 + img2.Stride * y);
for (int x = 0; x < halfwidth; ++x)
{
if (curRow[x] != prevRow[x])
{
int a = 0;
}
*(dst++) = curRow[x] ^ prevRow[x];
}
}
}
}
private unsafe void ApplyXor(BitmapData img1, byte[] array, BitmapData img2)
{
byte* prev0 = (byte*)img1.Scan0.ToPointer();
byte* cur0 = (byte*)img2.Scan0.ToPointer();
int height = img1.Height;
int width = img1.Width;
int halfwidth = width / 2;
fixed (byte* target = array)
{
ulong* dst = (ulong*)target;
for (int y = 0; y < height; ++y)
{
ulong* prevRow = (ulong*)(prev0 + img1.Stride * y);
ulong* curRow = (ulong*)(cur0 + img2.Stride * y);
for (int x = 0; x < halfwidth; ++x)
{
curRow[x] = *(dst++) ^ prevRow[x];
}
}
}
}
NOTE: You must configure your project to allow unsafe.
With previous methods, you can do:
- Save a img1 bitmap
- Get img2 bitmap, do XOR and get the array (array2, for example)
- With img3, get the XOR with img2 (array3, for example). Now, img2 isn't needed
- With img4, get the XOR with img3 (array4). Now, img3 isn't needed
- ...
You have img1 and array2, array3, array4... and you can recreate all images:
- Make XOR between img1 and array2 to get img2
- Make XOR between img2 and array3 to get img3
- ...
If you need send video over TCP, you can send the images sending one image and the XOR arrays (the differences). Or better yet, compress the XOR arrays using K4os.Compression.LZ4.