Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/29: Рейтинг темы: голосов - 29, средняя оценка - 4.62
629 / 41 / 25
Регистрация: 25.04.2017
Сообщений: 510
1

Простой Paint - Разбор полетов

16.12.2018, 17:17. Показов 5901. Ответов 53
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, задумал я написать простой растровый графический редактор на подобии Paint.
Совершенствовать модель буду со временем, а пока начал с простых вещей.
Есть несколько вопросов:
  1. Как и где лучше хранить то, что рисуется
  2. Как масштабировать холст вместе с тем, что рисуется
В качестве холста использую picturebox
C#
1
2
3
4
5
 btm = new Bitmap(Canvas.Width, Canvas.Height);
            Canvas.Image = btm;
            //Создаем область для работы с графикой на элементе Canvas.Image
            g = Graphics.FromImage(Canvas.Image);            
            g.FillRectangle(Brushes.White, 0, 0, btm.Width, btm.Height);
Возникли проблемы с сохранением
C#
1
2
3
4
5
6
7
        private void btSave_Click(object sender, EventArgs e)
        {
            var sfd = new SaveFileDialog() { Filter = "Image|*.png;*.bmp;*.jpg", DefaultExt = ".png" };
            if (sfd.ShowDialog() == DialogResult.OK)
                using (var bmp = Canvas.Image)
                    bmp.Save(sfd.FileName);//Сораняем рисунок
        }
После сохранения и повторного рисования возникает ошибка "Неверный параметр", как исправить?

Полный текст программы
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace PaintBoard
{
    public partial class MainForm : Form
    {
        Color color = Color.Black; //Создаем переменную типа Color присваиваем ей черный цвет.
        bool isPressed = false; //логическая переменная понадобиться для опеределения когда можно рисовать на Canvas
        Point CurrentPoint; //Текущая точка ресунка.
        Point PrevPoint; //Это начальная точка рисунка.
        Graphics g; //Создаем графический элемент.
        ColorDialog colorDialog = new ColorDialog(); //диалоговое окно для выбора цвета.
        private Bitmap btm;
 
        public MainForm()
        {
            InitializeComponent();
            //Canvas.BackColor = Color.White;
            Panel1.BackColor = Color.Gray;
            lbColor.BackColor = Color.Black; //По умолчанию для пера задан черный цвет, поэтому мы зададим такой же фон для label2
            btm = new Bitmap(Canvas.Width, Canvas.Height);
            Canvas.Image = btm;
            //Создаем область для работы с графикой на элементе Canvas.Image
            g = Graphics.FromImage(Canvas.Image);            
            g.FillRectangle(Brushes.White, 0, 0, btm.Width, btm.Height);
            g.SmoothingMode = SmoothingMode.AntiAlias;
 
 
 
        }
 
        private void lbColor_Click(object sender, EventArgs e)
        {
            if (colorDialog.ShowDialog() == DialogResult.OK) //Если окно закрылось с OK, то меняем цвет для пера и фона lbColor
            {
                color = colorDialog.Color; //меняем цвет для пера
                lbColor.BackColor = colorDialog.Color; //меняем цвет для Фона lbColor
            }
        }
 
        private void Canvas_MouseUp(object sender, MouseEventArgs e)
        {
            isPressed = false;//Запрещаем рисовать
        }
 
        private void Canvas_MouseDown(object sender, MouseEventArgs e)
        {
            isPressed = true;// Разрешаем рисовать
            CurrentPoint = e.Location;// Начальная точка равна текущему положению на Canvas
 
        }
 
        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            Canvas.Cursor = Cursors.Cross;
            ssPosXY.Text = e.Location.ToString();
            if (isPressed)
            {
 
                PrevPoint = CurrentPoint;// Наносим первую точку на Canvas
                CurrentPoint = e.Location;// Наносим вторую точку на Canvas
                my_Pen();// Соединяем 2 точки линией
                Canvas.Invalidate();
            }
        }
 
        private void btClear_Click(object sender, EventArgs e)
        {
            g.Clear(Color.White);
            Canvas.Invalidate();
            //Очищает элемент Canvas
        }
        private void my_Pen()
        {
            Pen pen = new Pen(color, (float)numericUpDown1.Value); //Создаем перо, задаем ему цвет и толщину.
            pen.StartCap = pen.EndCap = LineCap.Round;
            g.DrawLine(pen, CurrentPoint, PrevPoint); //Соединияем точки линиями
        }
 
        private void Canvas_MouseLeave(object sender, EventArgs e)
        {
            ssPosXY.Text = "";
        }
 
 
        private void btSave_Click(object sender, EventArgs e)
        {
            var sfd = new SaveFileDialog() { Filter = "Image|*.png;*.bmp;*.jpg", DefaultExt = ".png" };
            if (sfd.ShowDialog() == DialogResult.OK)
                using (var bmp = Canvas.Image)
                    bmp.Save(sfd.FileName);//Сораняем рисунок
        }
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.12.2018, 17:17
Ответы с готовыми решениями:

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

Разбор "полетов" по потоку Thread
наткнулся на статейку на сайте https://habr.com/company/nixsolutions/blog/260745/ и у меня...

IComparer. Разбор полетов
Нигде не нашел толкового описания, как именно работает это дело, как расставляет приоритеты и т.п....

Простой векторный графический редактор (разбор полётов)
Всем привет! Меня зовут ashsvis и я программист... Я пытался бороться с этим "недугом", но эта...

53
629 / 41 / 25
Регистрация: 25.04.2017
Сообщений: 510
18.12.2018, 21:47  [ТС] 21
Author24 — интернет-сервис помощи студентам
Storm23, Техническое задание

Требуется создать простой растровый графический редактор, который позволяет:
  1. Рисовать кистью, карандашом
  2. Строить простые фигуры, такие как линия, прямоугольник, эллипс и т.д.
  3. Стирать произвольную область(Ластик)
  4. Отменять, возвращать последнее действие(undo/redo)
  5. Форматировать холст(растягивать, масштабировать)
В редакторе нужно предусмотреть возможность чтения, сохранение файла.

Сразу скажу, что хочу разработать, потому что нравится и в целях обучения

Добавлено через 8 минут
Конечно, круто было бы еще добавить сюда заливку цветом, вывод координат в StatusStrip, и вообще двигать и форматировать фигуры, вставлять текст в изображение
0
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
19.12.2018, 09:21 22
Цитата Сообщение от worldandlife Посмотреть сообщение
двигать и форматировать фигуры
Двигать и форматировать фигуры - это уже ближе к векторному редактору. В растровом можно двигать разве что фрагменты изображения.
Цитата Сообщение от worldandlife Посмотреть сообщение
Требуется создать простой растровый графический редактор, который позволяет:
Ну ок. И какие идеи насчет модели?
0
629 / 41 / 25
Регистрация: 25.04.2017
Сообщений: 510
19.12.2018, 12:20  [ТС] 23
Цитата Сообщение от Storm23 Посмотреть сообщение
двигать разве что фрагменты изображения
Скорее это и имел в виду, ибо видел в paint'e

Добавлено через 43 минуты
Цитата Сообщение от Storm23 Посмотреть сообщение
И какие идеи насчет модели?
Модель данных
  1. Model - модель данных, предоставляет данные и реагирует на команды контроллера(Tool), изменяя своё состояние
  2. Tool - текущий инструмент, который предназначен для изменения модели
  3. Canva - контейнер для графического представления данных модели
0
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
19.12.2018, 15:10 24
Цитата Сообщение от worldandlife Посмотреть сообщение
Модель данных
Модель - это конкретный набор классов. Их нужно разработать. Для начала хотя бы в общем виде.
0
629 / 41 / 25
Регистрация: 25.04.2017
Сообщений: 510
19.12.2018, 16:20  [ТС] 25
Цитата Сообщение от Storm23 Посмотреть сообщение
Для начала хотя бы в общем виде.
Если честно, то тут я в ступоре.
По идее основные сущности редактора это его фигуры и инструменты, хотя по сути если взять ластик(инструмент) и линию(простая фигура), то это одно и тоже, ведь ластик это просто рисование цветом канвы(белым).

Хорошо, пусть тогда будет абстрактный класс Object , от которого будут наследоваться все классы редактора типа Line, Curve и т. д.
Еще нужен класс, который будет задавать стиль фигурам, то есть прозрачность, толщину кисти.
Тогда делаем класс PaintStyle и наследуем классы Pen и Brush.
0
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
19.12.2018, 17:31 26
Цитата Сообщение от worldandlife Посмотреть сообщение
Хорошо, пусть тогда будет абстрактный класс Object , от которого будут наследоваться все классы редактора типа Line, Curve и т. д.
Нет, не нужно никаких Line, Curve и т.д.

Во-первых прочитайте эту тему Простой векторный графический редактор (разбор полётов) (я думаю вы ее и так читали, но все же вам следует внимательно ее изучить). Вам нужно делать тоже самое что и там, с той разницей, что модель у вас будет немного другая конечно.

Далее, предлагаю такую модель:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    /// <summary>
    /// Document
    /// </summary>
    public class Document
    {
        /// <summary>
        /// Current tool
        /// </summary>
        public Tool Tool { get; protected set; }
 
        /// <summary>
        /// Current layer
        /// </summary>
        public Bitmap Layer { get; set; }
 
        /// <summary>
        /// Render layer
        /// </summary>
        public void Render(Graphics gr)
        {
            if (Tool != null)
                Tool.Render(gr, this);
            else
                gr.DrawImage(Layer, Point.Empty);
        }
    }
 
    /// <summary>
    /// Tool to change layer
    /// </summary>
    public abstract class Tool
    {
        /// <summary>
        /// Apply tool to layer
        /// </summary>
        internal virtual void Apply(Document doc)
        {
        }
 
        /// <summary>
        /// Render preview
        /// </summary>
        internal virtual void Render(Graphics gr, Document doc)
        {
        }
    }
Есть документ - это объект верхнего уровня, и есть абстрактный класс Tool, который может изменять document.
Document хранит слой в виде битмапа.
Tool содержит два метода. Render - выводит текущее изображение, поверх которого рисуется эффект создаваемый tool (например линия). А метод Apply - должен отрисовать результат применения Tool на битмапе Document. Перед отрисовкой нужно создать точку восстановления в UndoRedoManager.

Такая модель думаю подойдет как для простейших инструментов (типа рисования), так и для более сложных (изменение яркости/контраста, выделение области, копирование/сдвиг области и т.д.)

Для пробы создайте один инструмент PenTool который будет рисовать линию (проводимую от руки).
PenTool будет хранить линию в виде GraphicsPath, а в методе Apply - отрисовывать этот GraphicsPath на битмапе.

Создайте эти классы в отдельном проекте, создайте также проект для тестов, также добавьте UndoRedoManager.

Цитата Сообщение от worldandlife Посмотреть сообщение
ведь ластик это просто рисование цветом канвы(белым).
Вообще-то ластик должен очищать канву, то есть выставлять alpha = 0.
2
629 / 41 / 25
Регистрация: 25.04.2017
Сообщений: 510
19.12.2018, 18:00  [ТС] 27
Цитата Сообщение от Storm23 Посмотреть сообщение
ведь ластик это просто рисование цветом канвы(белым).
Честно, я сам был в этом не уверен, если правильно понимаю, то белый будет занимать место в памяти, а если alpha в 0 то нет
0
629 / 41 / 25
Регистрация: 25.04.2017
Сообщений: 510
20.12.2018, 22:58  [ТС] 28
Storm23, создал репозиторий
Пока только создал классы модели и создал проект тестов, а undo/redo manager где взять? Это то что у вас в блоге?
0
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
21.12.2018, 01:18 29
Цитата Сообщение от worldandlife Посмотреть сообщение
а undo/redo manager где взять
Здесь
https://github.com/ashsvis/Vec... Manager.cs
https://github.com/ashsvis/Vec... Command.cs
0
2063 / 1542 / 168
Регистрация: 14.12.2014
Сообщений: 13,402
21.12.2018, 01:26 30
Цитата Сообщение от Storm23 Посмотреть сообщение
Постановка задачи - это краткое описание того, ЧТО должна делать программа.
Постановка задачи - это полное математическое и т.д. описание методов решения задачи. т.е. результат всестороннего и полного анализа задачи, на основании ТЗ.
А то о чем вы говорите называется формулировка задачи
0
629 / 41 / 25
Регистрация: 25.04.2017
Сообщений: 510
24.12.2018, 00:45  [ТС] 31
Цитата Сообщение от Storm23 Посмотреть сообщение
Здесь
Добавил

Добавлено через 2 часа 10 минут
Решил вынести модель в отдельный проект библиотеки классов

Добавлено через 3 часа 40 минут
Цитата Сообщение от Storm23 Посмотреть сообщение
Для пробы создайте один инструмент PenTool который будет рисовать линию (проводимую от руки).
PenTool будет хранить линию в виде GraphicsPath, а в методе Apply - отрисовывать этот GraphicsPath на битмапе.
А как это сделать? Это нужно писать в тесте?
0
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.12.2018, 12:23 32
worldandlife,
Я вам написал минимальную обвязку кода и инструмент PenTool.
Вникните в смысл классов, как они работают и как взаимодействуют. Затем пишите другие инструменты по аналогии.

В класс Document добавил такие методы: CancelTool(отменяет текущий инструмент), ApplyTool(применяет текущий инструмент к документу), SetTool(устанавливает новый инструмент для документа).
Смысл в следующем: пока инструмент активен (например PenTool) он просто рисует свои данные поверх изображения. Когда же мы применяем инструмент - он отрисовывает свои данные уже непосредственно в изображение.
Полный код Document выглядит так:
Document
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    /// <summary>
    /// Document
    /// </summary>
    public class Document
    {
        /// <summary>
        /// Current tool
        /// </summary>
        public Tool Tool { get; protected set; }
 
        /// <summary>
        /// Current layer
        /// </summary>
        public Bitmap Layer { get; set; }
 
        /// <summary>
        /// Render layer
        /// </summary>
        public void Render(Graphics gr)
        {
            if (Tool != null)
                Tool.Render(gr, this);
            else
                gr.DrawImage(Layer, Point.Empty);
        }
 
        /// <summary>
        /// Cancel current tool (w/o applying)
        /// </summary>
        public void CancelTool()
        {
            Tool = null;
        }
 
        /// <summary>
        /// Apply and clear current tool (if persented)
        /// </summary>
        public void ApplyTool()
        {
            if (Tool != null)
                Tool.Apply(this);
            Tool = null;
        }
 
        /// <summary>
        /// Set new tool and Apply current tool (if presented)
        /// </summary>
        public void SetTool(Tool tool)
        {
            if (Tool != null)
                ApplyTool();
            Tool = tool;
        }
 
        /// <summary>
        /// Create restore point for Undo/Redo manager
        /// </summary>
        internal void CreateUndoPoint(string toolName)
        {
            //make clone of current Layer
            var ms = new MemoryStream();
            Layer.Save(ms, ImageFormat.Png);
 
            //create undo action
            Action undo = () =>
            {
                ms.Position = 0;
                if (Layer != null)
                    Layer.Dispose();
                Layer = new Bitmap(ms);
            };
 
            //create undo command (redo is not supported)
            var command = new ActionCommand(undo, null) {Name = toolName};
 
            //push command to undo/redo manager
            UndoRedoManager.Instance.Add(command);
        }
    }

В Document также добавлен метод CreateUndoPoint который создает точку восстановления в UndoRedoManager.

Далее я реализовал инструмент PenTool. Его код:
PenTool
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    /// <summary>
    /// Tool to drawing by Pen (100 hardness, straight lines)
    /// </summary>
    public class PenTool : Tool, IMouseHandler
    {
        /// <summary>
        /// Style of drawing
        /// </summary>
        public PenStyle PenStyle { get; set; } = new PenStyle();
 
        //key points of polyline
        private List<PointF> points = new List<PointF>();
 
        internal override void Render(Graphics gr, Document doc)
        {
            //render Layer
            base.Render(gr, doc);
 
            //render line
            RenderLine(gr);
        }
 
        private void RenderLine(Graphics gr)
        {
            //draw line over Leyer
            if (points.Count > 1)
            using (var pen = new Pen(PenStyle.Color, PenStyle.Width))
                gr.DrawLines(pen, points.ToArray());
        }
 
        internal override void Apply(Document doc)
        {
            //create undo point
            doc.CreateUndoPoint("Pen tool");
 
            //draw line on Layer 
            using (var gr = Graphics.FromImage(doc.Layer))
                RenderLine(gr);
 
            //clear points
            points.Clear();
        }
 
        #region IMouseHandler
 
        public void OnMouseDown(Document doc, Point point)
        {
            //flush previous lines
            if (points.Count > 1)
                Apply(doc);
 
            //clear points
            points.Clear();
 
            //add first point
            points.Add(point);
        }
 
        public void OnMouseMove(Document doc, Point point)
        {
            //add next point
            points.Add(point);
        }
 
        public void OnMouseUp(Document doc, Point point)
        {
        }
 
        #endregion
    }


Он реализует интерфейс IMouseHandler, который позволит ему обрабатывать движения мыши.
PenTool собирает точки движения мыши и сохраняет их в списке. При рендеринге он просто рисует эти точки, соединяя их линиями. Таким образом получаем инструмент рисования карандашом.

Я создал также два теста. Один - проверяет работу PenTool, другой - проверяет Undo:
Test
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        [TestMethod]
        public void TestPenTool()
        {
            //create tool
            var tool = new PenTool();
            //set tool to doc
            doc.SetTool(tool);
            //draw some lines
            tool.OnMouseDown(doc, new Point(10, 10));
            tool.OnMouseMove(doc, new Point(10, 100));
            tool.OnMouseMove(doc, new Point(100, 100));
            tool.OnMouseUp(doc, new Point(100, 100));
            //apply tool
            doc.ApplyTool();
            //save image
            SaveLayer();
        }
 
        [TestMethod]
        public void TestUndo()
        {
            if (UndoRedoManager.Instance.CanUndo)
                UndoRedoManager.Instance.Undo();
            SaveLayer("afterUndo");
        }


Сделал pull request на git.
Также в приложении полный исходный код на данном этапе.
Вложения
Тип файла: zip PaintApp.zip (3.95 Мб, 42 просмотров)
2
918 / 499 / 201
Регистрация: 08.10.2018
Сообщений: 1,543
Записей в блоге: 11
01.07.2019, 18:07 33
Идея написать свой "paint"-велосипед была прекрасной, жаль что у worldandlife нет времени продолжить тему.
Однако, попытаюсь "прикрутить" к проекту своё "колесо".
Я сделал fork с git проекта и буду продолжать здесь: https://github.com/ashsvis/my-first-Paint
Ну а если будет что-то путное выходить, то сделаю pull request.

А пока что сделано:
1. Инструмент Ластик. Крашу цветом фона. Пробовал использовать цвет Color.Transparent, что-то не выходит...
2. Добавил механизм Undo|Redo (честно позаимствовал из векторного графического редактора).
3. Сделал базовую форму для интерфейса. Так сразу видно результат.
Простой Paint - Разбор полетов

Дорогу осилит идущий!
0
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
01.07.2019, 21:21 34
Цитата Сообщение от ashsvis Посмотреть сообщение
Инструмент Ластик. Крашу цветом фона.
Красить цветом фона - это не ластик. Это просто кисть с цветом фона.
Нужно сразу определиться с тем, как будут рисоваться полупрозрачные линии и как будет работать ластик. Это не так просто как кажется. И тогда кстати вы увидите, что ваша текущая реализация PenTool - не подходит.
0
918 / 499 / 201
Регистрация: 08.10.2018
Сообщений: 1,543
Записей в блоге: 11
02.07.2019, 08:25 35
Цитата Сообщение от Storm23 Посмотреть сообщение
как будут рисоваться полупрозрачные линии
Скорее всего так, если я правильно понял назначение свойства PenStyle.Hardness:
C#
1
2
3
4
5
6
7
8
//class PenTool : Tool, IMouseHandler
private void RenderLine(Graphics gr)
{
    //draw line over Leyer
    if (points.Count > 1)
        using (var pen = new Pen(Color.FromArgb((int)(PenStyle.Hardness * 255), PenStyle.Color), PenStyle.Width))
            gr.DrawLines(pen, points.ToArray());
}
А для ластика нужно будет использовать либо SetPixel(), либо MakeTransparent() для участка канвы под ластиком... Но так ли это?
0
918 / 499 / 201
Регистрация: 08.10.2018
Сообщений: 1,543
Записей в блоге: 11
02.07.2019, 18:48 36
Пока думаю, как ластик реализовать, попутно добавил:
1. Выбор толщины карандаша
2. Выбор цвета карандаша
3. Загрузку и сохранение графического файла.
Миниатюры
Простой Paint - Разбор полетов  
1
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
03.07.2019, 10:13 37
Цитата Сообщение от ashsvis Посмотреть сообщение
Скорее всего так, если я правильно понял назначение свойства PenStyle.Hardness:
Нет, нет. Я ж говорю - все сложнее. Откройте photoshop или Paint.NET и посмотрите как они работают с прозрачностью.

Во-первых, hardness - это не прозрачность карандаша, это его мягкость:
Название: Скриншот 2019-07-03 10.04.08.png
Просмотров: 278

Размер: 14.6 Кб

Во-вторых, вот так Paint.NET рисует линию с полупрозрачностью:
Простой Paint - Разбор полетов

И вот так рисуете вы (если бы у вас поддерживалась полупрозрачность):
Простой Paint - Разбор полетов

Обратите внимание на центральный пиксел, где линии пересекаются.

Нужно что бы было как в Paint.NET.
0
918 / 499 / 201
Регистрация: 08.10.2018
Сообщений: 1,543
Записей в блоге: 11
03.07.2019, 10:51 38
Цитата Сообщение от Storm23 Посмотреть сообщение
Обратите внимание на центральный пиксел
Да, так оно и будет получаться. Я, почему-то не считал это недостатком...
Ну, а решение для ластика найдено:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
... 
       internal override void Render(Graphics gr, Document doc)
        {
            //render Layer
            base.Render(gr, doc);
 
            //render line
            RenderLine(gr, RibberStyle.Color);
        }
 
        private void RenderLine(Graphics gr, Color transparent)
        {
            //erase line over Leyer
            if (points.Count > 1)
                using (var pen = new Pen(transparent, RibberStyle.Width))
                {
                    pen.LineJoin = LineJoin.Round;
                    gr.DrawLines(pen, points.ToArray());
                }
        }
 
        internal override void Apply(Document doc)
        {
            doc.OnStartOperation("Ribber tool");
 
            //erase line on Layer 
            using (var gr = Graphics.FromImage(doc.Layer))
            {
                gr.CompositingMode = CompositingMode.SourceCopy;
                gr.CompositingQuality = CompositingQuality.HighSpeed;
                gr.SmoothingMode = SmoothingMode.HighSpeed;
                gr.PixelOffsetMode = PixelOffsetMode.HighSpeed;
                RenderLine(gr, RibberStyle.Color);
            }
            doc.Layer.MakeTransparent(RibberStyle.Color);
 
            //clear points
            points.Clear();
            doc.OnFinishOperation();
        }
...
вечером выложу в репозиторий.
0
918 / 499 / 201
Регистрация: 08.10.2018
Сообщений: 1,543
Записей в блоге: 11
03.07.2019, 11:16 39
Цитата Сообщение от Storm23 Посмотреть сообщение
И вот так рисуете вы (если бы у вас поддерживалась полупрозрачность)
Вот как получается:
Простой Paint - Разбор полетов

Разные линии затемняют друг друга, а линия сама по себе - нет (при внутреннем пересечении).
Так что всё нормально.
0
Эксперт .NETАвтор FAQ
10413 / 5143 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
03.07.2019, 11:21 40
Цитата Сообщение от ashsvis Посмотреть сообщение
решение для ластика найдено
Нет, для ластика тоже должна поддерживаться полупрозрачность (opacity) и hardness.
1
03.07.2019, 11:21
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.07.2019, 11:21
Помогаю со студенческими работами здесь

Открыть картинку в Paint или Paint Net если установлен
Здравствуйте. Как можно открыть картинку в программе Paint или если существует в Paint net И еще...

Разбор полетов
Меня больше всего интересует строчка вычесления позиции символа. (ring - lotr + 1). объясните,...

разбор полетов, ассемблер..
ПРивет всем! ТОлько начал изучать ассемблер, есть куча непоняток. Решил начинать с примеров, если...

Разбор полетов. ошибка е2140
Всем Привет! Тут такая тема- написать программу для задачи: Расчитать вероятность попадания...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru