Как нарисовать линию в c
Перейти к содержимому

Как нарисовать линию в c

  • автор:

Как нарисовать линию в С++ по двум координатам?

Мне надо несколько линий нарисовать черным, несколько белым.
Как?
Помню что есть функция в которую передаются координаты начала и конца линии.

Лучший ответ

Никак
В С++ нет фунций работы с графикой. Они есть только в конкретных реализациях библиотек.
Определись с какими библиотеками работаешь и смотри их документацию.

Остальные ответы
Нет такой функции в C++, смотри сторонние библиотеки.

Для старых компиляторов: есть заголовочный файл graphics.h, где содержится процедура void line(int x1, int y1, int x2, int y2), где (x1, y1), (x2, y2) — концы линии. Для задания цвета есть процедура color.

Не парься, возьми на вооружения OpenGL, пригодится. Не только линии сможешь рисовать.
А так вот: [ссылка заблокирована по решению администрации проекта]

Как нарисовать линию с помощью алгоритма Брезенхема и гамма-коррекции в текстовом файле?

5bd5fae59bb15314855816.png

Есть задача — создать текстовый файл формата .pgm или .ppm и заполнить его значениями = 255, чтобы получилось просто пустое изображение с белым фоном (размер задаётся при создании). Затем сделать функцию, с помощью которой можно отрисовать черную линию с произвольными координатами, которые задаются пользователем (я выбрал алгоритм Брезенхема). В итоге в текстовом файле сохраняется линия такого вида:

Теперь стоит задача нарисовать «красивую» линию, которая не будет выглядеть ступенчато, а просто как обычная ровная линия. Препод предлагает использовать гамма-коррекцию, а именно переводить каждый пиксель по такой формуле : encoded = ((original / 255) ^ (1 / gamma)) * 255
Также советует смотреть в сторону стандарта sRGB.
В первую очередь интересует, каковы значения переменных original и gamma? Во-вторых, как именно здесь должен применяться sRGB ? И для отрисовки «красивой» линии мне нужно просто каждый пиксель линии переводить по такой формуле ?
Код программы :

#include "stdafx.h" #include #include #include #include using namespace std; void drawLine(int** array, int x1, int y1, int x2, int y2) < const int deltaX = abs(x2 - x1); const int deltaY = abs(y2 - y1); const int signX = x1 < x2 ? 1 : -1; const int signY = y1 < y2 ? 1 : -1; // int error = deltaX - deltaY; // array[x2][y2] = 0; while (x1 != x2 || y1 != y2) < array[x1][y1] = 0; const int error2 = error * 2; // if (error2 >-deltaY) < error -= deltaY; x1 += signX; >if (error2 < deltaX) < error += deltaX; y1 += signY; >> > int main(void) < ofstream fout; fout.open("E:\\line.pgm"); fout.write("", 0); fout « "P2" « "\n" ; int numcols, numrows, x1, x2, y1, y2; cout « "Enter rows and columns number: "; cin » numrows » numcols; cout « "Enter coords x1 and y1: "; cin » x1 » y1; cout « "Enter coords x2 and y2: "; cin » x2 » y2; fout « numrows « " " « numcols « "\n"; fout « 255 « "\n"; int** array = new int*[numrows]; for (int count = 0; count < numrows; count++) array[count] = new int[numcols]; for (int i = 0; i < numrows; ++i) < for (int j = 0; j < numcols; ++j) < array[i][j] = 255; >> drawLine(array, x1, y1, x2, y2); for (int i = 0; i < numrows; ++i) < for (int j = 0; j < numcols; ++j) < fout « array[i][j] « " "; >> fout.close(); >
  • Вопрос задан более трёх лет назад
  • 1412 просмотров

6 комментариев

Средний 6 комментариев

lastuniverse

Роман @lastuniverse

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

BacCM

Роман, это их визуально сгладит

lastuniverse

Роман @lastuniverse

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

lastuniverse

Роман @lastuniverse

Гамма-коррекция тут никак не поможет. sRGB также не касается вашей задачи. Оба по большей части предназначены для унификации цветопередачи на мониторах и печатной продукции.
Как вариант, для сглаживания линий используйте Wu Algorithm (алгоритм для сглаживания линий).

Wu Algorithm

antialias.pngzoom.png

Для более «тонкого» сглаживания обратите внимание на возможность субпиксельного сглаживания

субпиксельное сглаживание

