uwekeim icon

Crop an image in memory

uwekeim | PRO | 08/16/11 08:35:49 PM UTC | 0 ⭐ | 2525 👁️ | Never ⏰ | []
C# |

3.9 KB

|

None

|

0 👍

/

0 👎

// This is related to http://stackoverflow.com/questions/7083853/simple-algorithm-to-crop-empty-borders-from-an-image-by-code
public static Rectangle MeasureImageCrop(Bitmap image)
{
    // GDI+ still lies to us - the return format is BGR, NOT RGB.
    var bmData = image.LockBits(
        new Rectangle(0, 0, image.Width, image.Height),
        ImageLockMode.ReadWrite,
        PixelFormat.Format24bppRgb);
 
    var stride = bmData.Stride;
    var scan0 = bmData.Scan0;
 
    var cutLeft = 0;
    var cutRight = 0;
    var cutTop = 0;
    var cutBottom = 0;
 
    const int step = 1;
 
    unsafe
    {
        var p = (byte*)(void*)scan0;
 
        var refBlue = p[0];
        var refGreen = p[1];
        var refRed = p[2];
 
        // --
        // Top.
 
        var wantBreak = false;
        for (var y = 0; y < image.Height; y += step)
        {
            p = ((byte*)(void*)scan0) + stride * y;
 
            for (var x = 0; x < image.Width; x += step)
            {
                var blue = p[0];
                var green = p[1];
                var red = p[2];
 
                if (blue != refBlue || green != refGreen || red != refRed)
                {
                    wantBreak = true;
                    break;
                }
 
                p += 3 * step;
            }
 
            if (wantBreak)
            {
                break;
            }
 
            cutTop += step;
        }
 
        // --
        // Bottom.
 
        wantBreak = false;
        for (var y = image.Height - 1; y >= 0; y -= step)
        {
            p = ((byte*)(void*)scan0) + stride * y;
 
            for (var x = 0; x < image.Width; x += step)
            {
                var blue = p[0];
                var green = p[1];
                var red = p[2];
 
                if (blue != refBlue || green != refGreen || red != refRed)
                {
                    wantBreak = true;
                    break;
                }
 
                p += 3 * step;
            }
 
            if (wantBreak)
            {
                break;
            }
 
            cutBottom += step;
        }
 
        // --
        // Left.
 
        p = (byte*)(void*)scan0;
 
        wantBreak = false;
        for (var x = 0; x < image.Width; x += step)
        {
            for (var y = 0; y < image.Height; y += step)
            {
                var blue = p[0];
                var green = p[1];
                var red = p[2];
 
                if (blue != refBlue || green != refGreen || red != refRed)
                {
                    wantBreak = true;
                    break;
                }
 
                p += stride * step;
            }
 
            if (wantBreak)
            {
                break;
            }
 
            cutLeft += step;
 
            p -= stride * image.Height;
            p += 3 * step;
        }
 
        // --
        // Right.
 
        p = (byte*)(void*)scan0;
 
        p += (image.Width - 1) * 3;
 
        wantBreak = false;
        for (var x = image.Width - 1; x >= 0; x -= step)
        {
            for (var y = 0; y < image.Height; y += step)
            {
                var blue = p[0];
                var green = p[1];
                var red = p[2];
 
                if (blue != refBlue || green != refGreen || red != refRed)
                {
                    wantBreak = true;
                    break;
                }
 
                p += stride * step;
            }
 
            if (wantBreak)
            {
                break;
            }
 
            cutRight += step;
 
            p -= stride * image.Height;
            p -= 3 * step;
        }
    }
 
    // --
 
    image.UnlockBits(bmData);
 
    return new Rectangle(
        cutLeft,
        cutTop,
        image.Width - cutRight - cutLeft,
        image.Height - cutBottom - cutTop);
}

Comments