คลังภาพที่มีคุณภาพสูง [ปิด]


141

ฉันต้องการปรับขนาดภาพใน C # ด้วยระดับคุณภาพที่ดีเหมือนกับ Photoshop มีไลบรารี่การประมวลผลภาพ C # ในการทำสิ่งนี้หรือไม่?


47
นี่คือ C # คำถามอื่น ๆ คือ C ++ ดังนั้นจึงไม่ซ้ำกันเลย
หมอโจนส์

7
imageresizing.netมีห้องสมุดที่มีคุณภาพสูงสุดและภาพที่มีประสิทธิภาพสูงสุดของการปรับขนาดคุณจะได้รับ คำตอบที่ได้รับการยอมรับจะตกเป็นเหยื่อของหนึ่งในข้อผิดพลาดของ GDI +และจะทำให้สิ่งประดิษฐ์เส้นขอบกว้าง 1px รอบ ๆ แต่ละภาพที่สร้าง ที่ได้รับการแก้ไขโดยใช้อินสแตนซ์ ImageAttributes ที่มี TileModeXY ที่ตั้งค่าไว้สำหรับพารามิเตอร์สุดท้ายของการเรียก DrawImage
Lilith River

2
@ คอมพิวเตอร์ภาษาศาสตร์ - TileModeXY เป็นตัวพิมพ์ผิดหรือไม่? คุณได้คัดลอกความคิดเห็นนี้ไปทั่วคำตอบหลาย ๆ คำและ google ค้นหาคำว่า "TileModeXY" เพียงเปิดโพสต์ของคุณเท่านั้น ลิงค์ต่อไปนี้สำหรับ System.Drawing.Drawing2D.WrapMode แสดงค่าที่เป็นไปได้ 5 ค่าเท่านั้น: Tile, TileFlipX, TileFlipY, TileFlipXY, Clamp msdn.microsoft.com/en-us/library/…
JasDev

1
ใช่มันควรเป็น TileFlipXY ขอบคุณสำหรับการแก้ไข!
Lilith River

คำตอบ:


233

นี่คือคลาสผู้ช่วย Image Manipulation ที่คุณสามารถดูและใช้งานได้ ฉันเขียนมันเป็นตัวอย่างของวิธีการทำงานบางอย่างของการจัดการรูปภาพใน C # คุณจะสนใจฟังก์ชันResizeImageที่ใช้ System.Drawing.Image ความกว้างและความสูงเป็นอาร์กิวเมนต์

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;

namespace DoctaJonez.Drawing.Imaging
{
    /// <summary>
    /// Provides various image untilities, such as high quality resizing and the ability to save a JPEG.
    /// </summary>
    public static class ImageUtilities
    {    
        /// <summary>
        /// A quick lookup for getting image encoders
        /// </summary>
        private static Dictionary<string, ImageCodecInfo> encoders = null;

        /// <summary>
        /// A lock to prevent concurrency issues loading the encoders.
        /// </summary>
        private static object encodersLock = new object();

        /// <summary>
        /// A quick lookup for getting image encoders
        /// </summary>
        public static Dictionary<string, ImageCodecInfo> Encoders
        {
            //get accessor that creates the dictionary on demand
            get
            {
                //if the quick lookup isn't initialised, initialise it
                if (encoders == null)
                {
                    //protect against concurrency issues
                    lock (encodersLock)
                    {
                        //check again, we might not have been the first person to acquire the lock (see the double checked lock pattern)
                        if (encoders == null)
                        {
                            encoders = new Dictionary<string, ImageCodecInfo>();

                            //get all the codecs
                            foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
                            {
                                //add each codec to the quick lookup
                                encoders.Add(codec.MimeType.ToLower(), codec);
                            }
                        }
                    }
                }

                //return the lookup
                return encoders;
            }
        }

        /// <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 System.Drawing.Bitmap ResizeImage(System.Drawing.Image image, int width, int height)
        {
            //a holder for the result
            Bitmap result = new Bitmap(width, height);
            //set the resolutions the same to avoid cropping due to resolution differences
            result.SetResolution(image.HorizontalResolution, image.VerticalResolution);

            //use a graphics object to draw the resized image into the bitmap
            using (Graphics graphics = Graphics.FromImage(result))
            {
                //set the resize quality modes to high quality
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                //draw the image into the target bitmap
                graphics.DrawImage(image, 0, 0, result.Width, result.Height);
            }

            //return the resulting bitmap
            return result;
        }

