Ändern Sie die Bildgröße proportional mit den Einschränkungen MaxHeight und MaxWidth

124

Verwenden von System.Drawing.Image.

Wenn eine Bildbreite oder -höhe das Maximum überschreitet, muss die Größe proportional geändert werden. Nach der Größenänderung muss sichergestellt werden, dass weder Breite noch Höhe den Grenzwert überschreiten.

Die Größe und Höhe wird so lange geändert, bis das Maximum und das Minimum automatisch überschritten werden (größtmögliche Größe), und das Verhältnis wird beibehalten.

Sarawut Positwinyu
quelle
@ Sarawut Positwinyu - Aber welches Seitenverhältnis möchten Sie?
Bibhu
Was möchten Sie tun, wenn die Größe eines Bilds nicht auf ein Maximum und ein Minimum der Höhe und Breite geändert werden kann und das Seitenverhältnis beibehalten wird?
Conrad Frix
@Bibhu Gibt es viele Arten von Seitenverhältnissen? Das weiß ich nicht. Ich möchte nur, dass das Bildverhältnis dem Originalbildverhältnis ähnelt, das möglich ist.
Sarawut Positwinyu
@Sarawut Positwinyu - Weitere Informationen zum Seitenverhältnis finden Sie in diesem Wiki-Link. en.wikipedia.org/wiki/Aspect_ratio_%28image%29
Bibhu
1
@Sarawut Positwinyu Du hast den Begriff Seitenverhältnis nicht missbraucht. Oder wenn Sie es getan haben, sind Sie in guter Gesellschaft
Conrad Frix

Antworten:

300

So was?

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;
}
Alex Aza
quelle
7
@ Alex nette Verwendung von Math.Min (das vergesse ich immer)
Conrad Frix
5
Ich würde vorschlagen, dass Sie eine using-Anweisung für das Graphics-Objekt verwenden, um zumindest einige Ressourcen zu sparen :)
Schalk
Ich denke nur an einen Fall, ich bin mir nicht sicher, ob es möglich ist oder nicht, dass nach Multiplikation mit dem Verhältnis die Breite oder Höhe immer noch größer als die maximale Breite oder Höhe sein könnte.
Sarawut Positwinyu
4
Stellen Sie außerdem sicher, dass Sie System.Drawing.Image verwenden, wenn Sie asp.net verwenden.
Induster
1
@Smith - Führen Sie die Speichermethode nicht aus, wenn Sie das Bild nicht speichern müssen. Genau das macht meine ScaleImage-Methode - sie gibt ein Bild zurück, ohne es zu speichern.
Alex Aza
5

Arbeitslösung:

Zum Ändern der Bildgröße mit einer Größe von weniger als 100 KB

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);

Weitere Informationen unter http://net4attack.blogspot.com/

user806084
quelle
5

Viel längere Lösung, berücksichtigt aber die folgenden Szenarien:

  1. Ist das Bild kleiner als der Begrenzungsrahmen?
  2. Ist das Bild und der Begrenzungsrahmen quadratisch?
  3. Ist das Bild quadratisch und der Begrenzungsrahmen nicht
  4. Ist das Bild breiter und höher als der Begrenzungsrahmen?
  5. Ist das Bild breiter als der Begrenzungsrahmen?
  6. Ist das Bild größer als der Begrenzungsrahmen?

    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;
            }
        }
    }
Ryan Mann
quelle
1
Ich denke, es gibt ein paar Tippfehler, bei denen Sie das Verhältnis verwenden, um die neue Höhe für die Bildgröße zu berechnen. Korrigieren Sie var nH = oH * r; Falsch: var nH = oW * r;
Wloescher
Behoben, nur nie kommentiert.
Ryan Mann