Thay đổi kích thước hình ảnh mà không làm giảm chất lượng [đã đóng]


108

Làm cách nào để thay đổi kích thước hình ảnh mà chất lượng hình ảnh không bị ảnh hưởng?


Bạn có thể cho chúng tôi biết thêm chi tiết? Hình ảnh của bạn có kích thước bao nhiêu và bạn cần kích thước của chúng?
Mark Ransom,


6
imageresizing.net - Thư viện này tạo ra hình ảnh chất lượng cao nhất mà bạn có thể nhận được với .NET
Lilith sông

Câu trả lời:


217

Như rcar đã nói, bạn không thể không giảm chất lượng, điều tốt nhất bạn có thể làm trong c # là:

Bitmap newImage = new Bitmap(newWidth, newHeight);
using (Graphics gr = Graphics.FromImage(newImage))
{
    gr.SmoothingMode = SmoothingMode.HighQuality;
    gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
    gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
    gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
}

2
Tôi có thể thêm rằng (nếu có thể) người dùng nên bắt đầu với một hình ảnh Bitmap, chẳng hạn, lớn gấp đôi so với nhu cầu và sau đó thu nhỏ lại. Hình ảnh thu được sẽ khá mịn.
Pretzel

2
gr.SmoothingMode = SmoothingMode.HighQuality là mã tốt hơn. Hiện tại, HighQuality và AntiAlias ​​đều giống nhau, nhưng có thể trong tương lai Microsoft sẽ phát minh ra thứ gì đó mới. Chất lượng cao luôn phải là một bí danh tốt nhất.
Eyal

4
Phương pháp 'System.Drawing.Image.Save (tên tệp chuỗi, định dạng ImageFormat)' lưu các JPG với chất lượng 75. Hình ảnh bị mờ và không được khách hàng chấp nhận. Điều gì đã khắc phục sự cố chất lượng là sử dụng Lưu (tên tệp chuỗi, bộ mã hóa ImageCodecInfo, EncoderParameters encoderParams) thay thế và chỉ định giá trị chất lượng gần 100.
Riga

3
Đây lá hiện vật trên biên giới của hình ảnh đôi khi ...
jjxtra

1
Tôi đã có hiện vật trên biên giới về việc sử dụng này. Bất kỳ gợi ý?
Gopichandar

32

Trừ khi bạn đang làm đồ họa vector, không có cách nào để thay đổi kích thước hình ảnh mà không có khả năng làm giảm chất lượng hình ảnh.


1
trừ khi bạn đang mở rộng nó ...
Blair Conrad

Bạn có thể mở rộng nó mà không bị mất bất kỳ thông tin, nhưng có nhiều loại khác nhau của bộ lọc mà bạn có thể sử dụng mà cho kết quả khác nhau - zero-trật tự giữ, thấp-pass vv
Adam Rosenfield

24
private static Image resizeImage(Image imgToResize, Size size)
{
    int sourceWidth = imgToResize.Width;
    int sourceHeight = imgToResize.Height;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)size.Width / (float)sourceWidth);
    nPercentH = ((float)size.Height / (float)sourceHeight);

    if (nPercentH < nPercentW)
        nPercent = nPercentH;
    else
        nPercent = nPercentW;

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

    Bitmap b = new Bitmap(destWidth, destHeight);
    Graphics g = Graphics.FromImage((Image)b);
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;

    g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
    g.Dispose();

    return (Image)b;
}

từ đây


Điều này hoạt động, nhưng trả về chất lượng giống hệt câu trả lời của Kris Erickso. Rất vui khi thấy Kích thước được sử dụng mặc dù ...
Sam Jones


3

Trừ khi bạn thay đổi kích thước, bạn không thể làm điều này với đồ họa raster.

Những gì bạn có thể làm với tính năng lọc và làm mịn tốt là thay đổi kích thước mà không làm giảm chất lượng đáng chú ý .

Bạn cũng có thể thay đổi siêu dữ liệu DPI của hình ảnh (giả sử nó có một số) sẽ giữ chính xác cùng một số lượng pixel, nhưng sẽ thay đổi cách người chỉnh sửa hình ảnh nghĩ về nó trong các phép đo 'thế giới thực'.

Và chỉ để bao gồm tất cả các cơ sở, nếu bạn thực sự muốn chỉ kích thước tệp của hình ảnh chứ không phải kích thước hình ảnh thực tế, tôi khuyên bạn nên xem xét mã hóa không mất dữ liệu của dữ liệu hình ảnh. Đề xuất của tôi cho việc này là lưu lại hình ảnh dưới dạng tệp .png (Tôi có xu hướng sử dụng paint làm trình chuyển mã miễn phí cho hình ảnh trong windows. Tải hình ảnh trong paint, lưu ở định dạng mới)


3

Bạn không thể thay đổi kích thước hình ảnh mà không làm giảm chất lượng, đơn giản vì bạn đang giảm số lượng pixel.

Không giảm kích thước phía máy khách, bởi vì các trình duyệt không thực hiện tốt công việc thay đổi kích thước hình ảnh.

