C# GDI+图像调整功能

发布于 2024-09-01 16:47:04 字数 275 浏览 1 评论 0原文

所以我的逻辑是有缺陷的,我需要一种更好、更正确的方法来调整我的 c# 应用程序中的图像大小,

我需要一个类似于此设置的功能

public void ResizeImageForWeb(string OriginalFile, string NewFile, int MaxWidth, int MaxHeight, int Quality)
{
// Resize Code

}

基本上,我是一名网页设计师,在尝试对桌面应用程序进行编程时迷失了方向。

So my logic is flawed and I need a better and correct way to resize an image in my c# app

I need a function similar to this setup

public void ResizeImageForWeb(string OriginalFile, string NewFile, int MaxWidth, int MaxHeight, int Quality)
{
// Resize Code

}

Basically, I'm a web designer lost trying to programming a desktop app.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时光沙漏 2024-09-08 16:47:04

这是我用来调整用户上传的图像大小的代码,以创建缩略图或只是强制执行大小限制。它不涉及图像质量,但它是一个开始。

// uses System.Drawing namespace
public class ImageResizer
{
    public bool ResizeImage(string fullFileName, int maxHeight, int maxWidth)
    {
        return this.ResizeImage(fullFileName, maxHeight, maxWidth, fullFileName);
    }

    public bool ResizeImage(string fullFileName, int maxHeight, int maxWidth, string newFileName)
    {
        using (Image originalImage = Image.FromFile(fullFileName))
        {
            int height = originalImage.Height;
            int width = originalImage.Width;
            int newHeight = maxHeight;
            int newWidth = maxWidth;

            if (height > maxHeight || width > maxWidth)
            {
                if (height > maxHeight)
                {
                    newHeight = maxHeight;
                    float temp = ((float)width / (float)height) * (float)maxHeight;
                    newWidth = Convert.ToInt32(temp);

                    height = newHeight;
                    width = newWidth;
                }

                if (width > maxWidth)
                {
                    newWidth = maxWidth;
                    float temp = ((float)height / (float)width) * (float)maxWidth;
                    newHeight = Convert.ToInt32(temp);
                }

                Image.GetThumbnailImageAbort abort = new Image.GetThumbnailImageAbort(ThumbnailCallback);
                using (Image resizedImage = originalImage.GetThumbnailImage(newWidth, newHeight, abort, System.IntPtr.Zero))
                {
                    resizedImage.Save(newFileName);
                }

                return true;
            }
            else if (fullFileName != newFileName)
            {
                // no resizing necessary, but need to create new file 
                originalImage.Save(newFileName);
            }
        }

        return false;
    }

    private bool ThumbnailCallback()
    {
        return false;
    }
}

This is code I've used to resize images that users upload to either create a thumbnail or simply to enforce a size restriction. It doesn't address picture quality, but it's a start.

// uses System.Drawing namespace
public class ImageResizer
{
    public bool ResizeImage(string fullFileName, int maxHeight, int maxWidth)
    {
        return this.ResizeImage(fullFileName, maxHeight, maxWidth, fullFileName);
    }

    public bool ResizeImage(string fullFileName, int maxHeight, int maxWidth, string newFileName)
    {
        using (Image originalImage = Image.FromFile(fullFileName))
        {
            int height = originalImage.Height;
            int width = originalImage.Width;
            int newHeight = maxHeight;
            int newWidth = maxWidth;

            if (height > maxHeight || width > maxWidth)
            {
                if (height > maxHeight)
                {
                    newHeight = maxHeight;
                    float temp = ((float)width / (float)height) * (float)maxHeight;
                    newWidth = Convert.ToInt32(temp);

                    height = newHeight;
                    width = newWidth;
                }

                if (width > maxWidth)
                {
                    newWidth = maxWidth;
                    float temp = ((float)height / (float)width) * (float)maxWidth;
                    newHeight = Convert.ToInt32(temp);
                }

                Image.GetThumbnailImageAbort abort = new Image.GetThumbnailImageAbort(ThumbnailCallback);
                using (Image resizedImage = originalImage.GetThumbnailImage(newWidth, newHeight, abort, System.IntPtr.Zero))
                {
                    resizedImage.Save(newFileName);
                }

                return true;
            }
            else if (fullFileName != newFileName)
            {
                // no resizing necessary, but need to create new file 
                originalImage.Save(newFileName);
            }
        }

        return false;
    }

    private bool ThumbnailCallback()
    {
        return false;
    }
}
不弃不离 2024-09-08 16:47:04

