ปรับขนาดภาพตามสัดส่วนด้วยข้อ จำกัด MaxHeight และ MaxWidth


124

การใช้System.Drawing.Image.

หากความกว้างหรือความสูงของรูปภาพเกินค่าสูงสุดจำเป็นต้องปรับขนาดตามสัดส่วน หลังจากปรับขนาดแล้วจำเป็นต้องตรวจสอบให้แน่ใจว่าความกว้างหรือความสูงยังไม่เกินขีด จำกัด

ความกว้างและความสูงจะถูกปรับขนาดจนกว่าจะไม่เกินสูงสุดและต่ำสุดโดยอัตโนมัติ (ขนาดใหญ่ที่สุดที่เป็นไปได้) และยังคงรักษาอัตราส่วนไว้


@ สราวุ ธ โพสิตวิญญู - แต่คุณต้องการอัตราส่วนเท่าใด?
Bibhu

คุณต้องการให้เกิดอะไรขึ้นหากไม่สามารถปรับขนาดภาพให้มีขนาดสูงสุดและต่ำสุดของความสูงและความกว้างและคงอัตราส่วนไว้ได้
Conrad Frix

@Bibhu อัตราส่วนภาพมีหลายประเภทหรือไม่? ฉันไม่รู้เกี่ยวกับเรื่องนั้น ฉันแค่อยากให้อัตราส่วนรูปภาพใกล้เคียงกับโฆษณาอัตราส่วนรูปภาพต้นฉบับ
Sarawut Positwinyu

@Sarawut Positwinyu - ดูลิงค์วิกินี้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับอัตราส่วน en.wikipedia.org/wiki/Aspect_ratio_%28image%29
Bibhu

1
@Sarawut Positwinyu คุณไม่ได้ใช้คำว่าอัตราส่วนภาพผิด หรือถ้าคุณทำคุณอยู่ในบริษัท ที่ดี
Conrad Frix

คำตอบ:


300

แบบนี้?

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 ใช้คณิตศาสตร์ได้ดี Min (ฉันมักจะลืมเรื่องนั้น)
Conrad Frix

5
ฉันขอแนะนำให้คุณใช้คำสั่งการใช้กับออบเจ็กต์กราฟิกอย่างน้อยก็เพื่อประหยัดทรัพยากร :)
ชาลก์

ฉันแค่คิดถึงกรณีหนึ่งฉันไม่แน่ใจว่าจะเป็นไปได้หรือไม่ว่าหลังจากคูณด้วยอัตราส่วนแล้วความกว้างหรือความสูงอาจยังมากกว่าความกว้างสูงสุดหรือความสูงสูงสุด
Sarawut Positwinyu

4
ตรวจสอบให้แน่ใจว่าคุณใช้ System.Drawing.Image หากใช้ asp.net
Induster

1
@Smith - อย่าเรียกใช้เมธอดบันทึกหากคุณไม่จำเป็นต้องบันทึกภาพ นี่คือสิ่งที่เมธอด ScaleImage ของฉันทำ - ส่งคืนรูปภาพโดยไม่บันทึก
Alex Aza

5

โซลูชันการทำงาน:

สำหรับ Resize ภาพที่มีขนาดต่ำกว่า 100Kb

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/


5

วิธีแก้ปัญหาที่ยาวกว่ามาก แต่อธิบายถึงสถานการณ์ต่อไปนี้:

  1. รูปภาพมีขนาดเล็กกว่ากรอบหรือไม่
  2. รูปภาพและ Bounding Box เป็นสี่เหลี่ยมจัตุรัสหรือไม่
  3. เป็นรูปสี่เหลี่ยมจัตุรัสและกรอบไม่ใช่
  4. ภาพกว้างและสูงกว่ากรอบหรือไม่
  5. ภาพกว้างกว่ากรอบขอบหรือไม่
  6. รูปภาพจะสูงกว่ากรอบกั้นหรือไม่

    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
ฉันคิดว่ามีการพิมพ์ผิดสองสามข้อที่คุณใช้อัตราส่วนในการคำนวณความสูงใหม่สำหรับภาพที่ปรับขนาด แก้ไข var nH = oH * r; ไม่ถูกต้อง: var nH = oW * r;
wloescher

คงแค่ไม่เคยแสดงความคิดเห็น
Ryan Mann
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.