2015-11-27 4 views
1

Как и в Photoshop, где вы можете ввести коэффициент или в моем случае определенное значение, такое как 800x600, я хочу, чтобы можно было зафиксировать Rectangle отношение/размер при перемещении мыши ..C# - Принудительный прямоугольник для фиксированного размера/отношения

на данный момент у меня есть это:

Cropping an image

Какой будет обрезать изображение, используя Rectangle созданный из перетаскивая на PictureBox. Ограничивающая рамка выбирает область без каких-либо ограничений. Я хочу, чтобы я мог заставить прямоугольник быть определенным соотношением (предпочтительно от установленного разрешения), подобно тому, как работает инструмент обрезки Photoshop.

Мой источник, если кому-то нужен более подробно:

Form1.cs

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Drawing.Drawing2D; 
using System.Drawing.Imaging; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace CropResize 
{ 
public partial class Form1 : Form 
{ 
    private static string path; 

    public Form1(string filePath) 
    { 
     InitializeComponent(); 
     path = filePath; 
    } 

    private Image _originalImage; 
    private Image _newImage; 

    private bool _selecting; 
    private Rectangle _selection; 


    private void Form1_Load(object sender, System.EventArgs e) 
    { 
     pictureBox1.Image = Image.FromFile(path); 

     if (pictureBox1.Image.Height > Screen.PrimaryScreen.Bounds.Height - 50 || pictureBox1.Image.Width > Screen.PrimaryScreen.Bounds.Width - 50) 
     { 
      if (pictureBox1.Image.Height > Screen.PrimaryScreen.Bounds.Height - 50) 
      { 
       Height = Screen.PrimaryScreen.Bounds.Height - 50; 
       panel1.Height = Size.Height - statusStrip1.Height - buttonSave.Height - 60; 
      } 
      if (pictureBox1.Image.Width > Screen.PrimaryScreen.Bounds.Width - 50) 
      { 
       Size = new Size(Screen.PrimaryScreen.Bounds.Width - 50, Screen.PrimaryScreen.Bounds.Height - 50); 
       panel1.Width = Size.Width - statusStrip1.Height - buttonSave.Height - 60; 
      } 

      pictureBox1.Image = pictureBox1.Image.Fit2PictureBox(pictureBox1); 

      panel1.Size = new Size(pictureBox1.Image.Width, pictureBox1.Image.Height); 

     } 

     Size = new Size(panel1.Size.Width + 50, panel1.Size.Height + buttonSave.Height + statusStrip1.Height + 80); 

     // Create a copy of the original image for later use 
     _originalImage = pictureBox1.Image.Clone() as Image; 
     _newImage = pictureBox1.Image.Clone() as Image; 
    } 

    private void buttonOrig_Click(object sender, System.EventArgs e) 
    { 
     pictureBox1.Image = _originalImage.Clone() as Image; 
    } 

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e) 
    { 
     // Starting point of the selection: 
     if (e.Button == MouseButtons.Left) 
     { 
      pictureBox1.Image.Dispose(); 
      pictureBox1.Image = _originalImage.Clone() as Image; 
      _selecting = true; 
      _selection = new Rectangle(new Point(e.X, e.Y), new Size()); 
     } 
    } 

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e) 
    { 
     // Update the actual size of the selection: 
     if (_selecting) 
     { 

      _selection.Width = (e.X - _selection.X); 
      _selection.Height = (e.Y - _selection.Y); 

      //int nGCD = GetGreatestCommonDivisor(1920, 1080); 
      //_selection.Width = _selection.Width/nGCD; 
      //_selection.Height = _selection.Height/nGCD; 


      int widthRatio = 16; 
      int heightRatio = 9; 

      if (_selection.Height * widthRatio <= _selection.Width) 
      { 
       _selection.Width = _selection.Height * widthRatio; 
      } 
      else if (_selection.Width * heightRatio <= _selection.Width) 
      { 
       _selection.Height = _selection.Width * heightRatio; 
      } 

      // Redraw the picturebox: 
      pictureBox1.Refresh(); 
     } 
    } 

    private void pictureBox1_Paint(object sender, PaintEventArgs e) 
    { 
     if (_selecting && _selection.Height != 0) 
     { 

      // Draw a rectangle displaying the current selection 
      e.Graphics.DrawRectangle(Pens.WhiteSmoke, _selection); 

      //e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(50, Color.Gray)), 0, pictureBox1.Height - pictureBox1.Image.Height, pictureBox1.Image.Width, pictureBox1.Image.Height); 
      e.Graphics.SetClip(_selection, CombineMode.Exclude); 
      e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100, Color.Black)), 0, 0, pictureBox1.Width, pictureBox1.Height); 

      int nGCD = GetGreatestCommonDivisor(_selection.Width, _selection.Height); 
      string str = string.Format("{0}:{1}", _selection.Width/nGCD, _selection.Height/nGCD); 

      toolStripStatusLabel1.Text = "Image Size: " + _selection.Width + "x" + _selection.Height + "px. Aspect Ratio: " + str; 
     } 
    } 

    public static int GetGreatestCommonDivisor(int height, int width) 
    { 
     return width == 0 ? height : GetGreatestCommonDivisor(width, height % width); 
    } 


    private void pictureBox1_MouseUp(object sender, MouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Left && 
      _selecting && 
      _selection.Size != new Size()) 
     { 
      // Create cropped image: 
      _newImage = pictureBox1.Image.Crop(_selection); 

      _selecting = false; 

      try 
      { 
       // Set new image to the picturebox: 
       //pictureBox1.Image = _newImage.Fit2PictureBox(pictureBox1); 

       pictureBox1.Image = _newImage; 

       //toolStripStatusLabel1.Text = "Image Cropped."; 
      } 
      catch (Exception) 
      { } 
     } 
     else 
     { 
      _selecting = false; 
     } 
    } 

    private void buttonResize_Click(object sender, EventArgs e) 
    { 
     pictureBox1.Image = ResizeImage(pictureBox1.Image, new Size(800, 600)); 

     int nGCD = GetGreatestCommonDivisor(pictureBox1.Image.Width, pictureBox1.Image.Height); 
     string str = string.Format("{0}:{1}", pictureBox1.Image.Width/nGCD, pictureBox1.Image.Height/nGCD); 

     toolStripStatusLabel1.Text = "Image Resized to " + pictureBox1.Image.Width + "x" + pictureBox1.Image.Height + "px. Aspect Ratio: " + str; 
    } 


    public static Image ResizeImage(Image image, Size size, bool preserveAspectRatio = true) 
    { 
     int newWidth; 
     int newHeight; 
     if (preserveAspectRatio) 
     { 
      int originalWidth = image.Width; 
      int originalHeight = image.Height; 
      float percentWidth = size.Width/originalWidth; 
      float percentHeight = size.Height/originalHeight; 
      float percent = percentHeight < percentWidth ? percentHeight : percentWidth; 
      newWidth = (int)(originalWidth * percent); 
      newHeight = (int)(originalHeight * percent); 
     } 
     else 
     { 
      newWidth = size.Width; 
      newHeight = size.Height; 
     } 
     Image newImage = new Bitmap(newWidth, newHeight); 
     using (Graphics graphicsHandle = Graphics.FromImage(newImage)) 
     { 
      graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic; 
      graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight); 
     } 
     return newImage; 
    } 


    private void buttonSave_Click(object sender, EventArgs e) 
    { 
     string filename = path.Substring(path.LastIndexOf("\\") + 1); 
     string newPath = path.Substring(0, path.LastIndexOf(".") - 1) + "NEW.png"; 

     toolStripStatusLabel1.Text = "Saving " + filename + " to " + newPath; 

     pictureBox1.Image.Save(newPath, ImageFormat.Png); 

     toolStripStatusLabel1.Text = filename + " saved to " + newPath; 

    } 
} 
} 