我当然不会使用 GetThumbnailImage 因为它会令人震惊 - 为了获得良好的分辨率而不诉诸 DX 或 OpenL 等,我会使用类似下面的东西(来自我自己的图形库,我在许多 Windows 应用程序中使用 - 我已经分享了一些以前有过几次,所以网上可能有变体)。这里有 3 个方法 - GetNonIndexedPixelFormat 方法用于在传递它无法处理的像素格式时阻止 GDI 崩溃(注释解释了这一点)。第一个允许按一个因子(缩放)缩放,最后一个允许固定大小重新缩放,同时保持纵横比(但如果您想倾斜它,可以轻松修改)。享受:

    /// <summary>
    /// Scale Image By A Percentage - Scale Factor between 0 and 1.
    /// </summary>
    /// <param name="originalImg">Image: Image to scale</param>
    /// <param name="ZoomFactor">Float: Sclae Value - 0 to 1 are the usual values</param>
    /// <returns>Image: Scaled Image</returns>
    public static Image ScaleByPercent(Image originalImg, float ZoomFactor)
    {    
        int destWidth = (int)((float)originalImg.Width * ZoomFactor);
        int destHeight = (int)((float)originalImg.Height * ZoomFactor);

        Bitmap bmPhoto = new Bitmap(destWidth, destHeight, GetNonIndexedPixelFormat(originalImg)); // PixelFormat.Format24bppRgb);

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

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(originalImg,
            new Rectangle(0, 0, destWidth, destHeight),
            new Rectangle(0, 0, originalImg.Width, originalImg.Height),
            GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }

    /// <summary>
    /// Gets the closest non-indexed pixel format
    /// </summary>
    /// <param name="originalImage">Image: Original image</param>
    /// <returns>PixelFormat: Closest non-pixel image format</returns>
    public static PixelFormat GetNonIndexedPixelFormat(Image originalImage)
    {
        /*
         * These formats cause an error when creating a GDI Graphics Oblect, so must be converted to non Indexed
         * Error is "A graphics object cannot be created from an image that has an indexed pixel format"
         * 
            PixelFormat.Undefined 
            PixelFormat.DontCare 
            PixelFormat.1bppIndexed
            PixelFormat.4bppIndexed
            PixelFormat.8bppIndexed
            PixelFormat.16bppGrayScale
            PixelFormat.16bppARGB1555
         * 
         * An attempt is made to use the closest (i.e. smallest fitting) format that will hold the palette.
         */

        switch (originalImage.PixelFormat)
        {
            case PixelFormat.Undefined: 
                //This is also the same Enumation as PixelFormat.DontCare:
                return PixelFormat.Format24bppRgb;
            case PixelFormat.Format1bppIndexed:
                return PixelFormat.Format16bppRgb555;
            case PixelFormat.Format4bppIndexed:
                return PixelFormat.Format16bppRgb555;
            case PixelFormat.Format8bppIndexed:
                return PixelFormat.Format16bppRgb555;
            case PixelFormat.Format16bppGrayScale:
                return PixelFormat.Format16bppArgb1555;
            case PixelFormat.Format32bppArgb:
                return PixelFormat.Format24bppRgb;                
            default:
                return originalImage.PixelFormat;
        }
    }

    /// <summary>
    /// Resize image keeping aspect ratio.
    /// </summary>
    /// <param name="originalImg">Image: Image to scale</param>
    /// <param name="Width">Int: Required width in pixels</param>
    /// <param name="Height">Int: Required height in pixels</param>
    /// <param name="BackgroundColour">Color: Background colour</param>
    /// <returns>Image: Scaled Image</returns>
    public static Image Resize(Image originalImg, int Width, int Height, Color BackgroundColour)
    {
        int destX = 0;
        int destY = 0;

        float nPercent = 0f;

        float nPercentW = ((float)Width / (float)originalImg.Width);
        float nPercentH = ((float)Height / (float)originalImg.Height);

        if (nPercentH < nPercentW)
        {
            nPercent = nPercentH;
            destX = System.Convert.ToInt16(((float)Width - ((float)originalImg.Width * nPercent)) / 2f);
        }
        else
        {
            nPercent = nPercentW;
            destY = System.Convert.ToInt16(((float)Height - ((float)originalImg.Height * nPercent)) / 2f);
        }

        int destWidth = (int)(originalImg.Width * nPercent);
        int destHeight = (int)(originalImg.Height * nPercent);

        Bitmap bmPhoto = new Bitmap(Width, Height, GetNonIndexedPixelFormat(originalImg)); // PixelFormat.Format24bppRgb);

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

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.Clear(BackgroundColour);
        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(originalImg,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(0, 0, originalImg.Width, originalImg.Height), GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }

I would certainly not use GetThumbnailImage as it would be shocking - for good resolution without resorting to DX or OpenL etc, I'd use something like the following (from my own graphics library I use in many windows apps - I have shared this a few times before so there may be variants float around the net). There are 3 methods here - the GetNonIndexedPixelFormat method is used to stop GDI crashing when passed pixel formats it can't handle (comments explain it). The first allows scaling by a factor (Zoom) and the last allows fixed size rescaling whilst keeping the aspect ratio (but can easily be modified if you want to skew it instead). Enjoy:

    /// <summary>
    /// Scale Image By A Percentage - Scale Factor between 0 and 1.
    /// </summary>
    /// <param name="originalImg">Image: Image to scale</param>
    /// <param name="ZoomFactor">Float: Sclae Value - 0 to 1 are the usual values</param>
    /// <returns>Image: Scaled Image</returns>
    public static Image ScaleByPercent(Image originalImg, float ZoomFactor)
    {    
        int destWidth = (int)((float)originalImg.Width * ZoomFactor);
        int destHeight = (int)((float)originalImg.Height * ZoomFactor);

        Bitmap bmPhoto = new Bitmap(destWidth, destHeight, GetNonIndexedPixelFormat(originalImg)); // PixelFormat.Format24bppRgb);

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

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(originalImg,
            new Rectangle(0, 0, destWidth, destHeight),
            new Rectangle(0, 0, originalImg.Width, originalImg.Height),
            GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }

    /// <summary>
    /// Gets the closest non-indexed pixel format
    /// </summary>
    /// <param name="originalImage">Image: Original image</param>
    /// <returns>PixelFormat: Closest non-pixel image format</returns>
    public static PixelFormat GetNonIndexedPixelFormat(Image originalImage)
    {
        /*
         * These formats cause an error when creating a GDI Graphics Oblect, so must be converted to non Indexed
         * Error is "A graphics object cannot be created from an image that has an indexed pixel format"
         * 
            PixelFormat.Undefined 
            PixelFormat.DontCare 
            PixelFormat.1bppIndexed
            PixelFormat.4bppIndexed
            PixelFormat.8bppIndexed
            PixelFormat.16bppGrayScale
            PixelFormat.16bppARGB1555
         * 
         * An attempt is made to use the closest (i.e. smallest fitting) format that will hold the palette.
         */

        switch (originalImage.PixelFormat)
        {
            case PixelFormat.Undefined: 
                //This is also the same Enumation as PixelFormat.DontCare:
                return PixelFormat.Format24bppRgb;
            case PixelFormat.Format1bppIndexed:
                return PixelFormat.Format16bppRgb555;
            case PixelFormat.Format4bppIndexed:
                return PixelFormat.Format16bppRgb555;
            case PixelFormat.Format8bppIndexed:
                return PixelFormat.Format16bppRgb555;
            case PixelFormat.Format16bppGrayScale:
                return PixelFormat.Format16bppArgb1555;
            case PixelFormat.Format32bppArgb:
                return PixelFormat.Format24bppRgb;                
            default:
                return originalImage.PixelFormat;
        }
    }

    /// <summary>
    /// Resize image keeping aspect ratio.
    /// </summary>
    /// <param name="originalImg">Image: Image to scale</param>
    /// <param name="Width">Int: Required width in pixels</param>
    /// <param name="Height">Int: Required height in pixels</param>
    /// <param name="BackgroundColour">Color: Background colour</param>
    /// <returns>Image: Scaled Image</returns>
    public static Image Resize(Image originalImg, int Width, int Height, Color BackgroundColour)
    {
        int destX = 0;
        int destY = 0;

        float nPercent = 0f;

        float nPercentW = ((float)Width / (float)originalImg.Width);
        float nPercentH = ((float)Height / (float)originalImg.Height);

        if (nPercentH < nPercentW)
        {
            nPercent = nPercentH;
            destX = System.Convert.ToInt16(((float)Width - ((float)originalImg.Width * nPercent)) / 2f);
        }
        else
        {
            nPercent = nPercentW;
            destY = System.Convert.ToInt16(((float)Height - ((float)originalImg.Height * nPercent)) / 2f);
        }

        int destWidth = (int)(originalImg.Width * nPercent);
        int destHeight = (int)(originalImg.Height * nPercent);

        Bitmap bmPhoto = new Bitmap(Width, Height, GetNonIndexedPixelFormat(originalImg)); // PixelFormat.Format24bppRgb);

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

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.Clear(BackgroundColour);
        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(originalImg,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(0, 0, originalImg.Width, originalImg.Height), GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }
小镇女孩 2024-09-08 16:47:04

使用 Graphics.DrawImage()。 GetThumbnailImage() 将从 jpeg 文件返回 120x120(或更小)的嵌入缩略图。对于任何超过这个尺寸的东西来说都是可怕的。

请参阅http://nathanaeljones.com/163/20-image-resizing-pitfalls/< /a> 以获取要使用的适当设置。

Use Graphics.DrawImage(). GetThumbnailImage() will return a 120x120 (or smaller) embedded thumbnail from an jpeg file. It will be horrible for anything above that size.

See http://nathanaeljones.com/163/20-image-resizing-pitfalls/ for the appropriate settings to use.

久伴你 2024-09-08 16:47:04

通过 Google 快速搜索,找到这个小片段

A quick search from Google find this little snippet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文