C#从图像中剪切矩形块

时间:2015-08-13 14:04:56

标签: c# image-processing screenshot

我开发了一个屏幕共享应用程序,我想使它像posibble一样高效,所以我试图只发送屏幕截图之间的差异。 所以,假设我们有这样的图像,例如:它是一个带有transpert部分的32bpprgba图像。  enter image description here

我想将每个块存储为List中的矩形并获取它们的边界。听起来可能非常复杂但实际上它只需要一点点逻辑。 到目前为止,这是我的代码:

-no-reboot

当你看到我试图使用高度和宽度扫描图像时,当我找到一个像素时,我将其发送到 private unsafe List<Rectangle> CodeImage(Bitmap bmp) { List<Rectangle> rec = new List<Rectangle>(); Bitmap bmpRes = new Bitmap(bmp.Width, bmp.Height); BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat); IntPtr scan0 = bmData.Scan0; int stride = bmData.Stride; int nWidth = bmp.Width; int nHeight = bmp.Height; int minX = int.MaxValue; ; int minY = int.MaxValue; int maxX = 0; bool found = false; for (int y = 0; y < bmp.Height; y++) { byte* p = (byte*)scan0.ToPointer(); p += y * stride; for (int x = 0; x < bmp.Width; x++) { if (p[3] != 0) //Check if pixel is not transparent; { found = true; if (x < minX) minX = x; if (x > maxX) maxX = x; if (y < minY) minY = y; } else { if (found) { int height = getBlockHeight(stride, scan0, maxX, minY); found = false; Rectangle temp = new Rectangle(minX, minY, maxX - minX, height); rec.Add(temp); y += minY; break; } } p += 4;//add to the pointer 4 bytes; } } return rec; } 函数以获得它的高度:

GetBlockHeight

但是我只是没有得到结果......我觉得这里有逻辑的东西......有人能点亮我的眼睛吗?我知道这需要一点时间和思考,但我非常感谢任何可以帮助的人。

1 个答案:

答案 0 :(得分:0)

在当前算法中,成功匹配矩形后,将y的高度增加break并使其超出内循环。这意味着您只能检测每条水平线一个矩形的数据。

如果我是你,我会在回到代码之前考虑以下事项:

  • 将完整图像保存为PNG文件,并查看其大小。真的需要进一步处理吗?
  • 这些矩形是否准确?是否会有不断发送整个屏幕内容的场景?
  • 如果您正在开发适用于Windows的程序,则可能会挂钩使屏幕上的区域无效的过程,在这种情况下,您不必自己确定这些矩形。我不了解其他操作系统

另外,我个人也不会尝试在&#34; nesty&#34;中解决矩形检测算法。 for - 循环,但请使用以下内容:

public void FindRectangles(Bitmap bitmap, Rectangle searchArea, List<Rectangle> results)
{
    // Find the first non-transparent pixel within the search area. 
    // Ensure that it is the pixel with the lowest y-value possible
    Point p;
    if (!TryFindFirstNonTransparent(bitmap, searchArea, out p))
    {
        // No non-transparent pixels in this area
        return;
    }

    // Find its rectangle within the area
    Rectangle r = GetRectangle(bitmap, p, searchArea);
    results.Add(r);

    // No need to search above the rectangle we just found
    Rectangle left = new Rectangle(searchArea.Left, r.Top, r.Left - searchArea.Left, searchArea.Bottom - r.Top);
    Rectangle right = new Rectangle(r.Right, r.Top, searchArea.Right - r.Right, searchArea.Bottom - r.Top);
    Rectangle bottom = new Rectangle(r.Left, r.Bottom, r.Width, searchArea.Bottom - r.Bottom);

    FindRectangles(bitmap, left, results);
    FindRectangles(bitmap, right, results);
    FindRectangles(bitmap, bottom, results);
}

public Rectangle GetRectangle(Bitmap bitmap, Point p, Rectangle searchArea)
{
    int right = searchArea.Right;
    for (int x = p.X; x < searchArea.Right; x++)
    {
        if (IsTransparent(x, p.Y))
        {
            right = x - 1;
            break;
        }
    }

    int bottom = searchArea.Bottom;
    for (int y = p.Y; y < searchArea.Bottom; y++)
    {
        if (IsTransparent(p.X, y))
        {
            bottom = y - 1;
            break;
        }
    }

    return new Rectangle(p.X, p.Y, right - p.X, bottom - p.Y);
}

这种方法在完全实现后,应该会给你一个矩形列表(虽然它偶尔会将一个矩形分成两个)。

(当然不是提供bitmap,而是将指针传递给带有一些元数据的像素数据)