Program.cs

using System; 
using System.Collections.Generic; 
using System.Drawing; 
using System.Drawing.Drawing2D; 
using System.Drawing.Imaging; 
using System.Linq; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace CropResize 
{ 
static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main(string[] args) 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1(args[0])); 
    } 


    public static Image SetImageWithinResolution(this Image image, PictureBox pictureBox) 
    { 
     //Bitmap bitmap = null; 
     if (image.Height > Screen.PrimaryScreen.Bounds.Height) 
     { 
      //ActiveForm.Size = new Size(100, 100); 
      Form.ActiveForm.Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); 
      image = image.Fit2PictureBox(pictureBox); 
      //Bitmap bitmap = new Bitmap(image,); 

     } 
     if (image.Width > Screen.PrimaryScreen.Bounds.Width) 
     { 
      //ActiveForm.Size = new Size(100, 100); 
      Form.ActiveForm.Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); 
      image = image.Fit2PictureBox(pictureBox); 
      //Bitmap bitmap = new Bitmap(); 

     } 
     return image; 
    } 


    public static Image Crop(this Image image, Rectangle selection) 
    { 
     Bitmap bmp = image as Bitmap; 

     try 
     { 
      // Check if it is a bitmap: 
      if (bmp == null) 
       throw new ArgumentException("No valid bitmap"); 

      // Crop the image: 
      Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat); 

      // Release the resources: 
      image.Dispose(); 

      return cropBmp; 
     } 
     catch (Exception) 
     { 
      return bmp; 
     } 
    } 


    public static Image Fit2PictureBox(this Image image, PictureBox picBox) 
    { 
     Bitmap bmp = null; 
     Graphics g; 

     // Scale: 
     double scaleY = (double)image.Width/picBox.Width; 
     double scaleX = (double)image.Height/picBox.Height; 
     double scale = scaleY < scaleX ? scaleX : scaleY; 

     // Create new bitmap: 
     bmp = new Bitmap(
      (int)((double)image.Width/scale), 
      (int)((double)image.Height/scale)); 

     // Set resolution of the new image: 
     bmp.SetResolution(
      image.HorizontalResolution, 
      image.VerticalResolution); 

     // Create graphics: 
     g = Graphics.FromImage(bmp); 

     // Set interpolation mode: 
     g.InterpolationMode = InterpolationMode.HighQualityBicubic; 

     // Draw the new image: 
     g.DrawImage(
      image, 
      new Rectangle(   // Destination 
       0, 0, 
       bmp.Width, bmp.Height), 
      new Rectangle(   // Source 
       0, 0, 
       image.Width, image.Height), 
      GraphicsUnit.Pixel); 

     // Release the resources of the graphics: 
     g.Dispose(); 

     // Release the resources of the origin image: 
     image.Dispose(); 

     return bmp; 
    } 
} 
+0

«Я хочу, чтобы Rectangle мог быть фиксированным размером», вы имели в виду сказать «фиксированного отношения»? – ardila

+0

Каков (нежелательный) результат вашего кода? –

+0

См. Выше (изменить) – Timmo

ответ

1

Может быть, этот пример поможет; это показывает, как ограничить обнаженный прямоугольник с заданным соотношением:

float ratio = 0.33f; 

Rectangle setRect() 
{ 
    int x = Math.Min(mDown.X, currPt.X); 
    int y = Math.Min(mDown.Y, currPt.Y); 

    int w = Math.Max(mDown.X, currPt.X) - x; 
    int h = Math.Max(mDown.Y, currPt.Y) - y; 

    if (ratio > 1) h = (int)(1f * w/ratio); 
    else   w = (int)(1f * h * ratio); 

    return new Rectangle(x, y, w, h); 
} 

Он использует два Points, один набор в MouseDown и один обновленном в MouseMove.

Это зависит от вас, чтобы интегрировать его с вами в программу; вместо живописи всех этих пикселей во время MouseMove я бы просто нарисовать прямоугольник на резиновую поверхности управления с помощью Paint события ..

Если вы масштабирование вещи, которые вы, возможно, захотите переключиться на использование всех floats.

Смежные вопросы