Thay đổi kích thước hình ảnh theo tỷ lệ với các ràng buộc MaxHeight và MaxWidth


124

Sử dụng System.Drawing.Image.

Nếu chiều rộng hoặc chiều cao hình ảnh vượt quá mức tối đa, nó cần được thay đổi kích thước theo tỷ lệ. Sau khi thay đổi kích thước, cần đảm bảo rằng cả chiều rộng hoặc chiều cao vẫn không vượt quá giới hạn.

Chiều rộng và chiều cao sẽ được thay đổi kích thước cho đến khi nó không vượt quá mức tối đa và tối thiểu tự động (kích thước lớn nhất có thể) và cũng duy trì tỷ lệ.


@Sarawut Positwinyu - Nhưng bạn muốn tỷ lệ khung hình nào?
Bibhu

Bạn muốn điều gì xảy ra nếu một hình ảnh không thể thay đổi kích thước tối đa và tối thiểu của chiều cao và chiều rộng và tỷ lệ khung hình được duy trì?
Conrad Frix

@Bibhu Có nhiều loại tỷ lệ khung hình? tôi không biết về điều đó Tôi chỉ muốn tỷ lệ hình ảnh tương tự như quảng cáo tỷ lệ hình ảnh gốc có thể.
Sarawut Positwinyu

@Sarawut Positwinyu - hãy xem liên kết wiki này để biết thêm về tỷ lệ khung hình. vi.wikipedia.org/wiki/Aspect_ratio_%28image%29
Bibhu

1
@Sarawut Positwinyu Bạn đã không sử dụng sai tỷ lệ khung hình. Hoặc nếu bạn đã ở trong một công ty tốt
Conrad Frix

Câu trả lời:


300

Như thế này?

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 sử dụng tốt Math.Min (Tôi luôn quên cái đó)
Conrad Frix

5
Tôi khuyên bạn nên sử dụng câu lệnh sử dụng trên đối tượng Đồ họa ít nhất để tiết kiệm một số tài nguyên :)
Schalk

Tôi chỉ nghĩ về một trường hợp, tôi không chắc có thể hay không sau khi nhân với tỷ lệ chiều rộng Hoặc chiều cao vẫn có thể lớn hơn chiều rộng tối đa hoặc chiều cao tối đa.
Sarawut Positwinyu

4
Đồng thời đảm bảo rằng bạn đang sử dụng System.Drawing.Image nếu sử dụng asp.net.
Ấn tượng

1
@Smith - không chạy phương thức Save nếu bạn không cần lưu hình ảnh. Đây chính xác là những gì phương thức ScaleImage của tôi thực hiện - trả về hình ảnh mà không lưu nó.
Alex Aza

5

Giải pháp làm việc:

Đối với Thay đổi kích thước hình ảnh với kích thước thấp hơn 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);

Tham khảo thêm tại http://net4attack.blogspot.com/


5

Giải pháp dài hơn nhiều, nhưng chiếm các tình huống sau:

  1. Là hình ảnh nhỏ hơn hộp giới hạn?
  2. Hình ảnh và Hộp Bounding có vuông không?
  3. Là hình vuông và hộp giới hạn không
  4. Hình ảnh có rộng và cao hơn khung giới hạn không
  5. Hình ảnh có rộng hơn khung giới hạn không
  6. Là hình ảnh cao hơn hộp giới hạn

    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
Tôi nghĩ rằng có một vài lỗi chính tả trong đó bạn đang sử dụng tỷ lệ để tính chiều cao mới cho hình ảnh đã thay đổi kích thước. Đúng var nH = oH * r; Không chính xác: var nH = oW * r;
wloescher

Đã sửa, chỉ không bao giờ bình luận.
Ryan Mann
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.