PS: перенес из комментариев 2 имплементации:

1. попытка соединить Ваш код с кодом WuLine (некий псевдокод для понимания)

// array[][] - полотно на котором рисуем // (далее все функции переделаны под grayscale вариант) #include "stdafx.h" #include #include #include #include using namespace std; // функция рисования линии void WuLine(int** array, int x0, int y0, int x1, int y1) < var steep = Math.Abs(y1 - y0) >Math.Abs(x1 - x0); if (steep) < Swap(ref x0, ref y0); Swap(ref x1, ref y1); >if (x0 > x1) < Swap(ref x0, ref x1); Swap(ref y0, ref y1); >DrawDarkPoint(steep, x0, y0, 1); DrawDarkPoint(steep, x1, y1, 1); float dx = x1 - x0; float dy = y1 - y0; float gradient = dy / dx; float y = y0 + gradient; for (var x = x0 + 1; x > // функция рисования "черной" точки void DrawDarkPoint(bool steep, int x, int y, float c) < if (!steep) < var color = GetPixel(x, y); color *= (1 - c); SetPixel(x, y, color); >else < var color = GetPixel(y, x); color *= (1 - c); SetPixel(y, x, color); >> // считываем значение цвета точки с полотна в координатах x,y int GetPixel(int x, int y) < // настоятельно рекомендую вставить проверку на выход за границы полотна return array[x][y]; >// рисуем точку на полотне в координатах x,y цветос c (число от 0 до 255) void SetPixel(int x, int y, int c) < // настоятельно рекомендую вставить проверку на выход за границы полотна array[x][y] = c; >// далее почти без изменений Ваш код int main(void) < ofstream fout; fout.open("E:\\line.pgm"); fout.write("", 0); fout « "P2" « "\n" ; int numcols, numrows, x1, x2, y1, y2; cout « "Enter rows and columns number: "; cin » numrows » numcols; cout « "Enter coords x1 and y1: "; cin » x1 » y1; cout « "Enter coords x2 and y2: "; cin » x2 » y2; fout « numrows « " " « numcols « "\n"; fout « 255 « "\n"; int** array = new int*[numrows]; for (int count = 0; count < numrows; count++) array[count] = new int[numcols]; for (int i = 0; i < numrows; ++i) < for (int j = 0; j < numcols; ++j) < array[i][j] = 255; >> WuLine(array, x1, y1, x2, y2); for (int i = 0; i < numrows; ++i) < for (int j = 0; j < numcols; ++j) < fout « array[i][j] « " "; >> fout.close(); >

2. полностью рабочий вариант на nodejs

// подключаем библиотеку работы с файлами const fs = require('fs'); // создаем сласс Canvas function Canvas(width,height) < this.width = width; this.height = height; this.sheet = []; for(let y=0; y> >; // Метод рисования линии Canvas.prototype.WuLine = function(x0, y0, x1, y1) < const steep = Math.abs(y1 - y0) >Math.abs(x1 - x0); if (steep) < var swap; swap = x0; x0 = y0; y0 = swap; swap = x1; x1 = y1; y1 = swap; >if (x0 > x1) < var swap; swap = x0; x0 = x1; x1 = swap; swap = y0; y0 = y1; y1 = swap; >this.DrawDarkPoint(steep, x0, y0, 1); this.DrawDarkPoint(steep, x1, y1, 1); const dx = x1 - x0; const dy = y1 - y0; const gradient = dy / dx; let y = y0 + gradient; for (var x = x0 + 1; x >; // метод рисования "черной" точки Canvas.prototype.DrawDarkPoint = function(steep, x, y, c) < const xx = Math.floor(x); const yy = Math.floor(y); if (!steep) < var color = this.GetPixel(xx, yy); color *= (1 - c); this.SetPixel(xx, yy, color); >else < var color = this.GetPixel(yy, xx); color *= (1 - c); this.SetPixel(yy, xx, color); >>; // метод получает значение цвета точки с полотна в координатах x,y Canvas.prototype.GetPixel = function(x, y) < return this.sheet[y][x]; >; // метод устанавливает значение с в точку на полотне в координатах x,y Canvas.prototype.SetPixel = function(x, y, c) < c = Math.floor(c); if(x=this.width) return; if(y=this.height) return; this.sheet[y][x] = c; >; // метод сохраняет картинку в файл в формате PPM Canvas.prototype.savePPM = function(fname) < const fd = fs.openSync(fname, 'a'); fs.writeSync(fd, "P3\n"); fs.writeSync(fd, "# P3 обозначает, что цвета даны в ASCII,\n"); fs.writeSync(fd, "# затем идут цифры, обозначающие число колонок и рядов\n"); fs.writeSync(fd, "# 255 для максимального значения цвета\n"); fs.writeSync(fd, "# затем триплеты RGB\n"); fs.writeSync(fd, this.width + " " + this.height + "\n"); fs.writeSync(fd, "255\n"); this.sheet.forEach(a=>< a.forEach(c=>< fs.writeSync(fd, c + " " + c + " " + c + "\n"); >); >); >; var canvas = new Canvas(400,400); for(let i=0; i canvas.savePPM("test.ppm");

