Загрузка данных
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
// Для Lab5_4 (вывод графики на экран поверх окон через WinAPI)
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("user32.dll")]
public static extern void ReleaseDC(IntPtr hwnd, IntPtr dc);
// Инструменты рисования (дом заменен на FruitBasket - корзину с фруктами и овощами, + Selection для обрезки 5.2.6)
enum Tool { Pencil, Line, Rectangle, Ellipse, FruitBasket, Selection }
Tool currentTool = Tool.Pencil;
// Графические объекты и переменные холста
Bitmap Img1, Img2;
Graphics gr;
Point p1, p2;
Pen pen1;
Brush brush1;
Color currentColor = Color.Black;
bool isPressed = false;
bool fillMode = false;
// Для выделения области и обрезки (п. 5.2.6)
Rectangle selRect = new Rectangle(0, 0, 0, 0);
Pen selPen;
// Настраиваемые параметры варианта (вместо этажей и окон -> ярусы и количество плодов в ряду)
int fruitRows = 3; // Ярусов фруктов/овощей
int fruitsPerRow = 3; // Плодов в одном ряду
float scaleFactor = 1.0f;
string currentFileName = "";
// Элементы интерфейса (создаются программно)
MenuStrip menuStrip1;
ToolStrip toolStrip1;
Panel canvasPanel;
Panel rightPanel;
PictureBox pictureBox1;
StatusStrip statusStrip1;
ToolStripStatusLabel statusScaleLabel;
ToolStripButton btnPencil, btnLine, btnRect, btnEllipse, btnFill, btnFruits, btnColor, btnSave, btnClear;
TrackBar trackScale;
NumericUpDown numRows, numFruitsPerRow;
OpenFileDialog openFileDialog1;
SaveFileDialog saveFileDialog1;
ColorDialog colorDialog1;
public Form1()
{
InitializeComponent();
pen1 = new Pen(currentColor, 2f);
brush1 = new SolidBrush(currentColor);
selPen = new Pen(Brushes.Blue, 1.2f);
selPen.DashStyle = DashStyle.Dash;
BuildInterface();
InitCanvas(800, 550);
}
// ====================================================================
// 1. ПРОГРАММНАЯ СБОРКА ИНТЕРФЕЙСА (Меню "Файл" + "Правка", Панели)
// ====================================================================
private void BuildInterface()
{
openFileDialog1 = new OpenFileDialog
{
Filter = "Все файлы|*.*|Рисунки BMP|*.bmp|Рисунки JPEG|*.jpg|Рисунки PNG|*.png",
FileName = ""
};
saveFileDialog1 = new SaveFileDialog
{
Filter = "Рисунки PNG|*.png|Рисунки JPEG|*.jpg|Рисунки BMP|*.bmp",
DefaultExt = "png"
};
colorDialog1 = new ColorDialog { Color = currentColor };
// --- ВЕРХНЕЕ МЕНЮ: "Файл" и "Правка" ---
menuStrip1 = new MenuStrip();
// 1. Меню "Файл"
ToolStripMenuItem fileMenu = new ToolStripMenuItem("Файл");
fileMenu.DropDownItems.Add("Создать (Чистый холст)", null, (s, e) => ClearCanvas());
fileMenu.DropDownItems.Add("Открыть...", null, MenuOpen_Click);
fileMenu.DropDownItems.Add("Сохранить", null, MenuSave_Click);
fileMenu.DropDownItems.Add("Сохранить как...", null, MenuSaveAs_Click);
fileMenu.DropDownItems.Add("Сохранить как на компоненте (5.2.5)", null, MenuSaveAsComponent_Click);
fileMenu.DropDownItems.Add(new ToolStripSeparator());
fileMenu.DropDownItems.Add("Выход", null, (s, e) => Close());
// 2. Меню "Правка" (справа от "Файл" со всеми функциями Lab5_1 - Lab5_4)
ToolStripMenuItem editMenu = new ToolStripMenuItem("Правка");
editMenu.DropDownItems.Add("Перерисовать холст (Lab5_1)", null, (s, e) => pictureBox1.Refresh());
editMenu.DropDownItems.Add(new ToolStripSeparator());
editMenu.DropDownItems.Add("Поворот на 180° и отражение по Y (5.2.1)", null, EditRotate180_Click);
editMenu.DropDownItems.Add("Поворот на 90° по часовой (5.2.1)", null, EditRotate90_Click);
editMenu.DropDownItems.Add("Масштабировать: уменьшить в 2 раза с рамкой (5.2.2)", null, EditScaleHalf_Click);
editMenu.DropDownItems.Add(new ToolStripSeparator());
editMenu.DropDownItems.Add("Сделать выбранный цвет прозрачным (5.2.3)", null, EditMakeTransparent_Click);
editMenu.DropDownItems.Add("Фильтр: уменьшить синий цвет попиксельно (5.2.4)", null, EditFilterBlue_Click);
editMenu.DropDownItems.Add("Фильтр: оттенки серого ColorMatrix (5.2.4)", null, EditGrayscale_Click);
editMenu.DropDownItems.Add(new ToolStripSeparator());
editMenu.DropDownItems.Add("Инструмент: Выделить рамкой (5.2.6)", null, (s, e) => SelectTool(Tool.Selection));
editMenu.DropDownItems.Add("Обрезать по выделенной области (5.2.6)", null, EditCropSelection_Click);
editMenu.DropDownItems.Add(new ToolStripSeparator());
editMenu.DropDownItems.Add("Отрисовать на экране поверх окон (Lab5_4)", null, EditDrawOnDesktop_Click);
menuStrip1.Items.Add(fileMenu);
menuStrip1.Items.Add(editMenu);
// --- ПАНЕЛЬ ИНСТРУМЕНТОВ (ToolStrip) ---
toolStrip1 = new ToolStrip();
btnPencil = CreateToolBtn("Карандаш", DrawIcon("pencil"), (s, e) => SelectTool(Tool.Pencil), true);
btnLine = CreateToolBtn("Линия", DrawIcon("line"), (s, e) => SelectTool(Tool.Line));
btnRect = CreateToolBtn("Прямоугольник", DrawIcon("rect"), (s, e) => SelectTool(Tool.Rectangle));
btnEllipse = CreateToolBtn("Эллипс", DrawIcon("ellipse"), (s, e) => SelectTool(Tool.Ellipse));
btnFill = new ToolStripButton
{
ToolTipText = "Режим заливки фигур",
Image = DrawIcon("fill"),
CheckOnClick = true
};
btnFill.CheckedChanged += (s, e) => fillMode = btnFill.Checked;
// Кнопка рисования овощей и фруктов (вместо Дома)
btnFruits = CreateToolBtn("Корзина с овощами и фруктами", DrawIcon("fruits"), (s, e) => SelectTool(Tool.FruitBasket));
btnColor = new ToolStripButton { ToolTipText = "Выбрать цвет", Image = DrawIcon("color") };
btnColor.Click += BtnColor_Click;
btnSave = new ToolStripButton { ToolTipText = "Сохранить рисунок", Image = DrawIcon("save") };
btnSave.Click += MenuSaveAs_Click;
btnClear = new ToolStripButton { ToolTipText = "Очистить холст", Image = DrawIcon("clear") };
btnClear.Click += (s, e) => ClearCanvas();
toolStrip1.Items.AddRange(new ToolStripItem[] {
btnPencil, btnLine, btnRect, btnEllipse, btnFill, btnFruits,
new ToolStripSeparator(),
btnColor, btnSave, btnClear
});
// --- ПРАВАЯ ПАНЕЛЬ НАСТРОЕК (Масштаб + Ярусы фруктов + Плодов в ряду) ---
rightPanel = new Panel
{
Dock = DockStyle.Right,
Width = 190,
BackColor = Color.FromArgb(240, 240, 240),
BorderStyle = BorderStyle.FixedSingle
};
Label lblScale = new Label { Text = "Масштаб:", Location = new Point(15, 20), AutoSize = true };
trackScale = new TrackBar
{
Location = new Point(10, 40),
Width = 165,
Minimum = 50,
Maximum = 200,
Value = 100,
TickFrequency = 25
};
trackScale.Scroll += TrackScale_Scroll;
Label lblRows = new Label { Text = "Ярусов фруктов:", Location = new Point(15, 100), AutoSize = true };
numRows = new NumericUpDown
{
Location = new Point(15, 122),
Width = 120,
Minimum = 1,
Maximum = 5,
Value = 3
};
numRows.ValueChanged += (s, e) => fruitRows = (int)numRows.Value;
Label lblPerRow = new Label { Text = "Плодов в ряду:", Location = new Point(15, 160), AutoSize = true };
numFruitsPerRow = new NumericUpDown
{
Location = new Point(15, 182),
Width = 120,
Minimum = 1,
Maximum = 8,
Value = 3
};
numFruitsPerRow.ValueChanged += (s, e) => fruitsPerRow = (int)numFruitsPerRow.Value;
rightPanel.Controls.AddRange(new Control[] { lblScale, trackScale, lblRows, numRows, lblPerRow, numFruitsPerRow });
// --- НИЖНЯЯ СТРОКА СОСТОЯНИЯ ---
statusStrip1 = new StatusStrip();
statusScaleLabel = new ToolStripStatusLabel("Масштаб: 100% | Инструмент: Карандаш");
statusStrip1.Items.Add(statusScaleLabel);
// --- ЦЕНТРАЛЬНАЯ ПАНЕЛЬ С ПРОКРУТКОЙ И PICTUREBOX ---
canvasPanel = new Panel
{
Dock = DockStyle.Fill,
AutoScroll = true,
BackColor = Color.LightGray
};
pictureBox1 = new PictureBox
{
Location = new Point(0, 0),
SizeMode = PictureBoxSizeMode.AutoSize,
BackColor = Color.White
};
pictureBox1.MouseDown += PictureBox1_MouseDown;
pictureBox1.MouseMove += PictureBox1_MouseMove;
pictureBox1.MouseUp += PictureBox1_MouseUp;
pictureBox1.Paint += PictureBox1_Paint;
canvasPanel.Controls.Add(pictureBox1);
// Добавляем все элементы на форму в правильном порядке Dock
this.Controls.Add(canvasPanel);
this.Controls.Add(rightPanel);
this.Controls.Add(toolStrip1);
this.Controls.Add(menuStrip1);
this.Controls.Add(statusStrip1);
this.MainMenuStrip = menuStrip1;
}
private ToolStripButton CreateToolBtn(string tooltip, Image icon, EventHandler onClick, bool isChecked = false)
{
var btn = new ToolStripButton
{
ToolTipText = tooltip,
Image = icon,
Checked = isChecked
};
btn.Click += onClick;
return btn;
}
private void SelectTool(Tool tool)
{
currentTool = tool;
btnPencil.Checked = (tool == Tool.Pencil);
btnLine.Checked = (tool == Tool.Line);
btnRect.Checked = (tool == Tool.Rectangle);
btnEllipse.Checked = (tool == Tool.Ellipse);
btnFruits.Checked = (tool == Tool.FruitBasket);
string toolName = tool == Tool.FruitBasket ? "Овощи и фрукты" :
tool == Tool.Selection ? "Выделение рамкой" : tool.ToString();
statusScaleLabel.Text = $"Масштаб: {(int)(scaleFactor * 100)}% | Инструмент: {toolName}";
}
// Генерация аккуратных иконок для кнопок на панели инструментов
private Bitmap DrawIcon(string type)
{
Bitmap bmp = new Bitmap(20, 20);
using (Graphics g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
Pen p = new Pen(Color.Black, 1.8f);
switch (type)
{
case "pencil":
g.DrawLine(new Pen(Color.DarkOrange, 3f), 3, 16, 15, 4);
g.FillPolygon(Brushes.Black, new Point[] { new Point(2, 18), new Point(6, 16), new Point(4, 14) });
break;
case "line":
g.DrawLine(p, 3, 16, 16, 3);
break;
case "rect":
g.DrawRectangle(p, 3, 4, 13, 11);
break;
case "ellipse":
g.DrawEllipse(p, 2, 4, 15, 11);
break;
case "fill":
g.FillRectangle(Brushes.RoyalBlue, 4, 4, 12, 12);
g.DrawRectangle(p, 4, 4, 12, 12);
break;
case "fruits":
// Иконка спелого яблока с зеленым листком (вместо домика)
g.FillEllipse(Brushes.Crimson, 3, 5, 13, 12);
g.DrawEllipse(new Pen(Color.DarkRed, 1.2f), 3, 5, 13, 12);
g.DrawLine(new Pen(Color.SaddleBrown, 2f), 9, 5, 10, 1);
g.FillEllipse(Brushes.ForestGreen, 10, 2, 6, 4);
break;
case "color":
g.FillRectangle(Brushes.MediumSeaGreen, 2, 2, 5, 15);
g.FillRectangle(Brushes.Gold, 7, 2, 5, 15);
g.FillRectangle(Brushes.Tomato, 12, 2, 5, 15);
break;
case "save":
g.DrawRectangle(p, 3, 3, 13, 13);
g.FillRectangle(Brushes.DimGray, 6, 3, 7, 5);
g.DrawRectangle(p, 6, 10, 7, 6);
break;
case "clear":
Pen redPen = new Pen(Color.Crimson, 2f);
g.DrawRectangle(redPen, 3, 3, 13, 13);
g.DrawLine(redPen, 3, 3, 16, 16);
g.DrawLine(redPen, 16, 3, 3, 16);
break;
}
}
return bmp;
}
// ====================================================================
// 2. ХОЛСТ И РИСОВАНИЕ ФИГУР + КОРЗИНА С ОВОЩАМИ И ФРУКТАМИ
// ====================================================================
private void InitCanvas(int width, int height)
{
Img1 = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(Img1))
{
g.Clear(Color.White);
}
pictureBox1.Image = Img1;
selRect = new Rectangle(0, 0, 0, 0);
}
private void ClearCanvas()
{
InitCanvas(Math.Max(800, canvasPanel.ClientSize.Width), Math.Max(550, canvasPanel.ClientSize.Height));
}
private void PictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
isPressed = true;
p1 = e.Location;
if (currentTool == Tool.Selection)
{
selRect = new Rectangle(p1.X, p1.Y, 0, 0);
}
}
private void PictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (!isPressed) return;
p2 = e.Location;
if (currentTool == Tool.Selection)
{
selRect = GetNormalizedRect(p1, p2);
pictureBox1.Invalidate();
return;
}
if (currentTool == Tool.Pencil)
{
using (Graphics g = Graphics.FromImage(Img1))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawLine(pen1, p1, p2);
}
p1 = p2;
pictureBox1.Image = Img1;
pictureBox1.Invalidate();
return;
}
// Для остальных фигур и корзины с фруктами рисуем на буферном изображении Img2
Img2 = new Bitmap(Img1);
using (Graphics g = Graphics.FromImage(Img2))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
DrawSelectedShape(g, p1, p2);
}
pictureBox1.Image = Img2;
pictureBox1.Invalidate();
}
private void PictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (!isPressed) return;
isPressed = false;
p2 = e.Location;
if (currentTool == Tool.Selection)
{
selRect = GetNormalizedRect(p1, p2);
pictureBox1.Invalidate();
return;
}
if (currentTool != Tool.Pencil)
{
using (Graphics g = Graphics.FromImage(Img1))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
DrawSelectedShape(g, p1, p2);
}
pictureBox1.Image = Img1;
}
pictureBox1.Invalidate();
}
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
// Отрисовка рамки выделения для п. 5.2.6
if (selRect.Width > 0 && selRect.Height > 0)
{
e.Graphics.DrawRectangle(isPressed ? selPen : Pens.Black, selRect);
}
}
private void DrawSelectedShape(Graphics g, Point pt1, Point pt2)
{
Rectangle rect = GetNormalizedRect(pt1, pt2);
switch (currentTool)
{
case Tool.Line:
g.DrawLine(pen1, pt1, pt2);
break;
case Tool.Rectangle:
if (fillMode) g.FillRectangle(brush1, rect);
g.DrawRectangle(pen1, rect);
break;
case Tool.Ellipse:
if (fillMode) g.FillEllipse(brush1, rect);
g.DrawEllipse(pen1, rect);
break;
case Tool.FruitBasket:
// Если просто кликнули мышкой без растягивания — задаем стандартный размер корзины
if (rect.Width < 30 || rect.Height < 30)
{
int defW = (int)(130 * scaleFactor);
int defH = (int)(110 * scaleFactor);
rect = new Rectangle(pt1.X - defW / 2, pt1.Y - defH / 2, defW, defH);
}
DrawFruitAndVeggieBasket(g, rect, fruitRows, fruitsPerRow);
break;
}
}
// Отрисовка корзины с овощами и фруктами (с двумя параметрами: ярусы и число плодов в ряду)
private void DrawFruitAndVeggieBasket(Graphics g, Rectangle bounds, int rows, int countPerRow)
{
int x = bounds.X;
int y = bounds.Y;
int w = bounds.Width;
int h = bounds.Height;
// Нижняя половина области — плетеная корзина, верхняя — ярусы овощей и фруктов
int basketTop = y + (int)(h * 0.52f);
int basketBottom = y + h;
int basketHeight = Math.Max(15, basketBottom - basketTop);
// 1. Сначала рисуем ярусы плодов (яблоки, груши/апельсины, морковки с ботвой)
int fruitZoneHeight = Math.Max(20, basketTop - y);
int rowStep = Math.Max(10, fruitZoneHeight / Math.Max(1, rows));
int itemWidth = Math.Max(12, (w - 16) / Math.Max(1, countPerRow));
int itemDiameter = Math.Min(itemWidth, rowStep + 10);
for (int r = 0; r < rows; r++)
{
// Нижний ярус лежит прямо у края корзины, следующие — выше
int itemY = basketTop - (r + 1) * (rowStep * 3 / 4) - itemDiameter / 4;
for (int c = 0; c < countPerRow; c++)
{
int itemX = x + 8 + c * itemWidth + (itemWidth - itemDiameter) / 2;
Rectangle itemRect = new Rectangle(itemX, itemY, itemDiameter, itemDiameter);
int type = (r + c) % 3; // Чередуем: 0 - яблоко, 1 - морковь, 2 - апельсин/помидор
if (type == 0) // Яблоко с веточкой и листочком
{
if (fillMode) g.FillEllipse(Brushes.Crimson, itemRect);
else g.FillEllipse(Brushes.White, itemRect);
g.DrawEllipse(pen1, itemRect);
// Черенок и листик
int midX = itemX + itemDiameter / 2;
g.DrawLine(pen1, midX, itemY, midX + 2, itemY - 6);
g.FillEllipse(Brushes.ForestGreen, midX + 1, itemY - 6, 7, 4);
g.DrawEllipse(Pens.DarkGreen, midX + 1, itemY - 6, 7, 4);
}
else if (type == 1) // Морковка с зеленой ботвой
{
Point[] carrotPts = new Point[]
{
new Point(itemX + 2, itemY + 2),
new Point(itemX + itemDiameter - 2, itemY + 2),
new Point(itemX + itemDiameter / 2, itemY + itemDiameter + 4)
};
if (fillMode) g.FillPolygon(Brushes.DarkOrange, carrotPts);
else g.FillPolygon(Brushes.White, carrotPts);
g.DrawPolygon(pen1, carrotPts);
// Зеленая ботва морковки сверху
int midX = itemX + itemDiameter / 2;
Pen greenPen = new Pen(Color.ForestGreen, 1.5f);
g.DrawLine(greenPen, midX, itemY + 2, midX - 5, itemY - 6);
g.DrawLine(greenPen, midX, itemY + 2, midX, itemY - 7);
g.DrawLine(greenPen, midX, itemY + 2, midX + 5, itemY - 6);
}
else // Спелый апельсин / томат с чашелистиком
{
if (fillMode) g.FillEllipse(Brushes.Gold, itemRect);
else g.FillEllipse(Brushes.White, itemRect);
g.DrawEllipse(pen1, itemRect);
int midX = itemX + itemDiameter / 2;
g.DrawLine(pen1, midX - 3, itemY + 2, midX + 3, itemY + 2);
g.DrawLine(pen1, midX, itemY - 2, midX, itemY + 4);
}
}
}
// 2. Рисуем саму корзину (трапеция с ободком и плетеной сеточкой) поверх нижнего края плодов
Point[] basketPoly = new Point[]
{
new Point(x, basketTop),
new Point(x + w, basketTop),
new Point(x + (int)(w * 0.82f), basketBottom),
new Point(x + (int)(w * 0.18f), basketBottom)
};
if (fillMode)
g.FillPolygon(Brushes.BurlyWood, basketPoly);
else
g.FillPolygon(Brushes.White, basketPoly);
g.DrawPolygon(pen1, basketPoly);
// Ободок корзины
Rectangle rimRect = new Rectangle(x - 3, basketTop - 4, w + 6, 8);
if (fillMode) g.FillRectangle(Brushes.Peru, rimRect);
else g.FillRectangle(Brushes.White, rimRect);
g.DrawRectangle(pen1, rimRect);
// Горизонтальные полосы плетения корзины
for (int i = 1; i <= 2; i++)
{
int lineY = basketTop + (basketHeight * i) / 3;
float ratio = (float)i / 3f;
int leftX = x + (int)(w * 0.18f * ratio);
int rightX = x + w - (int)(w * 0.18f * ratio);
g.DrawLine(pen1, leftX, lineY, rightX, lineY);
}
// Вертикальные ребра корзины
for (int i = 1; i <= 3; i++)
{
int topX = x + (w * i) / 4;
int botX = x + (int)(w * 0.18f) + ((int)(w * 0.64f) * i) / 4;
g.DrawLine(pen1, topX, basketTop + 4, botX, basketBottom);
}
}
private Rectangle GetNormalizedRect(Point pt1, Point pt2)
{
return new Rectangle(
Math.Min(pt1.X, pt2.X),
Math.Min(pt1.Y, pt2.Y),
Math.Abs(pt2.X - pt1.X),
Math.Abs(pt2.Y - pt1.Y));
}
// ====================================================================
// 3. ОБРАБОТЧИКИ МЕНЮ "ФАЙЛ"
// ====================================================================
private void MenuOpen_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(openFileDialog1.FileName))
{
try
{
using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.Inheritable))
{
Image loaded = Image.FromStream(fs);
Img1 = new Bitmap(loaded);
pictureBox1.Image = Img1;
currentFileName = openFileDialog1.FileName;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\nНе удалось открыть файл", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
private void MenuSave_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
if (string.IsNullOrEmpty(currentFileName))
{
MenuSaveAs_Click(sender, e);
return;
}
try
{
Bitmap bmp = new Bitmap(pictureBox1.Image);
bmp.Save(currentFileName);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\nНе удалось сохранить файл", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
private void MenuSaveAs_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
currentFileName = saveFileDialog1.FileName;
MenuSave_Click(sender, e);
}
}
// 5.2.5. Сохранить рисунок так, как он выглядит при растягивании на компоненте
private void MenuSaveAsComponent_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Dock = DockStyle.Fill;
Bitmap bitmap1 = new Bitmap(pictureBox1.Image);
Bitmap bitmap2 = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(bitmap2))
{
g.InterpolationMode = InterpolationMode.Bicubic;
g.DrawImage(bitmap1, new Rectangle(0, 0, bitmap2.Width, bitmap2.Height));
}
pictureBox1.Image = bitmap2;
MenuSaveAs_Click(this, e);
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
pictureBox1.Dock = DockStyle.None;
pictureBox1.Image = bitmap1;
}
// ====================================================================
// 4. ОБРАБОТЧИКИ МЕНЮ "ПРАВКА" (Все функции Lab5_2 и Lab5_4)
// ====================================================================
// 5.2.1. Поворот на 180 градусов и отражение
private void EditRotate180_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
Img1 = new Bitmap(pictureBox1.Image);
Img1.RotateFlip(RotateFlipType.Rotate180FlipY);
pictureBox1.Image = Img1;
}
private void EditRotate90_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
Img1 = new Bitmap(pictureBox1.Image);
Img1.RotateFlip(RotateFlipType.Rotate90FlipNone);
pictureBox1.Image = Img1;
}
// 5.2.2. Программное уменьшение в 2 раза с красной рамкой
private void EditScaleHalf_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
Bitmap bitmap1 = new Bitmap(pictureBox1.Image);
if (bitmap1.Width < 4 || bitmap1.Height < 4) return;
using (Graphics Gr1 = Graphics.FromImage(bitmap1))
{
Bitmap bitmap2 = new Bitmap(bitmap1.Width / 2, bitmap1.Height / 2, Gr1);
using (Graphics Gr2 = Graphics.FromImage(bitmap2))
{
Rectangle compressionRect = new Rectangle(0, 0, bitmap1.Width / 2, bitmap1.Height / 2);
Gr2.DrawImage(bitmap1, compressionRect);
Gr2.DrawRectangle(Pens.Red, 0, 0, bitmap2.Width - 1, bitmap2.Height - 1);
}
Img1 = bitmap2;
pictureBox1.Image = Img1;
}
}
// 5.2.3. Сделать выбранный в диалоге цвет прозрачным
private void EditMakeTransparent_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
Bitmap bitmap1 = new Bitmap(pictureBox1.Image);
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
bitmap1.MakeTransparent(colorDialog1.Color);
Img1 = bitmap1;
pictureBox1.Image = Img1;
}
}
// 5.2.4 (Часть 1). Попиксельная фильтрация синего цвета
private void EditFilterBlue_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
Bitmap bitmap1 = new Bitmap(pictureBox1.Image);
for (int x = 0; x < bitmap1.Width; x++)
{
for (int y = 0; y < bitmap1.Height; y++)
{
Color c = bitmap1.GetPixel(x, y);
if (c.R > 250 && c.G > 250 && c.B > 250) continue;
bitmap1.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B / 2));
}
}
Img1 = bitmap1;
pictureBox1.Image = Img1;
}
// 5.2.4 (Часть 2). Оттенки серого через ColorMatrix
private void EditGrayscale_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
Bitmap bitmap1 = new Bitmap(pictureBox1.Image);
Bitmap bitmap2 = new Bitmap(bitmap1.Width, bitmap1.Height);
using (Graphics g = Graphics.FromImage(bitmap2))
{
float[][] Map = {
new float[] {0.30f, 0.30f, 0.30f, 0.00f, 0.00f },
new float[] {0.59f, 0.59f, 0.59f, 0.00f, 0.00f },
new float[] {0.11f, 0.11f, 0.11f, 0.00f, 0.00f },
new float[] {0.00f, 0.00f, 0.00f, 1.00f, 0.00f },
new float[] {0.00f, 0.00f, 0.00f, 0.00f, 1.00f }
};
ColorMatrix grayMatrix = new ColorMatrix(Map);
ImageAttributes attributes = new ImageAttributes();
attributes.SetColorMatrix(grayMatrix);
Rectangle rect = new Rectangle(0, 0, bitmap1.Width, bitmap1.Height);
g.DrawImage(bitmap1, rect, 0, 0, bitmap1.Width, bitmap1.Height, GraphicsUnit.Pixel, attributes);
}
Img1 = bitmap2;
pictureBox1.Image = Img1;
}
// 5.2.6. Обрезка изображения по выделенной рамке selRect
private void EditCropSelection_Click(object sender, EventArgs e)
{
if (pictureBox1.Image == null) return;
if (selRect.Width <= 0 || selRect.Height <= 0)
{
MessageBox.Show("Сначала выделите область на холсте (Правка -> Инструмент: Выделить рамкой)!",
"Подсказка", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
Bitmap bitmap1 = new Bitmap(pictureBox1.Image);
Bitmap bitmap2 = new Bitmap(selRect.Width, selRect.Height);
using (Graphics g = Graphics.FromImage(bitmap2))
{
g.DrawImage(bitmap1, 0, 0, selRect, GraphicsUnit.Pixel);
}
Img1 = bitmap2;
pictureBox1.Image = Img1;
selRect = new Rectangle(0, 0, 0, 0);
pictureBox1.Invalidate();
}
// Lab5_4. Отрисовка в контексте экрана Windows поверх всех окон
private void EditDrawOnDesktop_Click(object sender, EventArgs e)
{
IntPtr desktopPtr = GetDC(IntPtr.Zero);
using (Graphics g = Graphics.FromHdc(desktopPtr))
{
Pen[] pens = { Pens.Red, Pens.Yellow, Pens.Green };
Brush[] brushes = { Brushes.Red, Brushes.Yellow, Brushes.Green };
int width = (this.ClientSize.Width - 1) / 2;
int height = (this.ClientSize.Height - 1) / 2;
for (int i = 0; i < 3; i++)
{
g.DrawRectangle(pens[i], i * width / 2, i * height / 2, width / 2, height / 2);
g.FillEllipse(brushes[i], i * width / 2, i * height / 2, width / 2, height / 2);
}
g.DrawLine(pens[2], 0, 0, width, height);
}
ReleaseDC(IntPtr.Zero, desktopPtr);
}
// ====================================================================
// 5. ДОПОЛНИТЕЛЬНЫЕ НАСТРОЙКИ (Выбор цвета и ползунок Масштаба)
// ====================================================================
private void BtnColor_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
currentColor = colorDialog1.Color;
pen1.Color = currentColor;
brush1 = new SolidBrush(currentColor);
}
}
private void TrackScale_Scroll(object sender, EventArgs e)
{
scaleFactor = trackScale.Value / 100f;
statusScaleLabel.Text = $"Масштаб: {trackScale.Value}% | Инструмент: {currentTool}";
}
}
}