2015-09-06 1 views
1

Я хотел получить изображение, чтобы заполнить окно с картинкой, но не оставляя пробелов. Таким образом, отсечение части изображения будет соответствовать, когда оно не будет изменено до пропорции pictureBox. И настроить, когда пользователь изменяет размер окна/pictureBox. Существующие опции Sizemode = Zoom оставляют пробелы, так как он боится обрезать любое изображение и Sizemode = StretchImage растягивает изображение, искажая его.Изменить размер изображения, чтобы заполнить иллюстрацию без растягивания

Единственный способ, которым я могу это сделать, - создать алгоритм для изменения размера изображения, сохранения коэффициента контрастности и установки ширины или длины изображения на ширину или длину изображения, а также создание некоторого цикла выполнения, который запускает алгоритм после кадра. Кажется, что это тяжелая работа для того, что она делает и какая-то хакерская. Есть ли лучший вариант?

Edit: Для тех, кто прибывает на, я реализовал решение Ивана Stoev слегка иначе:

class ImageHandling 
{ 
    public static Rectangle GetScaledRectangle(Image img, Rectangle thumbRect) 
    { 
     Size sourceSize = img.Size; 
     Size targetSize = thumbRect.Size; 
     float scale = Math.Max((float) targetSize.Width/sourceSize.Width, (float) targetSize.Height/sourceSize.Height); 
     var rect = new RectangleF(); 
     rect.Width = scale * sourceSize.Width; 
     rect.Height = scale * sourceSize.Height; 
     rect.X = (targetSize.Width - rect.Width)/2; 
     rect.Y = (targetSize.Height - rect.Height)/2; 
     return Rectangle.Round(rect); 
    } 

    public static Image GetResizedImage(Image img, Rectangle rect) 
    { 
     Bitmap b = new Bitmap(rect.Width, rect.Height); 
     Graphics g = Graphics.FromImage((Image) b); 
     g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
     g.DrawImage(img, 0, 0, rect.Width, rect.Height); 
     g.Dispose(); 
     try 
     { 
      return (Image)b.Clone(); 
     } 
     finally 
     { 
      b.Dispose(); 
      b = null; 
      g = null; 
     } 
    } 

    public Form1() 
    { 
     InitializeComponent(); 
     updateMainBackground(); 
    } 

    void updateMainBackground() 
    { 
     Image img = Properties.Resources.BackgroundMain; 
     Rectangle newRect = ImageHandling.GetScaledRectangle(img, mainBackground.ClientRectangle); 
     mainBackground.Image = ImageHandling.GetResizedImage(img, newRect); 
    } 

    private void Form1_Resize(object sender, EventArgs e) 
    { 
     updateMainBackground(); 
    } 
} 

ответ

2

Если я правильно понял, вы ищете режим «Заполнить» (аналогично фоновому изображению Windows). Нет стандартного способа сделать это, но не так сложно сделать свой собственный с помощью небольшого расчета и GDI +:

using System; 
using System.Drawing; 
using System.IO; 
using System.Net; 
using System.Windows.Forms; 

namespace Samples 
{ 
    public class ImageFillBox : Control 
    { 
     public ImageFillBox() 
     { 
      SetStyle(ControlStyles.Selectable | ControlStyles.SupportsTransparentBackColor, false); 
      SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Opaque | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true); 
     } 
     private Image image; 
     public Image Image 
     { 
      get { return image; } 
      set 
      { 
       if (image == value) return; 
       image = value; 
       Invalidate(); 
      } 
     } 
     protected override void OnPaint(PaintEventArgs e) 
     { 
      base.OnPaint(e); 
      if (image == null) 
       e.Graphics.Clear(BackColor); 
      else 
      { 
       Size sourceSize = image.Size, targetSize = ClientSize; 
       float scale = Math.Max((float)targetSize.Width/sourceSize.Width, (float)targetSize.Height/sourceSize.Height); 
       var rect = new RectangleF(); 
       rect.Width = scale * sourceSize.Width; 
       rect.Height = scale * sourceSize.Height; 
       rect.X = (targetSize.Width - rect.Width)/2; 
       rect.Y = (targetSize.Height - rect.Height)/2; 
       e.Graphics.DrawImage(image, rect); 
      } 
     } 
    } 
    static class Test 
    { 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      var testForm = new Form(); 
      testForm.Controls.Add(new ImageFillBox 
      { 
       Dock = DockStyle.Fill, 
       Image = GetImage(@"http://www.celebrityrockstarguitars.com/rock/images/Metall_1.jpg") 
      }); 
      Application.Run(testForm); 
     } 
     static Image GetImage(string path) 
     { 
      var uri = new Uri(path); 
      if (uri.IsFile) return Image.FromFile(path); 
      using (var client = new WebClient()) 
       return Image.FromStream(new MemoryStream(client.DownloadData(uri))); 
     } 
    } 
} 
+0

Работает отлично, спасибо большое. – daboss42

+0

У вас есть java-подход? благодаря –

0

Согласно документации PictureBoxSizeMode можно указать PictureBoxSizeMode.Zoom, чтобы получить изображение, чтобы сохранить соотношение сторон. Он будет масштабироваться как можно больше, если никакая часть изображения не будет переполнена в окне изображения.

И вы можете играть со свойством Dock (настройка DockStyle.Full), чтобы получить размер окна изображения до размера его контейнера.