        /// <summary> 
        /// Saves an image as a jpeg image, with the given quality 
        /// </summary> 
        /// <param name="path">Path to which the image would be saved.</param> 
        /// <param name="quality">An integer from 0 to 100, with 100 being the 
        /// highest quality</param> 
        /// <exception cref="ArgumentOutOfRangeException">
        /// An invalid value was entered for image quality.
        /// </exception>
        public static void SaveJpeg(string path, Image image, int quality)
        {
            //ensure the quality is within the correct range
            if ((quality < 0) || (quality > 100))
            {
                //create the error message
                string error = string.Format("Jpeg image quality must be between 0 and 100, with 100 being the highest quality.  A value of {0} was specified.", quality);
                //throw a helpful exception
                throw new ArgumentOutOfRangeException(error);
            }

            //create an encoder parameter for the image quality
            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            //get the jpeg codec
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            //create a collection of all parameters that we will pass to the encoder
            EncoderParameters encoderParams = new EncoderParameters(1);
            //set the quality parameter for the codec
            encoderParams.Param[0] = qualityParam;
            //save the image using the codec and the parameters
            image.Save(path, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        public static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            //do a case insensitive search for the mime type
            string lookupKey = mimeType.ToLower();

            //the codec to return, default to null
            ImageCodecInfo foundCodec = null;

            //if we have the encoder, get it to return
            if (Encoders.ContainsKey(lookupKey))
            {
                //pull the codec from the lookup
                foundCodec = Encoders[lookupKey];
            }

            return foundCodec;
        } 
    }
}

ปรับปรุง

มีคนสองสามคนที่ถูกถามในความคิดเห็นเพื่อดูตัวอย่างวิธีการใช้ ImageUtilities class ดังนั้นที่นี่คุณจะไป

//resize the image to the specified height and width
using (var resized = ImageUtilities.ResizeImage(image, 50, 100))
{
    //save the resized image as a jpeg with a quality of 90
    ImageUtilities.SaveJpeg(@"C:\myimage.jpeg", resized, 90);
}

บันทึก

โปรดจำไว้ว่าภาพนั้นเป็นแบบใช้ครั้งเดียวดังนั้นคุณต้องกำหนดผลลัพธ์ของการปรับขนาดของคุณให้เป็นการประกาศโดยใช้ (หรือคุณสามารถลองได้ในที่สุด


ImageCodecInfo jpegCodec = getEncoderInfo ("image / jpeg"); - ที่คุณกำหนด getEncoderInfo สาเหตุที่ฉันไม่สามารถรวบรวมได้
ilija veselica

3
คุณควรอ่าน GetEncoderInfo และไม่ใช่ getEncoderInfo ฉันแก้ไขข้อผิดพลาดและคอมไพล์ชั้นเรียนตอนนี้
หมอโจนส์

5
+1 สิ่งนี้ทำงานได้อย่างยอดเยี่ยม! ปัญหาหนึ่งที่คุณต้องแก้ไขในรหัสนี้คือการแปลงตัวแปรคุณภาพให้นานก่อนที่จะส่งไปยังพารามิเตอร์ตัวเข้ารหัสหรือคุณจะได้รับข้อยกเว้นของพารามิเตอร์ที่ไม่ถูกต้อง
James

1
@Behzad ถ้าคุณมองฟังก์ชั่น SaveJpeg ใช้พารามิเตอร์ int ที่เรียกว่าคุณภาพ คุณต้องเรียกใช้และระบุค่าที่ถูกต้องสำหรับพารามิเตอร์คุณภาพ (ยอมรับค่าระหว่าง 0 ถึง 100)
หมอโจนส์

1
หลังจากค้นหามานานส่วนการปรับขนาดของคำตอบนี้ ( ไม่ได้ใช้รหัสทั้งหมด ) ทำงานเพื่อปรับขนาด qrcode โดยไม่สูญเสียคุณภาพ การตั้งค่าที่เหมาะสมมีความสำคัญต่อคุณภาพของผลลัพธ์
Furkan Ekinci

15

เมื่อคุณวาดภาพโดยใช้ GDI + มันมีขนาดค่อนข้างดีในความคิดของฉัน คุณสามารถใช้สิ่งนี้เพื่อสร้างภาพที่ปรับขนาด

หากคุณต้องการปรับขนาดภาพของคุณด้วย GDI + คุณสามารถทำสิ่งนี้:

Bitmap original = ...
Bitmap scaled = new Bitmap(new Size(original.Width * 4, original.Height * 4));
using (Graphics graphics = Graphics.FromImage(scaled)) {
  graphics.DrawImage(original, new Rectangle(0, 0, scaled.Width, scaled.Height));
}

ไม่แน่ใจว่ารหัสมีการเปลี่ยนแปลง แต่ฉันต้องละเว้นnew Sizeในการประกาศของscaled:new Bitmap(original.Width * 4, original.Height * 4);
Kirk Woll


8


4

ลองใช้ค่าอื่นสำหรับ Graphics.InterpolationMode มีอัลกอริธึมการปรับสเกลทั่วไปหลายอย่างใน GDI + หากหนึ่งในนั้นเพียงพอสำหรับความต้องการของคุณคุณสามารถไปเส้นทางนี้แทนการพึ่งพาไลบรารีภายนอก


3

คุณสามารถลองdotImageซึ่งเป็นหนึ่งในผลิตภัณฑ์ของ บริษัท ของฉันซึ่งมีวัตถุสำหรับการสุ่มภาพใหม่ที่มีตัวกรอง 18 ชนิดสำหรับคุณภาพระดับต่างๆ

การใช้งานทั่วไปคือ:

// BiCubic is one technique available in PhotoShop
ResampleCommand resampler = new ResampleCommand(newSize, ResampleMethod.BiCubic);
AtalaImage newImage = resampler.Apply(oldImage).Image;

นอกจากนี้ dotImage ยังมีคำสั่งประมวลผลภาพแปลก ๆ 140 คำรวมถึงตัวกรองจำนวนมากที่คล้ายกับ PhotoShop หากคุณกำลังมองหา


SDK พร้อมคุณสมบัตินี้มีให้บริการฟรีสำหรับรูปแบบภาพถ่ายทั่วไป (JPEG, PNG, ฯลฯ ) atalasoft.com/photofree
Lou Franco

/ Lou Franco: เวอร์ชันฟรีรูปแบบทั่วไปสามารถใช้ในการปรับใช้การผลิตได้ฟรีหรือไม่
Oskar Austegard

ใช่ DotImage Photo Free สามารถนำไปใช้ได้ฟรี
Lou Franco

2

สิ่งนี้อาจช่วยได้

    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;

    }

โปรดสังเกตInterpolationMode.HighQualityBicubic-> โดยทั่วไปจะเป็นการแลกเปลี่ยนที่ดีระหว่างประสิทธิภาพและผลลัพธ์


2

ลองตัวอย่างโค้ดพื้นฐานนี้:

private static Bitmap ResizeBitmap(Bitmap srcbmp, int width, int height )
{
    Bitmap newimage = new Bitmap(width, height);
    using (Graphics g = Graphics.FromImage(newimage))
           g.DrawImage(srcbmp, 0, 0, width, height);
    return newimage;
}

0

มีบทความเกี่ยวกับโครงการรหัสเกี่ยวกับการใช้ GDI + สำหรับ. NET เพื่อทำการปรับขนาดรูปภาพโดยใช้การพูดการแก้ไข Bicubic

นอกจากนี้ยังมีบทความเกี่ยวกับหัวข้อนี้ในบล็อกอื่น (พนักงาน MS ฉันคิดว่า) แต่ฉันไม่สามารถหาลิงก์ได้ทุกที่ :( บางทีคนอื่นสามารถหามันได้?



0

นี่เป็นบทความที่ฉันเห็นว่าถูกอ้างอิงในโค้ดของ Paint.NET สำหรับการปรับขนาดภาพซ้ำ: เทคนิคการประมวลผลภาพอย่างง่ายโดย Paul Bourke


1: บทความที่ดี ไม่สามารถเข้าถึงลิงก์ แต่พบสิ่งนี้อีก: local.wasp.uwa.edu.au/~pbourke/texture_colour/imageprocess
Thomas Bratt

ฉันแก้ไขลิงก์ในโพสต์ต้นฉบับเนื่องจากลิงก์ของ Thomas เสียหายเช่นกัน ... paulbourke.net/texture_colour/imageprocess
Oskar Austegard

คำตอบนี้จะดีกว่าถ้ามันอธิบายส่วนที่เกี่ยวข้องของคำตอบแทนที่จะพึ่งพาลิงก์
KatieK

0

คุณอาจจะลองเคอร์เนลมายากล มันสร้างสิ่งประดิษฐ์ pixelation น้อยกว่า resub bicubic เมื่อยกระดับและมันยังให้ผลลัพธ์ที่ดีมากเมื่อลดระดับ ซอร์สโค้ดมีอยู่ใน c # จากเว็บไซต์


0

ฉันมีการปรับปรุงบางอย่างสำหรับคำตอบของ Doctor Jones

มันทำงานได้สำหรับผู้ที่ต้องการวิธีการปรับขนาดภาพสัดส่วน มันผ่านการทดสอบและใช้งานได้สำหรับฉัน

วิธีการเรียนฉันเพิ่ม:

public static System.Drawing.Bitmap ResizeImage(System.Drawing.Image image, Size size)
{
    return ResizeImage(image, size.Width, size.Height);
}


public static Size GetProportionedSize(Image image, int maxWidth, int maxHeight, bool withProportion)
{
    if (withProportion)
    {
        double sourceWidth = image.Width;
        double sourceHeight = image.Height;

        if (sourceWidth < maxWidth && sourceHeight < maxHeight)
        {
            maxWidth = (int)sourceWidth;
            maxHeight = (int)sourceHeight;
        }
        else
        {
            double aspect = sourceHeight / sourceWidth;

            if (sourceWidth < sourceHeight)
            {
                maxWidth = Convert.ToInt32(Math.Round((maxHeight / aspect), 0));
            }
            else
            {
                maxHeight = Convert.ToInt32(Math.Round((maxWidth * aspect), 0));
            }
        }
    }

    return new Size(maxWidth, maxHeight);
}

และใหม่พร้อมใช้งานตามรหัสนี้:

using (var resized = ImageUtilities.ResizeImage(image, ImageUtilities.GetProportionedSize(image, 50, 100)))
{
    ImageUtilities.SaveJpeg(@"C:\myimage.jpeg", resized, 90);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.