2013-08-02 5 views
2

Я разрабатываю приложение, используя .NET (4.5) MVC (4.0) C# (5.0). Я хочу сгенерировать изображение с изображением, которое у меня уже есть. Теперь требование похоже на то, что оно должно генерировать миниатюру максимальной квадратной части из центра изображения, не растягивая не целое изображение, кроме изображения квадратного размера.C# crop изображение из центра

как в примере моего размера исходного изображения: 578x700 я хочу создать миниатюру для размера заполнителя: 200x150, 185x138, 140x140, 89x66, 80x80, 45x45, 28x28

я был создать свой код, приведенный ниже, но не сделал получить точный результат. вот мой метод ядра, которые генерируют на миниатюру

public string GenerateThumbnailFromImage(string imageFilePath, int thumbWidth, int thumbHeight) 
    { 
     try 
     { 
      //Check if file exist 
      if (File.Exists(imageFilePath)) 
      { 
       //bool preserveAspectRatio = true; 
       string oldFilePath = imageFilePath; 
       string folderPath = Path.GetDirectoryName(imageFilePath); 
       string filename = Path.GetFileNameWithoutExtension(imageFilePath); 

       //Rename file with thumbnail size 
       filename = filename + "_" + thumbWidth.ToString() + Path.GetExtension(imageFilePath); 
       imageFilePath = Path.Combine(folderPath, filename); 


       using (Image image = Image.FromFile(oldFilePath)) 
       { 
        decimal originalWidth = image.Width; 
        decimal originalHeight = image.Height; 
        decimal requiredThumbWidth = thumbWidth; 
        decimal requiredThumbHeight = thumbHeight; 
        decimal startXPosition = 0; 
        decimal startYPosition = 0; 
        decimal screenWidth = originalWidth; 
        decimal screenHeight = originalHeight; 
        decimal ar = thumbWidth < thumbHeight 
            ? originalWidth/originalHeight 
            : originalHeight/originalWidth; 

        //Define Starting Position for thumbnail generation 
        if (originalWidth > originalHeight) 
         startXPosition = (originalWidth - originalHeight)/2; 
        else if (originalHeight > originalWidth) 
         startYPosition = (originalHeight - originalWidth)/2; 

        if (thumbWidth>thumbHeight) 
        { 
         requiredThumbWidth = thumbWidth; 
         requiredThumbHeight = requiredThumbWidth*ar; 
        } 
        else if (thumbHeight>thumbWidth) 
        { 
         requiredThumbHeight = thumbHeight; 
         requiredThumbWidth = requiredThumbHeight*ar; 
        } 
        else 
        { 
         requiredThumbWidth = thumbWidth; 
         requiredThumbHeight = thumbWidth; 
        } 

        using (var bmp = new Bitmap((int)requiredThumbWidth, (int)requiredThumbHeight)) 
        { 
         Graphics gr = Graphics.FromImage(bmp); 
         gr.SmoothingMode = SmoothingMode.HighQuality; 
         gr.CompositingQuality = CompositingQuality.HighQuality; 
         gr.InterpolationMode = InterpolationMode.High; 
         var rectDestination = new Rectangle(0, 0, (int)requiredThumbWidth, (int)requiredThumbHeight); 

         gr.DrawImage(image, rectDestination, (int)startXPosition, (int)startYPosition, (int)screenWidth, (int)screenHeight, GraphicsUnit.Pixel); 
         bmp.Save(imageFilePath); 

         return filename; 
        } 
       } 
      } 
      return null; 
     } 
     catch (Exception ex) 
     { 
      GlobalUtil.HandleAndLogException(ex, this); 
      throw ex; 
     } 
     finally 
     { 

     } 
    } 
+0

«не получить точный результат» не очень описательный – Sayse

+0

возможно дубликат [это] (Http: // StackOverflow.com/q/10242762/2256349) – Naren

+0

@Naren Этот пост предназначен для обрезки миниатюры, если этот парень нуждается в изменении размера для миниатюры, тогда мой ответ ниже. –

ответ

1

сделал это несколько раз, прежде чем, хитрость заключается в том, чтобы соответствовать высоте изображения во-первых, изменить масштаб ширины к пропорции, что вы должны были уменьшить высоту, затем повторите с ширины, если она по-прежнему не соответствует ширине и уменьшает более новую масштабированную высоту на эту дополнительную пропорцию. Таким образом, у вас есть эскиз, который всегда подходит, возможно, некоторые пробелы в X или Y, но изображение по-прежнему находится в одинаковых пропорциях, а не растянуто.

int originalHeight; 
int originalWidth; 
int imageHeight; 
int imageWidth; 
int requiredHeight; 
int requiredWidth; 
double scale; 

if(originalHeight > requiredHeight) 
{ 
    scale = requiredHeight/originalHeight; 
    imageHeight = requiredHeight; 
    imageWidth = originalHeight * scale; 
} 

if(imageWidth > requiredWidth) 
{ 
    scale = requiredWidth/imageWidth; 
    imageWidth = requiredWidth; 
    imageHeight = imageHeight * scale; 
} 

А потом рисунок, что Image в новый Bitmap этого размера, используя Graphics объект

7

Попробуйте это:

bool SaveCroppedImage(Image image, int targetWidth, int targetHeight, string filePath) 
{ 
    ImageCodecInfo jpgInfo = ImageCodecInfo.GetImageEncoders().Where(codecInfo => codecInfo.MimeType == "image/jpeg").First(); 
    Image finalImage = image; 
    System.Drawing.Bitmap bitmap = null; 
    try 
    { 
     int left = 0; 
     int top = 0; 
     int srcWidth = targetWidth; 
     int srcHeight = targetHeight; 
     bitmap = new System.Drawing.Bitmap(targetWidth, targetHeight); 
     double croppedHeightToWidth = (double)targetHeight/targetWidth; 
     double croppedWidthToHeight = (double)targetWidth/targetHeight; 

     if (image.Width > image.Height) 
     { 
      srcWidth = (int)(Math.Round(image.Height * croppedWidthToHeight)); 
      if (srcWidth < image.Width) 
      { 
       srcHeight = image.Height; 
       left = (image.Width - srcWidth)/2; 
      } 
      else 
      { 
       srcHeight = (int)Math.Round(image.Height * ((double)image.Width/srcWidth)); 
       srcWidth = image.Width; 
       top = (image.Height - srcHeight)/2; 
      } 
     } 
     else 
     { 
      srcHeight = (int)(Math.Round(image.Width * croppedHeightToWidth)); 
      if (srcHeight < image.Height) 
      { 
       srcWidth = image.Width; 
       top = (image.Height - srcHeight)/2; 
      } 
      else 
      { 
       srcWidth = (int)Math.Round(image.Width * ((double)image.Height/srcHeight)); 
       srcHeight = image.Height; 
       left = (image.Width - srcWidth)/2; 
      } 
     } 
     using (Graphics g = Graphics.FromImage(bitmap)) 
     { 
      g.SmoothingMode = SmoothingMode.HighQuality; 
      g.PixelOffsetMode = PixelOffsetMode.HighQuality; 
      g.CompositingQuality = CompositingQuality.HighQuality; 
      g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
      g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height), new Rectangle(left, top, srcWidth, srcHeight), GraphicsUnit.Pixel); 
     } 
     finalImage = bitmap; 
    } 
    catch { } 
    try 
    { 
     using (EncoderParameters encParams = new EncoderParameters(1)) 
     { 
      encParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)100); 
      //quality should be in the range [0..100] .. 100 for max, 0 for min (0 best compression) 
      finalImage.Save(filePath, jpgInfo, encParams); 
      return true; 
     } 
    } 
    catch { } 
    if (bitmap != null) 
    { 
     bitmap.Dispose(); 
    } 
    return false; 
} 
4

Вы должны получить соотношение размера назначения против фактического размера , Масштабируйте более короткую сторону, пока она не коснется фактического размера изображения. Обрезайте его, начиная с центра, и масштабируйте его до нужного размера.

