有两个指针(byte *)为1. B8G8R8A8像素数据2.字节缓冲区放置裁剪像素数据,非常简单的问题。这是我的实施:
private unsafe void Crop(byte* src, byte* dst, Rectangle rSrc, Rectangle rDst)
{
int sSrc = 4 * rSrc.Width, sDst = 4 * rDst.Width; // stride
for (int x = 0; x < rDst.Width; x++) for (int y = 0; y < rDst.Height; y++)
{
dst[(x * 4 + y * (sDst)) + 0] = src[((rDst.X + x) * 4 + (rDst.Y + y) * (sSrc)) + 0];
dst[(x * 4 + y * (sDst)) + 1] = src[((rDst.X + x) * 4 + (rDst.Y + y) * (sSrc)) + 1];
dst[(x * 4 + y * (sDst)) + 2] = src[((rDst.X + x) * 4 + (rDst.Y + y) * (sSrc)) + 2];
dst[(x * 4 + y * (sDst)) + 3] = src[((rDst.X + x) * 4 + (rDst.Y + y) * (sSrc)) + 3];
}
}
它的工作原理:1920x1080约为100ms,但需要~10 - 15 ms。有可能让它更快吗?例如,普通副本(没有裁剪)提供了更好的性能8毫秒(对于相同的分辨率),这里是函数:
private unsafe void Copy(void* dst, void* src, long count)
{
long block; block = count >> 3;
long* pDst = (long*)dst; long* pSrc = (long*)src;
{
for (int i = 0; i < block; i++) { *pDst = *pSrc; pDst++; pSrc++; }
}
}
需要你的想法!
感谢。
答案 0 :(得分:0)
实际上你可以让它在3毫秒内运行而且不需要不安全。
void Main()
{
int width;
int height;
int border;
byte[] src;
using (var bm = new Bitmap(@"C:\Data\sample-photo.jpg"))
{
width = bm.Width;
height = bm.Height;
border = width / 10;
src = new byte[width * height * 4];
for (var y = 0; y < bm.Height; y++)
for (var x = 0; x < bm.Width; x++)
{
var pixel = bm.GetPixel(x,y);
var i = GetIndex(width, x,y);
src[i + 1] = pixel.R;
src[i + 2] = pixel.G;
src[i + 3] = pixel.B;
}
}
var sw = Stopwatch.StartNew();
byte[] dst = null;
dst = Crop(src, width, border, width - border, border, height - border);
sw.Stop();
Console.WriteLine(sw.Elapsed);
using (var dstBmp = new Bitmap(width - border * 2, height - border * 2, PixelFormat.Format32bppArgb))
{
for (var y = 0; y < (height - border * 2); y++)
for (var x = 0; x < (width - border * 2); x++)
{
var i = GetIndex(dstBmp.Width, x, y);
var r = dst[i + 1];
var g = dst[i + 2];
var b = dst[i + 3];
dstBmp.SetPixel(x, y, Color.FromArgb(255, r, g, b));
}
dstBmp.Save(@"C:\Data\sample-photo-cropped.jpg");
}
}
byte[] Crop(byte[] src, int srcWidth, int xStart, int xEnd, int yStart, int yEnd)
{
var width = xEnd - xStart;
var height = yEnd - yStart;
var dst = new byte[width * height * 4];
for (var iY = yStart; iY < yEnd; iY++)
{
Array.Copy(src, GetIndex(srcWidth, xStart, iY), dst, GetIndex(width, 0, iY - yStart), width * 4);
}
return dst;
}
int GetIndex(int width, int x, int y)
{
return (x + (width * y)) * 4;
}
输出:
00:00:00.0007131
要使用指针,您可以使用Marshal
类,它有一堆重载用于复制内存或Buffer.MemoryCopy Method
答案 1 :(得分:0)
你去了
private static unsafe void Crop(byte* src, byte* dst, Rectangle rSrc, Rectangle rDst)
{
int* pDst = (int*)dst, pSrc = (int*)src + (rDst.Y * rSrc.Width + rDst.X);
int srcSkip = rSrc.Width - rDst.Width;
int rowCount = rDst.Height, colCount = rDst.Width;
for (int row = 0; row < rowCount; row++)
{
for (int col = 0; col < colCount; col++) *pDst++ = *pSrc++;
pSrc += srcSkip;
}
}