MaxHeight 및 MaxWidth 제약 조건에 비례하여 이미지 크기 조정


124

사용 System.Drawing.Image.

이미지 너비 또는 높이가 최대 값을 초과하는 경우 비례 적으로 크기를 조정해야합니다. 크기를 조정 한 후에는 너비 나 높이가 제한을 초과하지 않는지 확인해야합니다.

너비 및 높이는 자동으로 최대 및 최소를 초과하지 않을 때까지 (가능한 가장 큰 크기) 크기가 조정되고 비율도 유지됩니다.


@Sarawut Positwinyu-하지만 어떤 종횡비를 원하십니까?
Bibhu

이미지 크기를 높이와 너비의 최대 및 최소로 조정할 수없고 종횡비가 유지되는 경우 어떻게 하시겠습니까?
Conrad Frix 2011 년

@Bibhu 종횡비에는 많은 유형이 있습니까? 나는 그것에 대해 모른다. 나는 단지 이미지 비율이 가능한 원본 이미지 비율 광고와 유사하기를 원합니다.
Sarawut Positwinyu 2011 년

@Sarawut Positwinyu-종횡비에 대한 자세한 내용은이 위키 링크를 참조하십시오. en.wikipedia.org/wiki/Aspect_ratio_%28image%29
Bibhu

1
@Sarawut Positwinyu 당신은 종횡비라는 용어를 오용하지 않았습니다. 당신이 한 경우 또는 당신은에있어 좋은 회사
콘라드 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
(난 항상 그 일에 대해 잊지) Math.Min의 @ 알렉스 좋은 사용
콘래드 Frix

5
적어도 일부 리소스를 절약하기 위해 Graphics 개체에 using 문을 사용하는 것이 좋습니다. :)
Schalk

나는 단지 케이스에 대해 생각하고 있는데, 비율과 곱한 후에도 너비 또는 높이가 여전히 최대 너비 또는 최대 높이보다 클 수 있는지 여부가 확실하지 않습니다.
Sarawut Positwinyu 2011 년

4
또한 asp.net을 사용하는 경우 System.Drawing.Image를 사용하고 있는지 확인하십시오.
Induster 2012-08-18

1
@Smith-이미지를 저장할 필요가 없으면 Save 메서드를 실행하지 마십시오. 이것이 바로 내 ScaleImage 메서드가하는 일입니다. 이미지를 저장하지 않고 반환합니다.
Alex Aza

5

작업 솔루션 :

크기가 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. 이미지와 경계 상자가 정사각형입니까?
  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.