简体   繁体   中英

Crop Bitmap clone with pictureBox sizeMode is zoomed

I find this function on the internet to crop image, it doing fine if the pictureBox source sizeMode is normal. But when the pictureBox sizeMode is zoom its still cloned like the normal sizeMode.

How to clone same as the zoomed pictureBox? not the size of original normal bitmap?

public static Bitmap CropBitmap(Bitmap bitmap, int x, int y, int w, int h)
{
    Rectangle rect = new Rectangle(x, y, w, h);
    Bitmap cropped = bitmap.Clone(rect, bitmap.PixelFormat);
    return cropped;
}

and used like this

pictureBox2.Image = CropBitmap((Bitmap)pictureBox1.Image.Clone(), 35, 0, 110, 150);

The easiest way is to use DrawToBitmap method to get the output from the picture box regardless of the SizeMode , and then crop that output like this:

public static Bitmap Crop(PictureBox pb, int x, int y, int w, int h)
{
    var rect = pb.ClientRectangle;
    using (var output = new Bitmap(rect.Width, rect.Height, pb.Image.PixelFormat))
    {
        pb.DrawToBitmap(output, rect);
        return output.Clone(new Rectangle(x, y, w, h), output.PixelFormat);
    }
}

However, the drawback of the above method is that it really will crop the potentially scaled image.

If you indeed want to crop the original image, you need to map the passed rectangle (I assume it's in picture box client coordinates) to the original image coordinates.

It would be nice if the picture box provides a method ClientToImage (similar to ClientToScreen ), but it doesn't, so we need to extract the SizeMode logic from the Reference Source .

The new method is like this:

public static class ImageUtils
{
    public static Bitmap CropImage(this PictureBox pb, int x, int y, int w, int h)
    {
        var imageRect = pb.GetImageRectangle();
        var image = pb.Image;
        float scaleX = (float)image.Width / imageRect.Width;
        float scaleY = (float)image.Height / imageRect.Height;
        var cropRect = new Rectangle();
        cropRect.X = Scale(x - imageRect.X, scaleX, image.Width);
        cropRect.Y = Scale(y - imageRect.Y, scaleY, image.Height);
        cropRect.Width = Scale(w, scaleX, image.Width - cropRect.X);
        cropRect.Height = Scale(h, scaleY, image.Height - cropRect.Y);
        var result = new Bitmap(cropRect.Width, cropRect.Height, image.PixelFormat);
        using (var g = Graphics.FromImage(result))
            g.DrawImage(image, new Rectangle(new Point(0, 0), cropRect.Size), cropRect, GraphicsUnit.Pixel);
        return result;
    }

    static int Scale(int value, float scale, int maxValue)
    {
        int result = (int)(value * scale);
        return result < 0 ? 0 : result > maxValue ? maxValue : result;
    }

    public static Rectangle GetImageRectangle(this PictureBox pb)
    {
        var rect = pb.ClientRectangle;
        var padding = pb.Padding;
        rect.X += padding.Left;
        rect.Y += padding.Top;
        rect.Width -= padding.Horizontal;
        rect.Height -= padding.Vertical;
        var image = pb.Image;
        var sizeMode = pb.SizeMode;
        if (sizeMode == PictureBoxSizeMode.Normal || sizeMode == PictureBoxSizeMode.AutoSize)
            rect.Size = image.Size;
        else if (sizeMode == PictureBoxSizeMode.CenterImage)
        {
            rect.X += (rect.Width - image.Width) / 2;
            rect.Y += (rect.Height - image.Height) / 2;
            rect.Size = image.Size;
        }
        else if (sizeMode == PictureBoxSizeMode.Zoom)
        {
            var imageSize = image.Size;
            var zoomSize = pb.ClientSize;
            float ratio = Math.Min((float)zoomSize.Width / imageSize.Width, (float)zoomSize.Height / imageSize.Height);
            rect.Width = (int)(imageSize.Width * ratio);
            rect.Height = (int)(imageSize.Height * ratio);
            rect.X = (pb.ClientRectangle.Width - rect.Width) / 2;
            rect.Y = (pb.ClientRectangle.Height - rect.Height) / 2;
        }
        return rect;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM