Herhangi bir kalite kaybı olmadan bir Görüntüyü yeniden boyutlandırma [kapalı]


109

Görüntü kalitesi etkilenmeden bir görüntüyü nasıl yeniden boyutlandırabilirim?


Bize daha fazla ayrıntı verebilir misiniz? Resimleriniz ne kadar büyük ve ne boyutta olmalarına ihtiyacınız var?
Mark Ransom


6
imageresizing.net - Bu kütüphane .NET ile elde edebileceğiniz en yüksek kaliteli görüntüleri üretir
Lilith River

Yanıtlar:


218

Gibi rcar diyor, bazı kalite kaybı olmadan, en iyi sizsiniz c # yapabilirim edemez:

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
Kullanıcının (mümkünse), örneğin olması gerekenden iki kat daha büyük olan bir Bitmap görüntüsü ile başlaması ve ardından küçültmesi gerektiğini ekleyebilirim. Ortaya çıkan görüntü oldukça düzgün olmalıdır.
Pretzel

2
gr.SmoothingMode = SmoothingMode.HighQuality daha iyi koddur. Şu anda, HighQuality ve AntiAlias ​​aynı şeydir, ancak gelecekte Microsoft yeni bir şey icat edebilir. HighQuality her zaman en iyisi için bir takma ad olmalıdır.
Eyal

4
'System.Drawing.Image.Save (dize dosya adı, ImageFormat formatı)' yöntemi, JPG'leri 75 kalitesinde kaydeder. Görüntü bulanıktı ve istemci tarafından kabul edilemez. Kalite sorununu çözen şey, bunun yerine Kaydet'i (dize dosya adı, ImageCodecInfo kodlayıcı, EncoderParameters kodlayıcıParams) kullanmak ve 100'e yakın bir kalite değeri belirlemekti.
Riga

3
Bu bazen görüntünün sınırında eserler bırakır ...
jjxtra

1
Bunu kullanırken sınırda eserlerim vardı. Herhangi bir öneriniz var mı?
Gopichandar

32

Vektör grafikleri yapmadığınız sürece, bir görüntü kalitesini potansiyel olarak kaybetmeden bir görüntüyü yeniden boyutlandırmanın bir yolu yoktur.


1
genişletmiyorsan ...
Blair Conrad

Herhangi bir bilgi kaybetmeden genişletebilirsiniz, ancak farklı sonuçlar veren kullanabileceğiniz farklı filtre türleri vardır - sıfır derece bekletme, düşük geçiş vb.
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;
}

dan burada


Bu işe yarıyor, ancak Kris Erickso'nun cevabına aynı kaliteyi döndürüyor. Yine de kullanılan boyutu görmek güzel ...
Sam Jones


3

Yeniden boyutlandırmadığınız sürece bunu raster grafiklerle yapamazsınız.

İyi filtreleme ve yumuşatma ile yapabileceğiniz şey, göze çarpan herhangi bir kaliteyi kaybetmeden yeniden boyutlandırmaktır .

Ayrıca, görüntünün DPI meta verilerini (bazılarına sahip olduğunu varsayarak) değiştirebilir ve bu, tam olarak aynı piksel sayısını koruyacak, ancak görüntü editörlerinin 'gerçek dünya' ölçümlerinde onun hakkındaki düşüncelerini değiştirecektir.

Ve tüm temelleri kapsayacak şekilde, görüntünün gerçek boyutlarını değil de yalnızca dosya boyutunu kastettiyseniz, görüntü verilerinin kayıpsız kodlamasına bakmanızı öneririm. Bunun için önerim, resmi bir .png dosyası olarak yeniden kaydetmek olacaktır (boyayı pencerelerdeki resimler için ücretsiz bir kod dönüştürücü olarak kullanma eğilimindeyim. Resmi boyayla yükleyin, yeni formatta olduğu gibi kaydedin)


3

Piksel sayısını azalttığınız için bir görüntüyü kalite kaybı olmadan yeniden boyutlandıramazsınız.

İstemci tarafının boyutunu küçültmeyin, çünkü tarayıcılar resimleri yeniden boyutlandırma konusunda iyi bir iş çıkarmaz.

Yapabileceğiniz şey, boyutu işlemeden önce veya kullanıcı yüklerken programlı olarak değiştirmektir.

Bunu c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx ile yapmanın bir yolunu açıklayan bir makale burada.


"tarayıcılar görüntüleri yeniden boyutlandırma konusunda iyi bir iş çıkarmıyor" - bu, '08'de doğru olabilir, ancak neyse ki şu anda bu alanda kilometrelerce ilerideyiz (büyük ölçüde eski IE sürümlerinin yavaş yavaş kaybolması nedeniyle).
Camilo Martin

2

Bu açık kaynaklı ASP.NET modülünün görüntü yeniden boyutlandırma kalitesini beğenip beğenmediğinize bakın . Canlı bir demo var, böylece onunla uğraşabilirsiniz. Photoshop çıktısından ayırt edilmesi (benim için) imkansız sonuçlar veriyor. Aynı zamanda benzer dosya boyutlarına sahiptir - MS, JPEG kodlayıcısında iyi bir iş çıkardı.


JPEG nispeten basit bir formattır. Referans uygulamalarını kalite / dosya boyutu açısından yenmek için yapabileceğiniz pek bir şey yok çünkü sonuçta sadece genel sıkıştırmalı DCT katsayıları var.
Camilo Martin

1

Orada bir şey var, bağlama duyarlı yeniden boyutlandırma, onu kullanıp kullanamayacağınızı bilmiyorum, ama bakmaya değer, orası kesin

Güzel bir video demosu (Büyütme ortaya doğru görünür) http://www.youtube.com/watch?v=vIFCV2spKtg

Burada bazı kodlar olabilir. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/

Bu aşırı mıydı? Belki pikselleri biraz bulanıklaştırmak için büyütülmüş bir görüntüye uygulayabileceğiniz bazı kolay filtreler vardır, buna bakabilirsiniz.


Orijinal soruyla hiçbir ilgisi olmadığından şüpheleniyorum, ancak bu tekniği seviyorum.
Matt Cruikshank

1

Daha büyük mü yoksa daha küçük mü yeniden boyutlandırıyorsunuz? Küçük bir yüzde ile mi yoksa 2x, 3x gibi daha büyük bir faktörle mi? Uygulamanız için kalite derken neyi kastediyorsunuz? Ve ne tür resimler - fotoğraflar, keskin kenarlı çizimler veya ne? Kendi düşük seviyeli piksel öğütme kodunuzu yazmak veya mevcut kitaplıklarla (.net veya her neyse) mümkün olduğunca çok yapmaya mı çalışıyorsunuz?

Bu konuda geniş bir bilgi birikimi var. Anahtar kavram enterpolasyondur.

Tarama önerileri:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* C # için: 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 * bu java'ya özeldir ancak eğitici olabilir - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html


1

Burada, bu sınıfa filigran kodları da ekleyebilirsiniz:

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

Burada, bir C # resmi yeniden boyutlandırma kodu örneği sağlayan bir forum dizisi . C # ile yeniden örnekleme yapmak için GD kitaplık bağlayıcılarından birini kullanabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.