如何调整图像C#的大小

ini*_*iki 269 c# resize image

Size,WidthHeightGet()的性质System.Drawing.Image;
如何在C#中运行时调整Image对象的大小?

现在,我只是创建一个新的Image使用:

// objImage is the original Image
Bitmap objBitmap = new Bitmap(objImage, new Size(227, 171));
Run Code Online (Sandbox Code Playgroud)

mpe*_*pen 454

这将执行高质量的调整大小:

/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(Image image, int width, int height)
{
    var destRect = new Rectangle(0, 0, width, height);
    var destImage = new Bitmap(width, height);

    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;
}
Run Code Online (Sandbox Code Playgroud)

保持纵横比是留给读者的一个练习(实际上,我只是觉得这个功能不是为你做这个功能).

此外,这是一篇很好的文章,描述了图像大小调整的一些缺陷.上面的功能将涵盖其中的大多数,但您仍然需要担心保存.

  • @dotNetBlackBelt请停止使用不适合您的用户名;-) (11认同)
  • @dotNetBlackBelt您可能需要添加对`System.Drawing`的引用并使用System.Drawing.Imaging添加`; (5认同)
  • 在调整图像大小时,代码工作正常,但是将大小从66 KB增加到132 KB.锄头可以减少它吗? (4认同)
  • @chamara这可能是因为你选择的保存质量.请参阅http://msdn.microsoft.com/en-us/library/bb882583(v=vs.110).aspx尝试质量= 90 (3认同)
  • @kstubs你确定.`Bitmap`本质上只是类的名称,您可以将其保存为您喜欢的任何文件类型. (3认同)
  • 这不会保持原有的宽高比吗? (2认同)
  • 为了修复丢失的 EXIF 数据和方向问题,我添加了以下内容:`foreach (PropertyItem propertyItem in image.PropertyItems) { destImage.SetPropertyItem(propertyItem); }` (2认同)

Mat*_*att 141

不确定这有什么困难,做你正在做的事情,使用重载的Bitmap构造函数来创建一个重新调整大小的图像,你唯一缺少的是回转到Image数据类型:

    public static Image resizeImage(Image imgToResize, Size size)
    {
       return (Image)(new Bitmap(imgToResize, size));
    }

    yourImage = resizeImage(yourImage, new Size(50,50));
Run Code Online (Sandbox Code Playgroud)

  • 此代码无法控制调整大小的质量,这非常重要.看看马克的答案. (21认同)
  • 您可以手动处理它,也可以让垃圾收集器完成它的工作。不管。 (3认同)
  • 在将它分配给新图像之前,你不应该处理`yourImage`吗? (2认同)
  • @Elmue 垃圾收集器不会自动清理远程 GDI+ 对象。处理它们至关重要。 (2认同)
  • @Elmue,你所说的确实是一个糟糕的建议。我已经在扫描软件、数百万文档和页面的批量转换以及 OCR 等软件中使用图像处理工作了 8 年,除非在最微不足道的情况下才会处理位图,否则会导致内存泄漏、低效代码和软件将逐渐停止(崩溃、性能等)。当您不需要某些东西时,您应该始终尽快通知 GC,这样 GC 以后就不必做那么多工作,这确实会影响应用程序的性能和可扩展性(在很大程度上) (2认同)

Vin*_*nzz 39

这个问题上,你会有一些答案,包括我的:

public Image resizeImage(int newWidth, int newHeight, string stPhotoPath)
 {
     Image imgPhoto = Image.FromFile(stPhotoPath); 

     int sourceWidth = imgPhoto.Width;
     int sourceHeight = imgPhoto.Height;

     //Consider vertical pics
    if (sourceWidth < sourceHeight)
    {
        int buff = newWidth;

        newWidth = newHeight;
        newHeight = buff;
    }

    int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
    float nPercent = 0, nPercentW = 0, nPercentH = 0;

    nPercentW = ((float)newWidth / (float)sourceWidth);
    nPercentH = ((float)newHeight / (float)sourceHeight);
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = System.Convert.ToInt16((newWidth -
                  (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = System.Convert.ToInt16((newHeight -
                  (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);


    Bitmap bmPhoto = new Bitmap(newWidth, newHeight,
                  PixelFormat.Format24bppRgb);

    bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                 imgPhoto.VerticalResolution);

    Graphics grPhoto = Graphics.FromImage(bmPhoto);
    grPhoto.Clear(Color.Black);
    grPhoto.InterpolationMode =
        System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

    grPhoto.DrawImage(imgPhoto,
        new Rectangle(destX, destY, destWidth, destHeight),
        new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
        GraphicsUnit.Pixel);

    grPhoto.Dispose();
    imgPhoto.Dispose();
    return bmPhoto;
}
Run Code Online (Sandbox Code Playgroud)

  • 你忘记了imgPhoto.Dispose(); 该文件一直在使用中 (5认同)

Lin*_*lva 22

为什么不使用这个System.Drawing.Image.GetThumbnailImage方法?

public Image GetThumbnailImage(
    int thumbWidth, 
    int thumbHeight, 
    Image.GetThumbnailImageAbort callback, 
    IntPtr callbackData)
Run Code Online (Sandbox Code Playgroud)

例:

Image originalImage = System.Drawing.Image.FromStream(inputStream, true, true);
Image resizedImage = originalImage.GetThumbnailImage(newWidth, (newWidth * originalImage.Height) / originalWidth, null, IntPtr.Zero);
resizedImage.Save(imagePath, ImageFormat.Png);
Run Code Online (Sandbox Code Playgroud)

来源:http: //msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx

  • 正如你所说:可能需要很长时间.但这不是内存泄漏.如果永远不释放内存,它将是一个内存泄漏.但这是垃圾收集器的NORMAL行为,它在CPU空闲时释放内存.using()语句不会阻止内存泄漏.它只是在垃圾收集器有时间释放内存时立即释放内存.这是这个具体案例的唯一区别. (8认同)
  • 这不是调整图像大小的正确方法.如果它存在,这将从jpg中提取缩略图.如果它不存在,则无法控制质量或新图像.此外,此代码具有内存泄漏. (6认同)
  • @Bobrot 为什么这会导致内存泄漏? (2认同)
  • GDI 库中的任何内容仍处于非托管状态。如果不使用 using 语句或之后处理对象,系统可能需要很长时间才能对这些对象进行垃圾收集并使内存再次可用。 (2认同)

Dom*_*nic 10

这将 -

  • 调整宽度和高度,无需循环
  • 不超过图像原始尺寸

//////////////

private void ResizeImage(Image img, double maxWidth, double maxHeight)
{
    double resizeWidth = img.Source.Width;
    double resizeHeight = img.Source.Height;

    double aspect = resizeWidth / resizeHeight;

    if (resizeWidth > maxWidth)
    {
        resizeWidth = maxWidth;
        resizeHeight = resizeWidth / aspect;
    }
    if (resizeHeight > maxHeight)
    {
        aspect = resizeWidth / resizeHeight;
        resizeHeight = maxHeight;
        resizeWidth = resizeHeight * aspect;
    }

    img.Width = resizeWidth;
    img.Height = resizeHeight;
}
Run Code Online (Sandbox Code Playgroud)

  • OP询问System.Drawing.Image,由于'Width'和'Height'属性不可设置,因此您的代码无效.但是,它适用于System.Windows.Controls.Image. (10认同)

小智 9

public static Image resizeImage(Image image, int new_height, int new_width)
{
    Bitmap new_image = new Bitmap(new_width, new_height);
    Graphics g = Graphics.FromImage((Image)new_image );
    g.InterpolationMode = InterpolationMode.High;
    g.DrawImage(image, 0, 0, new_width, new_height);
    return new_image;
}
Run Code Online (Sandbox Code Playgroud)


Qui*_*pie 7

在我创建的应用程序中,有必要创建一个具有多个选项的函数.它非常大,但它可以调整图像大小,可以保持纵横比并可以剪切边缘以仅返回图像的中心:

/// <summary>
    /// Resize image with a directory as source
    /// </summary>
    /// <param name="OriginalFileLocation">Image location</param>
    /// <param name="heigth">new height</param>
    /// <param name="width">new width</param>
    /// <param name="keepAspectRatio">keep the aspect ratio</param>
    /// <param name="getCenter">return the center bit of the image</param>
    /// <returns>image with new dimentions</returns>
    public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width, Boolean keepAspectRatio, Boolean getCenter)
    {
        int newheigth = heigth;
        System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFileLocation);

        // Prevent using images internal thumbnail
        FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
        FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);

        if (keepAspectRatio || getCenter)
        {
            int bmpY = 0;
            double resize = (double)FullsizeImage.Width / (double)width;//get the resize vector
            if (getCenter)
            {
                bmpY = (int)((FullsizeImage.Height - (heigth * resize)) / 2);// gives the Y value of the part that will be cut off, to show only the part in the center
                Rectangle section = new Rectangle(new Point(0, bmpY), new Size(FullsizeImage.Width, (int)(heigth * resize)));// create the section to cut of the original image
                //System.Console.WriteLine("the section that will be cut off: " + section.Size.ToString() + " the Y value is minimized by: " + bmpY);
                Bitmap orImg = new Bitmap((Bitmap)FullsizeImage);//for the correct effect convert image to bitmap.
                FullsizeImage.Dispose();//clear the original image
                using (Bitmap tempImg = new Bitmap(section.Width, section.Height))
                {
                    Graphics cutImg = Graphics.FromImage(tempImg);//              set the file to save the new image to.
                    cutImg.DrawImage(orImg, 0, 0, section, GraphicsUnit.Pixel);// cut the image and save it to tempImg
                    FullsizeImage = tempImg;//save the tempImg as FullsizeImage for resizing later
                    orImg.Dispose();
                    cutImg.Dispose();
                    return FullsizeImage.GetThumbnailImage(width, heigth, null, IntPtr.Zero);
                }
            }
            else newheigth = (int)(FullsizeImage.Height / resize);//  set the new heigth of the current image
        }//return the image resized to the given heigth and width
        return FullsizeImage.GetThumbnailImage(width, newheigth, null, IntPtr.Zero);
    }
Run Code Online (Sandbox Code Playgroud)

为了更容易访问该函数,可以添加一些重载函数:

/// <summary>
    /// Resize image with a directory as source
    /// </summary>
    /// <param name="OriginalFileLocation">Image location</param>
    /// <param name="heigth">new height</param>
    /// <param name="width">new width</param>
    /// <returns>image with new dimentions</returns>
    public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width)
    {
        return resizeImageFromFile(OriginalFileLocation, heigth, width, false, false);
    }

    /// <summary>
    /// Resize image with a directory as source
    /// </summary>
    /// <param name="OriginalFileLocation">Image location</param>
    /// <param name="heigth">new height</param>
    /// <param name="width">new width</param>
    /// <param name="keepAspectRatio">keep the aspect ratio</param>
    /// <returns>image with new dimentions</returns>
    public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width, Boolean keepAspectRatio)
    {
        return resizeImageFromFile(OriginalFileLocation, heigth, width, keepAspectRatio, false);
    }
Run Code Online (Sandbox Code Playgroud)

现在是可选的最后两个布尔值.像这样调用函数:

System.Drawing.Image ResizedImage = resizeImageFromFile(imageLocation, 800, 400, true, true);
Run Code Online (Sandbox Code Playgroud)


小智 7

此代码与从上述答案之一发布的相同..但将透明像素转换为白色而不是黑色...谢谢:)

    public Image resizeImage(int newWidth, int newHeight, string stPhotoPath)
    {
        Image imgPhoto = Image.FromFile(stPhotoPath);

        int sourceWidth = imgPhoto.Width;
        int sourceHeight = imgPhoto.Height;

        //Consider vertical pics
        if (sourceWidth < sourceHeight)
        {
            int buff = newWidth;

            newWidth = newHeight;
            newHeight = buff;
        }

        int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
        float nPercent = 0, nPercentW = 0, nPercentH = 0;

        nPercentW = ((float)newWidth / (float)sourceWidth);
        nPercentH = ((float)newHeight / (float)sourceHeight);
        if (nPercentH < nPercentW)
        {
            nPercent = nPercentH;
            destX = System.Convert.ToInt16((newWidth -
                      (sourceWidth * nPercent)) / 2);
        }
        else
        {
            nPercent = nPercentW;
            destY = System.Convert.ToInt16((newHeight -
                      (sourceHeight * nPercent)) / 2);
        }

        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);


        Bitmap bmPhoto = new Bitmap(newWidth, newHeight,
                      PixelFormat.Format24bppRgb);

        bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                     imgPhoto.VerticalResolution);

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.Clear(Color.White);
        grPhoto.InterpolationMode =
            System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(imgPhoto,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
            GraphicsUnit.Pixel);

        grPhoto.Dispose();
        imgPhoto.Dispose();

        return bmPhoto;
    }
Run Code Online (Sandbox Code Playgroud)


Les*_*all 6

这是我为特定要求制定的代码,即:目的地始终是横向比率.它应该给你一个良好的开端.

public Image ResizeImage(Image source, RectangleF destinationBounds)
{
    RectangleF sourceBounds = new RectangleF(0.0f,0.0f,(float)source.Width, (float)source.Height);
    RectangleF scaleBounds = new RectangleF();

    Image destinationImage = new Bitmap((int)destinationBounds.Width, (int)destinationBounds.Height);
    Graphics graph = Graphics.FromImage(destinationImage);
    graph.InterpolationMode =
        System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

    // Fill with background color
    graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), destinationBounds);

    float resizeRatio, sourceRatio;
    float scaleWidth, scaleHeight;

    sourceRatio = (float)source.Width / (float)source.Height;

    if (sourceRatio >= 1.0f)
    {
        //landscape
        resizeRatio = destinationBounds.Width / sourceBounds.Width;
        scaleWidth = destinationBounds.Width;
        scaleHeight = sourceBounds.Height * resizeRatio;
        float trimValue = destinationBounds.Height - scaleHeight;
        graph.DrawImage(source, 0, (trimValue / 2), destinationBounds.Width, scaleHeight);
    }
    else
    {
        //portrait
        resizeRatio = destinationBounds.Height/sourceBounds.Height;
        scaleWidth = sourceBounds.Width * resizeRatio;
        scaleHeight = destinationBounds.Height;
        float trimValue = destinationBounds.Width - scaleWidth;
        graph.DrawImage(source, (trimValue / 2), 0, scaleWidth, destinationBounds.Height);
    }

    return destinationImage;

}
Run Code Online (Sandbox Code Playgroud)


小智 6

public string CreateThumbnail(int maxWidth, int maxHeight, string path)
{

    var image = System.Drawing.Image.FromFile(path);
    var ratioX = (double)maxWidth / image.Width;
    var ratioY = (double)maxHeight / image.Height;
    var ratio = Math.Min(ratioX, ratioY);
    var newWidth = (int)(image.Width * ratio);
    var newHeight = (int)(image.Height * ratio);
    var newImage = new Bitmap(newWidth, newHeight);
    Graphics thumbGraph = Graphics.FromImage(newImage);

    thumbGraph.CompositingQuality = CompositingQuality.HighQuality;
    thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
    //thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;

    thumbGraph.DrawImage(image, 0, 0, newWidth, newHeight);
    image.Dispose();

    string fileRelativePath = "newsizeimages/" + maxWidth + Path.GetFileName(path);
    newImage.Save(Server.MapPath(fileRelativePath), newImage.RawFormat);
    return fileRelativePath;
}
Run Code Online (Sandbox Code Playgroud)

点击这里http://bhupendrasinghsaini.blogspot.in/2014/07/resize-image-in-c.html


kle*_*uke 6

你可以试试净贵宾,在C#绑定libvips。这是一个延迟的,流式的,由需求驱动的图像处理库,因此它可以执行此类操作,而无需加载整个图像。

例如,它带有一个方便的图像缩略图:

Image image = Image.Thumbnail("image.jpg", 300, 300);
image.WriteToFile("my-thumbnail.jpg");
Run Code Online (Sandbox Code Playgroud)

它还支持智能裁切,这是一种智能地确定图像最重要部分并在裁切图像时使其聚焦的方法。例如:

Image image = Image.Thumbnail("owl.jpg", 128, crop: "attention");
image.WriteToFile("tn_owl.jpg");
Run Code Online (Sandbox Code Playgroud)

owl.jpg偏心组合在哪里:

猫头鹰

给出以下结果:

猫头鹰聪明的庄稼

首先,它会缩小图像以使垂直轴达到128像素,然后使用该attention策略将其裁剪为128像素。该图片会在图像中搜索可能引起人眼注意的功能,Smartcrop()有关详细信息,请参阅。