Вот код:

 


public static Image ResizeImage(Image imgToResize, Size destinationSize) 
     { 
      var originalWidth = imgToResize.Width; 
      var originalHeight = imgToResize.Height; 

      //how many units are there to make the original length 
      var hRatio = (float)originalHeight/destinationSize.Height; 
      var wRatio = (float)originalWidth/destinationSize.Width; 

      //get the shorter side 
      var ratio = Math.Min(hRatio, wRatio); 

      var hScale = Convert.ToInt32(destinationSize.Height * ratio); 
      var wScale = Convert.ToInt32(destinationSize.Width * ratio); 

      //start cropping from the center 
      var startX = (originalWidth - wScale)/2; 
      var startY = (originalHeight - hScale)/2; 

      //crop the image from the specified location and size 
      var sourceRectangle = new Rectangle(startX, startY, wScale, hScale); 

      //the future size of the image 
      var bitmap = new Bitmap(destinationSize.Width, destinationSize.Height); 

      //fill-in the whole bitmap 
      var destinationRectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height); 

      //generate the new image 
      using (var g = Graphics.FromImage(bitmap)) 
      { 
       g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
       g.DrawImage(imgToResize, destinationRectangle, sourceRectangle, GraphicsUnit.Pixel); 
      } 

      return bitmap; 

     } 

 

Зов это следующим образом:

 

var thumbImage = ImageHelper.ResizeImage(image, new Size(45, 45)); 
thumbImage.Save(thumbFullPath); 
 
+0

Кажется, что вы только изменяете размер изображения. Я попробовал вашу функцию, и она дает тот же результат, что и моя собственная функция, которая просто изменяет размер изображения. Разве он не собирался обрезать его? –

+0

Нет, просто попробуйте его с более крупным изображением, которое он обрезает и масштабирует, поэтому он держит вещи в пропорциях. он отлично работает –

0
public 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(maxWidth, maxWidth); 
    using (var graphics = Graphics.FromImage(newImage)) 
    { 
     // Calculate x and y which center the image 
     int y = (maxHeight/2) - newHeight/2; 
     int x = (maxWidth/2) - newWidth/2; 

     // Draw image on x and y with newWidth and newHeight 
     graphics.DrawImage(image, x, y, newWidth, newHeight); 
    } 

    return newImage; 
} 
2

В вашем пакете NuGet, добавьте ImageFactory решение по James South. Все, что вам нужно, есть. Хотел бы я купить Джеймсу больше пива.

Пример использования:

using (ImageFactory imgf = new ImageFactory(preserveExifData: true)) { 
    imgf 
     .Load(img) 
     .Crop(rect) 
     .Format(new JpegFormat { Quality = 100 }) 
     .Save(destination) 
} 

// given that : 
// 'img' is your Image object, could be an Image.FromFile() object or the likes 
// 'rect' is the size of your crop and that you have already did the math 
// new JpegFormat { Quality = 70 } is part of the package 
// and 'destination' is the destination path of your new image in your disk 
0

Также с помощью пакета ImageFactory NuGet, я рекомендую использовать Изменение размера Обрезка функцию.

Смотрите примеры этого here

using ImageProcessor; 
using ImageProcessor.Imaging; 
using System.Drawing; 
using System.IO; 

public static byte[] ResizeAndCrop(byte[] image, int width, int height) 
    { 
     using (var ms = new MemoryStream()) 
     { 
      using (var imgf = new ImageFactory(true)) 
       imgf 
        .Load(image) 
        .Resize(new ResizeLayer(new Size(width, height), ResizeMode.Crop)) 
        .Save(ms); 
      return ms.ToArray(); 
     } 
    } 

Это займет любое изображение в формате byte[] и урожая от центра.

Это задается параметром anchorPosition в ResizeLayer, который имеет значение в AnchorPosition.Center умолчанию используется именно

new ResizeLayer(new Size(width, height), ResizeMode.Crop/*, AnchorPosition.Center*/) 
Смежные вопросы