5bd6cb8fbf6b3023697404.png

tj57 @tj57 Автор вопроса

Роман, я попробовал первый вариант реализовать, код работает без ошибок, но результат не тот — рисуется обычная несглаженная линия. Не подскажете, в чем может быть проблема? От использования функций GetPixel и SetPixel пришлось отказаться, так как вылезали ошибки по памяти, когда я пытался эти функции имплементировать

// функция рисования "черной" точки void DrawDarkPoint(int **array, bool steep, int x, int y, float c) < if (!steep) < int color = array[x][y]; color *= (1 - c); array[x][y] = color; >else < int color = array[y][x]; color *= (1 - c); array[y][x] = color; >> void WuLine(int** array, int x0, int y0, int x1, int y1) < int steep = abs(y1 - y0) >abs(x1 - x0); if (steep) < swap(x0, y0); swap(x1, y1); >if (x0 > x1) < swap(x0, x1); swap(y0, y1); >DrawDarkPoint(array, steep, x0, y0, 1); DrawDarkPoint(array, steep, x1, y1, 1); float dx = x1 - x0; float dy = y1 - y0; float gradient = dy / dx; float y = y0 + gradient; for (int x = x0 + 1; x >

tj57 @tj57 Автор вопроса

Роман, хотя, я нашел такой вариант рисования сглаженной линии в одном источнике:
members.chello.at/easyfilter/bresenham.html

void plotLineAA(int x0, int y0, int x1, int y1) < int dx = abs(x1 - x0), sx = x0= -dx) < /* x step */ if (x0 == x1) break; if (e2 + dy < ed) setPixelAA(x0, y0 + sy, 255 * (e2 + dy) / ed); err -= dy; x0 += sx; >if (2 * e2 > > void setPixelAA(int x, int y, double alpha) < int a = 1 - alpha / 255; >

При этом не рисуется линия вообще, то есть элементы массива не заполняются значениями. Мне почему-то кажется, что дело в выборе значения в setPixelAA

Решения вопроса 0
Ответы на вопрос 1
Программист на «си с крестами» и не только

Я бы работал по такой формуле:

result = ((original / max) 1 / gamma ) · 255

Original — это полученное алгоритмом Ву значение (float или хотя бы short!)
max — максимально возможное значение original. Для short, например, это 65535.
gamma — традиционно 2,2.

Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

cpp

  • C++
  • +1 ещё

В чем ошибка кода?

  • 1 подписчик
  • 9 часов назад
  • 97 просмотров

Как нарисовать линию из символов?

Дали задание, нужно нарисовать фигуру из четырёх заданных точек. Но проблема в том, что точки могут быть не только прямые, а к примеру одна из точек на 1 уровень ниже чем вторая. С выводом точек я справился, но вот как вывести кривые линии из символов, после часа гуглинга и попыток понять алгоритм Брезенхема, я так и не понял. Так-что вопрос напрашивается сам, как из символов, нарисовать линию между двумя точками (которые могут быть на одном уровне, или на разных)? Точки мы записываем как структуру:

struct Point

И выводим просто фигуру из символов:

 o***************o * * * * ** * * * o********* * ********o 

Отслеживать

13.7k 12 12 золотых знаков 43 43 серебряных знака 75 75 бронзовых знаков

Как нарисовать линию в c

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

При работе в dosbox есть один нюанс: чтобы окно не закрывалось преждевременно, нужно как-то делать задержку. Я для задержки использую cin.get() . Если задержку сделать после прекращения работы графического режима, то на экране ничего не будет. Надо задержку делать во время работы графического режима, не потом.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *