MaxHeight制約とMaxWidth制約で画像を均等にサイズ変更


124

を使用しSystem.Drawing.Imageます。

画像の幅または高さが最大値を超える場合は、それに比例してサイズを変更する必要があります。サイズ変更後、幅も高さも制限を超えていないことを確認する必要があります。

幅と高さは、自動的に最大値と最小値(最大サイズ)を超えないようにサイズ変更され、比率も維持されます。


@Sarawut Positwinyu-しかし、どのアスペクト比が必要ですか?
Bibhu

高さと幅の最大と最小に画像のサイズを変更できず、アスペクト比が維持されている場合はどうしますか?
コンラッドフリックス

@Bibhuアスペクト比の種類はたくさんありますか?私はそれについて知りません。画像比率を元の画像比率広告と同じようにしたいだけです。
Sarawut Positwinyu

@Sarawut Positwinyu-アスペクト比の詳細については、このWikiリンクを参照してください。en.wikipedia.org/wiki/Aspect_ratio_%28image%29
Bibhu

1
@Sarawut Positwinyuアスペクト比という用語を誤用していません。または、あなたが良き
仲間

回答:


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のMath.Minの素晴らしい使い方(私はいつもそのことを忘れています)
Conrad Frix

5
少なくともいくつかのリソースを節約するために、グラフィックスオブジェクトでusingステートメントを使用することをお勧めします:)
Schalk

ケースについて考えているだけですが、比率を掛けた後でも、幅または高さが最大幅または最大高さよりも大きくなる可能性があるかどうかはわかりません。
Sarawut Positwinyu

4
また、asp.netを使用している場合は、System.Drawing.Imageを使用していることも確認してください。
インダストラー

1
@Smith-画像を保存する必要がない場合は、Saveメソッドを実行しないでください。これはまさに私のScaleImageメソッドが行うことです-保存せずに画像を返します。
Alex Aza

5

ワーキングソリューション:

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

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 2017

修正済み、コメントはありません。
Ryan Mann
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.