/// <summary> /// Determine the real size of the layer, i.e., the smallest rectangle /// that includes all non-transparent pixels. /// </summary> private static Rectangle FindImageRectangle(Surface surface) { var rectPos = new Util.RectanglePosition { Left = surface.Width, Top = surface.Height, Right = 0, Bottom = 0 }; unsafe { // Search for top non-transparent pixel bool fPixelFound = false; for (int y = 0; y < surface.Height; y++) { if (ExpandImageRectangle(surface, y, 0, surface.Width, ref rectPos)) { fPixelFound = true; break; } } // Narrow down the other dimensions of the image rectangle if (fPixelFound) { // Search for bottom non-transparent pixel for (int y = surface.Height - 1; y > rectPos.Bottom; y--) { if (ExpandImageRectangle(surface, y, 0, surface.Width, ref rectPos)) { break; } } // Search for left and right non-transparent pixels. Because we // scan horizontally, we can't just break, but we can examine fewer // candidate pixels on the remaining rows. for (int y = rectPos.Top + 1; y < rectPos.Bottom; y++) { ExpandImageRectangle(surface, y, 0, rectPos.Left, ref rectPos); ExpandImageRectangle(surface, y, rectPos.Right + 1, surface.Width, ref rectPos); } } else { rectPos.Left = 0; rectPos.Top = 0; } } Debug.Assert(rectPos.Left <= rectPos.Right); Debug.Assert(rectPos.Top <= rectPos.Bottom); var result = new Rectangle(rectPos.Left, rectPos.Top, rectPos.Right - rectPos.Left + 1, rectPos.Bottom - rectPos.Top + 1); return(result); }
/// <summary> /// Check for non-transparent pixels in a row, or portion of a row. /// Expands the size of the image rectangle if any were found. /// </summary> /// <returns>True if non-transparent pixels were found, false otherwise.</returns> unsafe private static bool ExpandImageRectangle(Surface surface, int y, int xStart, int xEnd, ref Util.RectanglePosition rectPos) { bool fPixelFound = false; ColorBgra *rowStart = surface.GetRowAddress(y); ColorBgra *pixel = rowStart + xStart; for (int x = xStart; x < xEnd; x++) { if (pixel->A > 0) { // Expand the rectangle to include the specified point. if (x < rectPos.Left) { rectPos.Left = x; } if (x > rectPos.Right) { rectPos.Right = x; } if (y < rectPos.Top) { rectPos.Top = y; } if (y > rectPos.Bottom) { rectPos.Bottom = y; } fPixelFound = true; } pixel++; } return(fPixelFound); }