从C#中心开始裁剪图像

时间:2016-06-30 09:56:17

标签: c#

this回答之后,我制作了以下代码来调整图像大小,同时保持宽高比正确:

private static Bitmap ResizeImage(Image image, int? width, int? height)
   {
       var dimensions = GetImageDimensions(image.Width, image.Height, width, height);

       var destRect = new Rectangle(0, 0, dimensions.Item1, dimensions.Item2);
       var destImage = new Bitmap(dimensions.Item1, dimensions.Item2);

       destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

       using (var graphics = Graphics.FromImage(destImage))
       {
           graphics.CompositingMode = CompositingMode.SourceCopy;
           graphics.CompositingQuality = CompositingQuality.HighQuality;
           graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
           graphics.SmoothingMode = SmoothingMode.HighQuality;
           graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

           using (var wrapMode = new ImageAttributes())
           {
               wrapMode.SetWrapMode(WrapMode.TileFlipXY);
               graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
           }
       }

       return destImage;
   }

我制作了以下方法来确定尺寸:

public static Tuple<int, int> GetImageDimensions(int originalWidth, int originalHeight, int? width, int? height)
    {
        double widthRatio = (double)originalHeight / (double)originalWidth;
        double heighthRatio = (double)originalWidth / (double)originalHeight;
        int newWidth = originalWidth;
        int newHeight = originalHeight;

        if (width.HasValue && !height.HasValue && width.Value <= originalWidth)
        {
            newWidth = width.Value;
            newHeight = (int)(width.Value * widthRatio);
        }
        else if (!width.HasValue && height.HasValue && height.Value <= originalHeight)
        {
            newHeight = height.Value;
            newWidth = (int)(height.Value * heighthRatio);
        }

        return new Tuple<int, int>(newWidth, newHeight);
    }

我的问题:如果用户同时填充新的宽度一个新的高度,而不是调整我想要裁剪的图像(从原始图像的中心像素开始)。看到这张图片:

enter image description here

如果我的图像原来是1000x1000像素(图像中的红色),并且我将它传递给我的方法以及新的with和height(均为500),我想要返回裁剪后的图像(绿色图片)。但是,无论我在ResizeImage方法中更改了哪个参数,我似乎无法裁剪图像。在调用graphics.DrawImage时,我尝试更改所有参数,但我似乎无法获得上图所示的结果。发生了什么事?

2 个答案:

答案 0 :(得分:3)

您可以使用 System.Drawing.Image 命名空间的图像类,该命名空间返回预期广播中的图像。

例如:

Image image = Image.FromFile(path); // actual image
Image thumb = image.GetThumbnailImage(150, 150, () => false, IntPtr.Zero); //cropped image with height 150 and width 150 

答案 1 :(得分:1)

首先,我建议更改您的GetImageDimensions方法 - 它还应该返回是调整大小还是裁剪:

public static Tuple<int, int, bool> GetImageDimensions(int originalWidth, int originalHeight, int? width, int? height)
{
    double widthRatio = (double)originalHeight / (double)originalWidth;
    double heighthRatio = (double)originalWidth / (double)originalHeight;
    int newWidth = originalWidth;
    int newHeight = originalHeight;
    bool cropping = false;

    if (width.HasValue && !height.HasValue && width.Value <= originalWidth)
    {
        newWidth = width.Value;
        newHeight = (int)(width.Value * widthRatio);
    }
    else if (!width.HasValue && height.HasValue && height.Value <= originalHeight)
    {
        newHeight = height.Value;
        newWidth = (int)(height.Value * heighthRatio);
    }
    else
    {
        cropping = true;
    }

    return new Tuple<int, int>(newWidth, newHeight, cropping);
}

现在,基本上你需要以你想要的方式裁剪图像是新的尺寸的位置。假设您的GetImageDimensions方法返回正确的尺寸,您可以按如下方式计算位置:

var newDimensions = GetImageDimensions(...);

// We need to detect whether to resize or to crop
bool mustCrop = newDimensions.Item3;

// Initialize your SOURCE coordinates
int x = 0;
int y = 0;
int w = image.Width;
int h = image.Height;

// Adjust if we want to crop
if (mustCrop)
{
    x = (image.Width - newDimensions.Item1) / 2;
    y = (image.Height - newDimensions.Item2) / 2;
    w = newDimensions.Item1;
    h = newDimensions.Item2;
}

现在,您可以使用新尺寸为目标图像创建新的位图。之后,您可以绘制新图像,同时提供位置和新尺寸作为坐标:

graphics.DrawImage(image, 0, 0, new Rectangle(x, y, w, h), GraphicsUnit.Pixel);

这应该处理缩放和裁剪。所以你的ResizeImage方法看起来像这样:

private static Bitmap ResizeImage(Image image, int? width, int? height)
{
   var dimensions = GetImageDimensions(image.Width, image.Height, width, height);

   // We need to detect whether to resize or to crop
   bool mustCrop = newDimensions.Item3;

   // Initialize your SOURCE coordinates. By default, we copy
   // then entire image, resizing it
   int x = 0;
   int y = 0;
   int w = image.Width;
   int h = image.Height;

   // Adjust if we want to crop
   if (mustCrop)
   {
       x = (image.Width - newDimensions.Item1) / 2;
       y = (image.Height - newDimensions.Item2) / 2;
       w = newDimensions.Item1;
       h = newDimensions.Item2;
   }

   var destImage = new Bitmap(dimensions.Item1, dimensions.Item2);
   destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

   using (var graphics = Graphics.FromImage(destImage))
   {
       graphics.CompositingMode = CompositingMode.SourceCopy;
       graphics.CompositingQuality = CompositingQuality.HighQuality;
       graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
       graphics.SmoothingMode = SmoothingMode.HighQuality;
       graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

       using (var wrapMode = new ImageAttributes())
       {
           wrapMode.SetWrapMode(WrapMode.TileFlipXY);
           graphics.DrawImage(image, new Point(0,0), new Rectangle(x, y, w, h), GraphicsUnit.Pixel, wrapMode);
       }
   }

   return destImage;

}

请注意:我没试过这个。你可以对事物进行微调,但是你得到了图片......