2011-06-28 15 views
112

Korzystanie z System.Drawing.Image.Zmiana rozmiaru obrazu proporcjonalnie z ograniczeniami MaxHeight i MaxWidth

Jeśli szerokość lub wysokość obrazu przekracza wartość maksymalną, należy zmienić jego rozmiar proporcjonalnie. Po zmianie rozmiaru należy się upewnić, że ani szerokość ani wysokość nie przekraczają limitu.

Szerokość i wysokość zostaną przeskalowane, dopóki nie zostanie automatycznie przekroczona maksymalna i minimalna (największy możliwy rozmiar), a także zachowane zostaną proporcje.

+0

@Sarawut Positwinyu - Ale co Proporcje chcesz? – Bibhu

+0

Co chcesz zrobić, jeśli nie można zmienić rozmiaru obrazu na maksymalną i minimalną wysokość i szerokość, a współczynnik proporcji zostanie zachowany? –

+0

@Bibhu Czy istnieje wiele typów współczynników kształtu? nie wiem o tym. Chcę tylko, aby proporcje obrazu były podobne, jak to możliwe w przypadku reklamy o oryginalnym stosunku obrazu. –

Odpowiedz

270

Podoba Ci się to?

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 nice use of Math.Min (I zawsze zapominaj o tym) –

+5

Proponuję użyć instrukcji using na obiekcie Graphics przynajmniej by zaoszczędzić trochę zasobów :) – Schalk

+0

Po prostu myślę o sprawie, nie wiem czy to możliwe, czy nie, po pomnożeniu przez stosunek szerokości lub wysokości może być większy niż maksymalna szerokość lub maksymalna wysokość. –

4

Roztwór roboczy:

Dla Resize obrazu o wielkości niższe niż 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); 

Więcej referencyjny w http://net4attack.blogspot.com/

5

znacznie dłużej rozwiązanie, ale stanowi dla następujących scenariuszy:

  1. Czy obraz jest mniejszy od obwiedni?
  2. Czy obraz i pole ograniczające są kwadratowe?
  3. Czy kwadratowy obrazu i obwiednia nie jest
  4. Czy obraz jest szerszy i wyższy niż obwiedni
  5. obraz jest szerszy niż obwiedni
  6. Czy obraz jest wyższy niż obwiedni

    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

Myślę, że istnieje kilka literówek, w których używasz współczynnika do obliczenia nowej wysokości dla obrazu o zmienionym rozmiarze. Prawidłowy var nH = oH * r; Nieprawidłowo: var nH = oW * r; – wloescher

Powiązane problemy