MaxHeight ve MaxWidth kısıtlamalarıyla görüntüyü orantılı olarak yeniden boyutlandırın


124

Kullanarak System.Drawing.Image.

Bir görüntü genişliği veya yüksekliği maksimum değeri aşarsa, orantılı olarak yeniden boyutlandırılması gerekir. Yeniden boyutlandırıldıktan sonra genişliğin veya yüksekliğin sınırı aşmadığından emin olması gerekir.

Genişlik ve Yükseklik, otomatik olarak maksimum ve minimuma (mümkün olan en büyük boyut) aşılmayana kadar yeniden boyutlandırılacak ve oranı da koruyacaktır.


@Sarawut Positwinyu - Ama en boy oranını istiyorsun?
Bibhu

Bir görüntü maksimum ve minimum yükseklik ve genişlik olarak yeniden boyutlandırılamazsa ve en boy oranı korunursa ne olmasını istersiniz?
Conrad Frix

@Bibhu Çok sayıda en boy oranı var mı? Bunu bilmiyorum. Sadece resim oranının mümkün olan orijinal resim oranı reklamına benzer olmasını istiyorum.
Sarawut Positwinyu

@Sarawut Positwinyu - en boy oranı hakkında daha fazla bilgi için bu wiki bağlantısına bakın. en.wikipedia.org/wiki/Aspect_ratio_%28image%29
Bibhu

1
@Sarawut Positwinyu En boy oranı terimini kötüye kullanmadınız. Ya da iyi bir şirketteyseniz
Conrad Frix

Yanıtlar:


300

Bunun gibi?

public static void Test()
{
    using (var image = Image.FromFile(@"c:\logo.png"))
    using (var newImage = ScaleImage(image, 300, 400))
    {
        newImage.Save(@"c:\test.png", ImageFormat.Png);
    }
}

public static Image ScaleImage(Image image, int maxWidth, int maxHeight)
{
    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);

    using (var graphics = Graphics.FromImage(newImage))
        graphics.DrawImage(image, 0, 0, newWidth, newHeight);

    return newImage;
}

7
@Alex Math.Min'in güzel kullanımı (bunu her zaman unuturum)
Conrad Frix

5
En azından bazı kaynakları korumak için Graphics nesnesinde bir using ifadesi kullanmanızı öneririm :)
Schalk

Sadece bir durum hakkında düşünüyorum, bu oranla çarpıldıktan sonra genişlik veya yüksekliğin maksimum genişlik veya maksimum yükseklikten daha büyük olmasının mümkün olup olmadığından emin değilim.
Sarawut Positwinyu

4
Ayrıca asp.net kullanıyorsanız System.Drawing.Image kullandığınızdan emin olun.
Induster

1
@Smith - görüntüyü kaydetmeniz gerekmiyorsa Kaydet yöntemini çalıştırmayın. Bu tam olarak ScaleImage yöntemimin yaptığı şeydir - görüntüyü kaydetmeden döndürür.
Alex Aza

5

Çalışma Çözümü:

100Kb'den daha küçük boyutlu resmi yeniden boyutlandırmak için

WriteableBitmap bitmap = new WriteableBitmap(140,140);
bitmap.SetSource(dlg.File.OpenRead());
image1.Source = bitmap;

Image img = new Image();
img.Source = bitmap;
WriteableBitmap i;

do
{
    ScaleTransform st = new ScaleTransform();
    st.ScaleX = 0.3;
    st.ScaleY = 0.3;
    i = new WriteableBitmap(img, st);
    img.Source = i;
} while (i.Pixels.Length / 1024 > 100);

Http://net4attack.blogspot.com/ adresinde Daha Fazla Referans


5

Çok daha uzun bir çözüm, ancak aşağıdaki senaryoları hesaba katar:

  1. Görüntü sınırlayıcı kutudan daha küçük mü?
  2. Görüntü ve Sınırlayıcı Kutu kare mi?
  3. Görüntü kare mi ve sınırlayıcı kutu
  4. Resim, sınırlayıcı kutudan daha geniş ve uzun mu?
  5. Görüntü, sınırlayıcı kutudan daha geniş mi
  6. Resim, sınırlayıcı kutudan daha uzun mu

    private Image ResizePhoto(FileInfo sourceImage, int desiredWidth, int desiredHeight)
    {
        //throw error if bouning box is to small
        if (desiredWidth < 4 || desiredHeight < 4)
            throw new InvalidOperationException("Bounding Box of Resize Photo must be larger than 4X4 pixels.");            
        var original = Bitmap.FromFile(sourceImage.FullName);
    
        //store image widths in variable for easier use
        var oW = (decimal)original.Width;
        var oH = (decimal)original.Height;
        var dW = (decimal)desiredWidth;
        var dH = (decimal)desiredHeight;
    
        //check if image already fits
        if (oW < dW && oH < dH)
            return original; //image fits in bounding box, keep size (center with css) If we made it bigger it would stretch the image resulting in loss of quality.
    
        //check for double squares
        if (oW == oH && dW == dH)
        {
            //image and bounding box are square, no need to calculate aspects, just downsize it with the bounding box
            Bitmap square = new Bitmap(original, (int)dW, (int)dH);
            original.Dispose();
            return square;
        }
    
        //check original image is square
        if (oW == oH)
        {
            //image is square, bounding box isn't.  Get smallest side of bounding box and resize to a square of that center the image vertically and horizontally with Css there will be space on one side.
            int smallSide = (int)Math.Min(dW, dH);
            Bitmap square = new Bitmap(original, smallSide, smallSide);
            original.Dispose();
            return square;
        }
    
        //not dealing with squares, figure out resizing within aspect ratios            
        if (oW > dW && oH > dH) //image is wider and taller than bounding box
        {
            var r = Math.Min(dW, dH) / Math.Min(oW, oH); //two dimensions so figure out which bounding box dimension is the smallest and which original image dimension is the smallest, already know original image is larger than bounding box
            var nH = oH * r; //will downscale the original image by an aspect ratio to fit in the bounding box at the maximum size within aspect ratio.
            var nW = oW * r;
            var resized = new Bitmap(original, (int)nW, (int)nH);
            original.Dispose();
            return resized;
        }
        else
        {
            if (oW > dW) //image is wider than bounding box
            {
                var r = dW / oW; //one dimension (width) so calculate the aspect ratio between the bounding box width and original image width
                var nW = oW * r; //downscale image by r to fit in the bounding box...
                var nH = oH * r;
                var resized = new Bitmap(original, (int)nW, (int)nH);
                original.Dispose();
                return resized;
            }
            else
            {
                //original image is taller than bounding box
                var r = dH / oH;
                var nH = oH * r;
                var nW = oW * r;
                var resized = new Bitmap(original, (int)nW, (int)nH);
                original.Dispose();
                return resized;
            }
        }
    }

1
Yeniden boyutlandırılan görüntünün yeni yüksekliğini hesaplamak için oranı kullandığınız birkaç yazım hatası olduğunu düşünüyorum. Doğru var nH = oH * r; Yanlış: var nH = oW * r;
wloescher

Düzeltildi, sadece yorum yapılmadı.
Ryan Mann
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.