我正在创建一个屏幕共享应用程序,它捕获屏幕并将其分成小块,并与memcmp
进行比较,而不是仅发送差异。
但是,有时它可以达到200~300kb!当然,它实际上使传输速度非常慢,所以我想听听如何优化我的程序的有效性。
这实际上是图像扫描码:
private int _imageQuality;
private byte[] _encodeBuffer;
private Bitmap _decodedBitmap;
private PixelFormat _encodedFormat;
private int _encodedWidth;
private int _encodedHeight;
private readonly object _imageProcessLock = new object();
private JpgCompression _jpgCompression;
public unsafe void CodeImage(IntPtr scan0, Rectangle scanArea, Size imageSize, PixelFormat format,
Stream outStream)
{
lock (_imageProcessLock)
{
byte* pScan0 = (byte*)scan0.ToInt32();
int stride = 0;
int rawLength = 0;
int pixelSize = 4;
// MessageBox.Show(pixelSize.ToString());
stride = imageSize.Width * pixelSize;
rawLength = stride * imageSize.Height;
if (_encodeBuffer == null)
{
this._encodedFormat = format;
this._encodedWidth = imageSize.Width;
this._encodedHeight = imageSize.Height;
this._encodeBuffer = new byte[rawLength];
fixed (byte* ptr = _encodeBuffer)
{
byte[] temp = null;
using (Bitmap tmpBmp = new Bitmap(imageSize.Width, imageSize.Height, stride, format, scan0))
{
temp = _jpgCompression.Compress(tmpBmp);
}
outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4);
// MessageBox.Show(temp.Length.ToString());
outStream.Write(temp, 0, temp.Length);
NativeMethods.memcpy(new IntPtr(ptr), scan0, (uint)rawLength);
}
return;
}
long oldPos = outStream.Position;
outStream.Write(new byte[4], 0, 4);
long totalDataLength = 0;
List<Rectangle> blocks = new List<Rectangle>();
Size s = new Size(scanArea.Width, CheckBlock.Height);
Size lastSize = new Size(scanArea.Width % CheckBlock.Width, scanArea.Height % CheckBlock.Height);
int lasty = scanArea.Height - lastSize.Height;
int lastx = scanArea.Width - lastSize.Width;
Rectangle cBlock = new Rectangle();
List<Rectangle> finalUpdates = new List<Rectangle>();
s = new Size(scanArea.Width, s.Height);
fixed (byte* encBuffer = _encodeBuffer)
{
var index = 0;
for (int y = scanArea.Y; y != scanArea.Height; y += s.Height)
{
if (y == lasty)
{
s = new Size(scanArea.Width, lastSize.Height);
}
cBlock = new Rectangle(scanArea.X, y, scanArea.Width, s.Height);
int offset = (y * stride) + (scanArea.X * pixelSize);
if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)stride) != 0)
{
index = blocks.Count - 1;
if (blocks.Count != 0 && (blocks[index].Y + blocks[index].Height) == cBlock.Y)
{
cBlock = new Rectangle(blocks[index].X, blocks[index].Y, blocks[index].Width,
blocks[index].Height + cBlock.Height);
blocks[index] = cBlock;
}
else
{
blocks.Add(cBlock);
}
}
}
for (int i = 0; i < blocks.Count; i++)
{
s = new Size(CheckBlock.Width, blocks[i].Height);
for (int x = scanArea.X; x != scanArea.Width; x += s.Width)
{
if (x == lastx)
{
s = new Size(lastSize.Width, blocks[i].Height);
}
cBlock = new Rectangle(x, blocks[i].Y, s.Width, blocks[i].Height);
bool foundChanges = false;
uint blockStride = (uint)(pixelSize * cBlock.Width);
for (int j = 0; j < cBlock.Height; j++)
{
int blockOffset = (stride * (cBlock.Y + j)) + (pixelSize * cBlock.X);
if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, blockStride) != 0)
{
foundChanges = true;
}
NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, blockStride);
//copy-changes
}
if (foundChanges)
{
index = finalUpdates.Count - 1;
if (finalUpdates.Count > 0 &&
(finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X)
{
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];
int blockStride = pixelSize * rect.Width;
Bitmap tmpBmp = null;
BitmapData tmpData = null;
long length;
try
{
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);
NativeMethods.memcpy((byte*)tmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride);
//copy-changes
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);
length = outStream.Length;
long old = outStream.Position;
_jpgCompression.Compress(tmpBmp, ref outStream);
length = outStream.Position - length;
outStream.Position = old - 4;
outStream.Write(BitConverter.GetBytes(length), 0, 4);
outStream.Position += length;
}
finally
{
tmpBmp.UnlockBits(tmpData);
tmpBmp.Dispose();
}
totalDataLength += length + (4 * 5);
}
outStream.Position = oldPos;
outStream.Write(BitConverter.GetBytes(totalDataLength), 0, 4);
}
}
我试过gzip,lz4,这些都可以压缩1kb最大......它没有真正帮助.. 我将不胜感激任何帮助!非常感谢你。