2015-03-31 18:38:16 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Drawing.Imaging;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Runtime.InteropServices;
|
2015-04-14 18:42:48 +00:00
|
|
|
|
using xServer.Core.Compression;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
|
|
|
|
namespace xServer.Core.Helper
|
|
|
|
|
{
|
2015-05-18 05:10:25 +00:00
|
|
|
|
public class UnsafeStreamCodec : IDisposable
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
private int _imageQuality;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2015-03-31 18:38:16 +00:00
|
|
|
|
public int ImageQuality
|
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
get { return _imageQuality; }
|
2015-03-31 18:38:16 +00:00
|
|
|
|
private set
|
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
lock (_imageProcessLock)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
_imageQuality = value;
|
2015-05-18 05:10:25 +00:00
|
|
|
|
|
|
|
|
|
if (_jpgCompression != null)
|
|
|
|
|
{
|
|
|
|
|
_jpgCompression.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
_jpgCompression = new JpgCompression(_imageQuality);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Size CheckBlock { get; private set; }
|
2015-03-31 20:37:38 +00:00
|
|
|
|
private byte[] _encodeBuffer;
|
|
|
|
|
private Bitmap _decodedBitmap;
|
|
|
|
|
private PixelFormat _encodedFormat;
|
|
|
|
|
private int _encodedWidth;
|
|
|
|
|
private int _encodedHeight;
|
2015-05-18 03:24:13 +00:00
|
|
|
|
private readonly object _imageProcessLock = new object();
|
2015-03-31 20:37:38 +00:00
|
|
|
|
private JpgCompression _jpgCompression;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
|
|
|
|
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
|
|
|
public static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count);
|
|
|
|
|
|
|
|
|
|
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
|
|
|
public static extern int memcmp(IntPtr ptr1, IntPtr ptr2, uint count);
|
|
|
|
|
|
|
|
|
|
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
|
|
|
public static extern int memcpy(IntPtr dst, IntPtr src, uint count);
|
|
|
|
|
|
|
|
|
|
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
|
|
|
public static extern unsafe int memcpy(void* dst, void* src, uint count);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initialize a new object of UnsafeStreamCodec
|
|
|
|
|
/// </summary>
|
2015-03-31 20:37:38 +00:00
|
|
|
|
/// <param name="imageQuality">The quality to use between 0-100</param>
|
2015-04-02 08:26:57 +00:00
|
|
|
|
public UnsafeStreamCodec(int imageQuality = 100)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
|
|
|
|
this.CheckBlock = new Size(50, 1);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-18 05:10:25 +00:00
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
Dispose(true);
|
|
|
|
|
|
|
|
|
|
// Tell the Garbage Collector to not waste time finalizing this object
|
|
|
|
|
// since we took care of it.
|
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
|
{
|
|
|
|
|
if (disposing)
|
|
|
|
|
{
|
|
|
|
|
if (_decodedBitmap != null)
|
|
|
|
|
{
|
|
|
|
|
_decodedBitmap.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_jpgCompression != null)
|
|
|
|
|
{
|
|
|
|
|
_jpgCompression.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
public unsafe void CodeImage(IntPtr scan0, Rectangle scanArea, Size imageSize, PixelFormat format, Stream outStream)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
lock (_imageProcessLock)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-05-18 04:37:12 +00:00
|
|
|
|
byte* pScan0 = (byte*)scan0.ToInt32();
|
|
|
|
|
|
2015-03-31 18:38:16 +00:00
|
|
|
|
if (!outStream.CanWrite)
|
2015-05-18 04:37:12 +00:00
|
|
|
|
{
|
2015-03-31 18:38:16 +00:00
|
|
|
|
throw new Exception("Must have access to Write in the Stream");
|
2015-05-18 04:37:12 +00:00
|
|
|
|
}
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
int stride = 0;
|
|
|
|
|
int rawLength = 0;
|
|
|
|
|
int pixelSize = 0;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
switch (format)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
|
|
|
|
case PixelFormat.Format24bppRgb:
|
|
|
|
|
case PixelFormat.Format32bppRgb:
|
2015-03-31 20:37:38 +00:00
|
|
|
|
pixelSize = 3;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
break;
|
|
|
|
|
case PixelFormat.Format32bppArgb:
|
|
|
|
|
case PixelFormat.Format32bppPArgb:
|
2015-03-31 20:37:38 +00:00
|
|
|
|
pixelSize = 4;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2015-03-31 20:37:38 +00:00
|
|
|
|
throw new NotSupportedException(format.ToString());
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
stride = imageSize.Width * pixelSize;
|
|
|
|
|
rawLength = stride * imageSize.Height;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
if (_encodeBuffer == null)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
this._encodedFormat = format;
|
|
|
|
|
this._encodedWidth = imageSize.Width;
|
|
|
|
|
this._encodedHeight = imageSize.Height;
|
|
|
|
|
this._encodeBuffer = new byte[rawLength];
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
fixed (byte* ptr = _encodeBuffer)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] temp = null;
|
2015-03-31 20:37:38 +00:00
|
|
|
|
using (Bitmap tmpBmp = new Bitmap(imageSize.Width, imageSize.Height, stride, format, scan0))
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
temp = _jpgCompression.Compress(tmpBmp);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4);
|
|
|
|
|
outStream.Write(temp, 0, temp.Length);
|
2015-05-18 04:37:12 +00:00
|
|
|
|
memcpy(new IntPtr(ptr), scan0, (uint)rawLength);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
if (this._encodedFormat != format)
|
2015-05-18 04:37:12 +00:00
|
|
|
|
{
|
2015-03-31 18:38:16 +00:00
|
|
|
|
throw new Exception("PixelFormat is not equal to previous Bitmap");
|
2015-05-18 04:37:12 +00:00
|
|
|
|
}
|
|
|
|
|
else if (this._encodedWidth != imageSize.Width || this._encodedHeight != imageSize.Height)
|
|
|
|
|
{
|
2015-03-31 18:38:16 +00:00
|
|
|
|
throw new Exception("Bitmap width/height are not equal to previous bitmap");
|
2015-05-18 04:37:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long oldPos = outStream.Position;
|
|
|
|
|
outStream.Write(new byte[4], 0, 4);
|
|
|
|
|
long totalDataLength = 0;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
List<Rectangle> blocks = new List<Rectangle>();
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
Size s = new Size(scanArea.Width, CheckBlock.Height);
|
2015-05-18 04:37:12 +00:00
|
|
|
|
Size lastSize = new Size(scanArea.Width % CheckBlock.Width, scanArea.Height % CheckBlock.Height);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
int lasty = scanArea.Height - lastSize.Height;
|
|
|
|
|
int lastx = scanArea.Width - lastSize.Width;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
|
|
|
|
Rectangle cBlock = new Rectangle();
|
|
|
|
|
List<Rectangle> finalUpdates = new List<Rectangle>();
|
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
s = new Size(scanArea.Width, s.Height);
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
fixed (byte* encBuffer = _encodeBuffer)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
var index = 0;
|
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
for (int y = scanArea.Y; y != scanArea.Height; y += s.Height)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
|
|
|
|
if (y == lasty)
|
2015-05-18 04:37:12 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
s = new Size(scanArea.Width, lastSize.Height);
|
2015-05-18 04:37:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
cBlock = new Rectangle(scanArea.X, y, scanArea.Width, s.Height);
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
int offset = (y * stride) + (scanArea.X * pixelSize);
|
|
|
|
|
|
|
|
|
|
if (memcmp(encBuffer + offset, pScan0 + offset, (uint)stride) != 0)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
index = blocks.Count - 1;
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
if (blocks.Count != 0 && (blocks[index].Y + blocks[index].Height) == cBlock.Y)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-04-21 18:27:52 +00:00
|
|
|
|
cBlock = new Rectangle(blocks[index].X, blocks[index].Y, blocks[index].Width,
|
2015-05-18 04:37:12 +00:00
|
|
|
|
blocks[index].Height + cBlock.Height);
|
2015-03-31 20:37:38 +00:00
|
|
|
|
blocks[index] = cBlock;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
blocks.Add(cBlock);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-02 08:26:57 +00:00
|
|
|
|
for (int i = 0; i < blocks.Count; i++)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
s = new Size(CheckBlock.Width, blocks[i].Height);
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
|
|
|
|
for (int x = scanArea.X; x != scanArea.Width; x += s.Width)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
|
|
|
|
if (x == lastx)
|
2015-05-18 04:37:12 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
s = new Size(lastSize.Width, blocks[i].Height);
|
2015-05-18 04:37:12 +00:00
|
|
|
|
}
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
cBlock = new Rectangle(x, blocks[i].Y, s.Width, blocks[i].Height);
|
|
|
|
|
bool foundChanges = false;
|
2015-05-18 04:37:12 +00:00
|
|
|
|
uint blockStride = (uint)(pixelSize * cBlock.Width);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
|
|
|
|
for (int j = 0; j < cBlock.Height; j++)
|
|
|
|
|
{
|
2015-05-18 04:37:12 +00:00
|
|
|
|
int blockOffset = (stride * (cBlock.Y + j)) + (pixelSize * cBlock.X);
|
|
|
|
|
|
|
|
|
|
if (memcmp(encBuffer + blockOffset, pScan0 + blockOffset, blockStride) != 0)
|
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
foundChanges = true;
|
2015-05-18 04:37:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(encBuffer + blockOffset, pScan0 + blockOffset, blockStride);
|
|
|
|
|
//copy-changes
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
if (foundChanges)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
|
|
|
|
index = finalUpdates.Count - 1;
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
|
|
|
|
if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
|
|
|
|
Rectangle rect = finalUpdates[index];
|
|
|
|
|
int newWidth = cBlock.Width + rect.Width;
|
|
|
|
|
cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height);
|
|
|
|
|
finalUpdates[index] = cBlock;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
finalUpdates.Add(cBlock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < finalUpdates.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
Rectangle rect = finalUpdates[i];
|
2015-05-18 04:37:12 +00:00
|
|
|
|
int blockStride = pixelSize * rect.Width;
|
|
|
|
|
|
|
|
|
|
Bitmap tmpBmp = null;
|
|
|
|
|
BitmapData tmpData = null;
|
|
|
|
|
long length;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
try
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-05-18 04:37:12 +00:00
|
|
|
|
tmpBmp = new Bitmap(rect.Width, rect.Height, format);
|
|
|
|
|
tmpData = tmpBmp.LockBits(new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height),
|
|
|
|
|
ImageLockMode.ReadWrite, tmpBmp.PixelFormat);
|
|
|
|
|
|
|
|
|
|
for (int j = 0, offset = 0; j < rect.Height; j++)
|
|
|
|
|
{
|
|
|
|
|
int blockOffset = (stride * (rect.Y + j)) + (pixelSize * rect.X);
|
|
|
|
|
memcpy((byte*)tmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride);
|
2015-04-21 18:27:52 +00:00
|
|
|
|
//copy-changes
|
2015-05-18 04:37:12 +00:00
|
|
|
|
offset += blockStride;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outStream.Write(BitConverter.GetBytes(rect.X), 0, 4);
|
|
|
|
|
outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4);
|
|
|
|
|
outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4);
|
|
|
|
|
outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4);
|
|
|
|
|
outStream.Write(new byte[4], 0, 4);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
length = outStream.Length;
|
|
|
|
|
long OldPos = outStream.Position;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
_jpgCompression.Compress(tmpBmp, ref outStream);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
length = outStream.Position - length;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
outStream.Position = OldPos - 4;
|
|
|
|
|
outStream.Write(BitConverter.GetBytes(length), 0, 4);
|
|
|
|
|
outStream.Position += length;
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
tmpBmp.UnlockBits(tmpData);
|
|
|
|
|
tmpBmp.Dispose();
|
|
|
|
|
}
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
totalDataLength += length + (4 * 5);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outStream.Position = oldPos;
|
2015-03-31 20:37:38 +00:00
|
|
|
|
outStream.Write(BitConverter.GetBytes(totalDataLength), 0, 4);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
public unsafe Bitmap DecodeData(IntPtr codecBuffer, uint length)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
if (length < 4)
|
2015-05-18 04:37:12 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
return _decodedBitmap;
|
2015-05-18 04:37:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int dataSize = *(int*)(codecBuffer);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
if (_decodedBitmap == null)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
byte[] temp = new byte[dataSize];
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
2015-03-31 18:38:16 +00:00
|
|
|
|
fixed (byte* tempPtr = temp)
|
|
|
|
|
{
|
2015-05-18 04:37:12 +00:00
|
|
|
|
memcpy(new IntPtr(tempPtr), new IntPtr(codecBuffer.ToInt32() + 4), (uint)dataSize);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-18 04:37:12 +00:00
|
|
|
|
this._decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp));
|
|
|
|
|
|
|
|
|
|
return _decodedBitmap;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
return _decodedBitmap;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Bitmap DecodeData(Stream inStream)
|
|
|
|
|
{
|
|
|
|
|
byte[] temp = new byte[4];
|
|
|
|
|
inStream.Read(temp, 0, 4);
|
2015-03-31 20:37:38 +00:00
|
|
|
|
int dataSize = BitConverter.ToInt32(temp, 0);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
if (_decodedBitmap == null)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
temp = new byte[dataSize];
|
2015-03-31 18:38:16 +00:00
|
|
|
|
inStream.Read(temp, 0, temp.Length);
|
2015-05-18 04:37:12 +00:00
|
|
|
|
this._decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp));
|
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
return _decodedBitmap;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
using (Graphics g = Graphics.FromImage(_decodedBitmap))
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-03-31 20:37:38 +00:00
|
|
|
|
while (dataSize > 0)
|
2015-03-31 18:38:16 +00:00
|
|
|
|
{
|
2015-05-18 04:37:12 +00:00
|
|
|
|
byte[] tempData = new byte[4 * 5];
|
2015-03-31 18:38:16 +00:00
|
|
|
|
inStream.Read(tempData, 0, tempData.Length);
|
|
|
|
|
|
|
|
|
|
Rectangle rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4),
|
2015-05-18 04:37:12 +00:00
|
|
|
|
BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12));
|
2015-03-31 20:37:38 +00:00
|
|
|
|
int updateLen = BitConverter.ToInt32(tempData, 16);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
byte[] buffer = new byte[updateLen];
|
2015-03-31 18:38:16 +00:00
|
|
|
|
inStream.Read(buffer, 0, buffer.Length);
|
|
|
|
|
|
|
|
|
|
using (MemoryStream m = new MemoryStream(buffer))
|
|
|
|
|
{
|
2015-05-18 04:37:12 +00:00
|
|
|
|
using (Bitmap tmp = (Bitmap)Image.FromStream(m))
|
|
|
|
|
{
|
|
|
|
|
g.DrawImage(tmp, rect.Location);
|
|
|
|
|
}
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
|
|
|
|
dataSize -= updateLen + (4 * 5);
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-18 04:37:12 +00:00
|
|
|
|
|
2015-03-31 20:37:38 +00:00
|
|
|
|
return _decodedBitmap;
|
2015-03-31 18:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
}
|