Những gì bạn có thể làm là thay đổi kích thước theo chương trình trước khi hiển thị hoặc khi người dùng tải lên.

Đây là một bài viết giải thích một cách để thực hiện việc này trong c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx


"trình duyệt không làm tốt công việc của thay đổi kích thước hình ảnh" - điều này có thể đã đúng trong '08, nhưng may mắn là chúng tôi dặm về phía trước trong lĩnh vực này bây giờ (đến một mức độ lớn do các phiên bản IE cũ chậm làm sáng tỏ dần).
Camilo Martin

2

Xem bạn có thích chất lượng thay đổi kích thước hình ảnh của mô-đun ASP.NET mã nguồn mở này không. Có một bản trình diễn trực tiếp, vì vậy bạn có thể tự làm với nó. Nó mang lại kết quả mà (đối với tôi) không thể phân biệt được với đầu ra của Photoshop. Nó cũng có kích thước tệp tương tự - MS đã làm rất tốt trên bộ mã hóa JPEG của họ.


Vâng, JPEG là một định dạng tương đối đơn giản. Bạn không thể làm gì nhiều để đánh bại các triển khai tham chiếu về chất lượng / kích thước tệp bởi vì cuối cùng nó chỉ là hệ số DCT với nén chung.
Camilo Martin

1

Có một cái gì đó ngoài kia, thay đổi kích thước theo ngữ cảnh, không biết bạn có sử dụng được không, nhưng nó rất đáng xem, đó là điều chắc chắn

Bản giới thiệu video đẹp (Phóng to xuất hiện ở giữa) http://www.youtube.com/watch?v=vIFCV2spKtg

Ở đây có thể có một số mã. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/

Đó có phải là quá mức cần thiết? Có thể có một số bộ lọc dễ dàng bạn có thể áp dụng cho hình ảnh phóng to để làm mờ các pixel một chút, bạn có thể xem xét điều đó.


Tôi nghi ngờ nó không liên quan gì đến câu hỏi ban đầu, nhưng tôi thực sự yêu thích kỹ thuật này.
Matt Cruikshank, 17/09/08

1

Bạn đang thay đổi kích thước lớn hơn hay nhỏ hơn? Bằng một% nhỏ hay một hệ số lớn hơn như 2x, 3x? Ý bạn là gì về chất lượng cho ứng dụng của bạn? Và loại hình ảnh nào - ảnh chụp, hình vẽ đường nét cứng, hay gì? Viết mã mài pixel cấp thấp của riêng bạn hoặc cố gắng làm điều đó càng nhiều càng tốt với các thư viện hiện có (.net hoặc bất cứ điều gì)?

Có một lượng lớn kiến ​​thức về chủ đề này. Khái niệm chính là nội suy.

Đề xuất duyệt web:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* cho C #: https: //secure.codeproject.com/KB/GDI-plus/imageprocessing4.aspx?display=PrintAll&fid=3657&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=629945 * đây là java cụ thể nhưng có thể mang tính giáo dục - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html


1

Tại đây, bạn cũng có thể tìm thêm mã hình mờ trong lớp này:

public class ImageProcessor
    {
        public Bitmap Resize(Bitmap image, int newWidth, int newHeight, string message)
        {
            try
            {
                Bitmap newImage = new Bitmap(newWidth, Calculations(image.Width, image.Height, newWidth));

                using (Graphics gr = Graphics.FromImage(newImage))
                {
                    gr.SmoothingMode = SmoothingMode.AntiAlias;
                    gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    gr.DrawImage(image, new Rectangle(0, 0, newImage.Width, newImage.Height));

                    var myBrush = new SolidBrush(Color.FromArgb(70, 205, 205, 205));

                    double diagonal = Math.Sqrt(newImage.Width * newImage.Width + newImage.Height * newImage.Height);

                    Rectangle containerBox = new Rectangle();

                    containerBox.X = (int)(diagonal / 10);
                    float messageLength = (float)(diagonal / message.Length * 1);
                    containerBox.Y = -(int)(messageLength / 1.6);

                    Font stringFont = new Font("verdana", messageLength);

                    StringFormat sf = new StringFormat();

                    float slope = (float)(Math.Atan2(newImage.Height, newImage.Width) * 180 / Math.PI);

                    gr.RotateTransform(slope);
                    gr.DrawString(message, stringFont, myBrush, containerBox, sf);
                    return newImage;
                }
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }

        public int Calculations(decimal w1, decimal h1, int newWidth)
        {
            decimal height = 0;
            decimal ratio = 0;


            if (newWidth < w1)
            {
                ratio = w1 / newWidth;
                height = h1 / ratio;

                return height.To<int>();
            }

            if (w1 < newWidth)
            {
                ratio = newWidth / w1;
                height = h1 * ratio;
                return height.To<int>();
            }

            return height.To<int>();
        }

    }

0

Đây là một chuỗi diễn đàn cung cấp mẫu mã thay đổi kích thước hình ảnh C #. Bạn có thể sử dụng một trong các chất kết dính thư viện GD để lấy mẫu lại trong C #.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.