МИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра ВТ ОТЧЕТ по лабораторной работе №3 по дисциплине «Организация ЭВМ и систем» Тема: ИССЛЕДОВАНИЕ ВИДЕОСИСТЕМЫ (ГРАФИЧЕСКИЙ РЕЖИМ) Студент гр. 8005 Преподаватель Павлов С.М. Санкт-Петербург 2021 Цель работы - изучение работы с видеосистемой в графическом режиме, вывод графика заданной функции с масштабированием и разметкой осей. Краткие сведения о видеосистемах ПЭВМ. Основным техническим средством для оперативного формирования и отображения как текстовой, так и графической информации в компьютере является видеосистема. Видеосистема компьютера состоит из трех основных компонентов: видеоадаптер (видеокарты); монитор (дисплей); программное обеспечение (драйверы видеосистемы). Видеоадаптер посылает в монитор сигналы управления яркостью лучей и синхросигналы строчной и кадровой развёрток. Монитор преобразует эти сигналы в зрительные образы. А программные средства обрабатывают видеоизображения — выполняют кодирование и декодирование сигналов, координатные преобразования, сжатие изображений и др. Графический режим работы видеосистемы. Графический режим монитора предназначен для вывода на экран графиков, рисунков и т. д. Разумеется, в этом режиме можно выводить также и текстовую информацию в виде различных надписей, причем эти надписи могут иметь произвольный шрифт, размер букв и т.д. В графическом режиме экран монитора состоит из точек, каждая из которых может быть одного из нескольких цветов. Количество точек по горизонтали и вертикали называется разрешающей способностью монитора в данном режиме. Например, выражение разрешающая способность 640 x 200 - означает, что монитор в данном режиме выводит 640 точек по горизонтали и 200 точек по вертикали. 2 Принцип работы с графической библиотекой. Прежде чем использовать функции графической библиотеки С++, необходимо инициализировать систему графики - загрузить соответствующий адаптеру или режиму .BGI-драйвер, установить в начальные значения внешние переменные и константы, выбрать шрифт и т.д. Начнем рассмотрение с подключения графического режима: int driver, mode; // драйвер и режим driver = DETECT; // автоопределение initgraph(&driver,&mode,"c:\\borlandc\\bgi"); Инициализацию графической модели выполняет функция initgraph(): void far initgraph(int *graphdriver, int *graphmode, char * pathtodriver). При вызове она инициализирует графическую систему, загружая. BGIдрайвер, определяемый указателем graphdriver, и устанавливая видеоадаптер в графический режим, задаваемый указателем graphmode. Третий аргумент функции initgraph() задает маршрут поиска файла, содержащего .BGI-драйвер. Если файл не найден в заданной директории, функция просматривает текущий директорий. В нашем случае маршрут задан следующим образом: "c:\\borlandc\\bgi" С++ поддерживает фиксированное число драйверов, каждый из которых, в свою очередь, поддерживает ряд режимов. Как тип драйвера, так и режим могут быть заданы числом или символической константой. Далее перейдем непосредственно к выводу графика заданной функции: Две функции позволяют определить ширину и высоту экрана в пикселах для текущего видеорежима: getmaxx() и getmaxy(). Задание стиля линии выполняет функция setlinestyle(). void setlinestyle (int linestyle, unsigned upattern, int thickness) - устанавливает стиль "рисования" отрезков прямых линий и графических примитивов. Аргумент linestyle выбирает стиль линии, а аргумент thickness - толщину линии. 3 Аргумент upattern используется только в том случае, когда задается отличный от предопределенных стиль линии, т.е. если linestyle равен USERBIT_LINE (4). Что же касается функции rectangle(), то ее прототип выглядит следующим образом: void rectangle( int left, int top, int right, int bottom) - выводит контур прямоугольника, заданного координатами левого верхнего (left, top) и правого нижнего (right, bottom) углов. Координаты углов задаются относительно координат левого верхнего угла текущего графического окна. Контур выводится линией текущего цвета и стиля. Цвет контура устанавливается функцией setcolor(). Стиль линии задается функцией setlinestyle(). Заполнение цветом прямоугольной области выполняется с помощью функций setfillstyle и floodfill. Начнем с setfillstyle(): void setfillstyle(int pattern, int color) - выбирает один из предопределенных стилей заполнения. Значение pattern идентифицирует стиль. Аргумент color задает цвет, используемый для пикселов по заданному шаблону. Задав стиль, перейдем к самому заполнению, выполняемому функцией floodfill(): void floodfill (int x, int y, int border) - заполняет текущим стилем область экрана, ограниченную непрерывной линией с цветом border, начиная с точки с координатами (х, у). Функция заполняет область либо внутри замкнутой линии, либо вне ее. Это зависит от положения начальной точки: если она лежит внутри области, заполняется внутренняя область; если точка лежит вне замкнутой области, заполняется внешняя область; если точка лежит точно на линии цвета border, заполнение не производится. Заполнение начинается с начальной точки и продолжается во всех направлениях, пока не встретится пиксел с цветом border. Цвет border должен отличаться от цвета заполнения, в противном случае будет заполнен весь экран. 4 Построение графика функции выполняется с помощью функции drawf(): На вход подаем количество точек по оси X, для которых будет рассчитано значение функции. Переменная dx отвечает за шаг аргумента x, шаг рассчитывается в соответствии с диапазоном аргумента, представленном в задании. Далее создан цикл, осуществляющий поиск максимума значения функции на представленном диапазоне аргумента x. После того, как максимум найден запускаем цикл отрисовки заданной функции: рассчитываем значение в каждой точке диапазона, и устанавливаем найденную точку на экран с помощью функции putpixel(): void putpixel(int x, int у, int pixelcolor) Определяет, лежит ли пиксел с координатами (х, у) в текущем графическом окне, и, если лежит, выводит на экран пиксел, код цвета которого равен pixelcolor. В противном случае цвет пиксела не изменяется. Используя функцию putpixel(), можно "стереть" пиксел, если вывести его с кодом цвета фона. Для того, чтобы пиксел лежал в созданном окне необходимо нормировать координату значения функции, привести ее к целочисленному значению, а потом привести эту координату к соответствующим параметрами окна. Нарисовав график функции, перейдем к отрисовке координатных осей: За стиль координатных осей отвечает функция setlinestyle(), описанная выше. Чтобы нарисовать оси, необходимо воспользоваться функцией line(): void line( int x1, int y1, int x2, int y2) - выводит отрезок прямой линии между двумя явно специфицированными точками (x1, y1) и (х2, у2), используя текущие цвет, стиль, толщину и режим вывода линии. Координаты (x1, y1) и (х2, у2) задаются относительно левого верхнего угла текущего графического окна. Функция не изменяет текущую позицию. Подпись осей выполняется функцией outtextxy(): void outtextxy (int x, int y, char *textstring) - выводит ASCII-строку текста, на начало которой указывает textstring, используя текущие цвет, установки направления, типа шрифта и выравнивания строки. Аргументы х и у явно 5 специфицируют новую текущую позицию, используемую для вывода строки. Координаты X и Y измеряются относительно координат левого верхнего угла текущего графического окна. Для разметки осей создает циклы, следующего вида: for(i=0; i<29; ++i) line(X0+20*i,Y0-220,X0+20*i,Y0-225); В таких циклах отрисовываем штрихи, находящиеся друг от друга на определенном расстоянии, как это реализовано на обычной линейке. Подписываем штрихи с помощью outtextxy(). После построения графика и координатных осей, осталось вывести максимальное значение функции на заданном диапазоне значений аргумента. Максимальное значение находили в функции drawf() описанной выше. Это значение было найдено в формате float, для того чтобы вывести его была создана следующая конструкция: Вначале используем функцию sprintf(), чтобы записать максимальное значение в массив символов: int sprintf(char *buf, const char *format, arg-list) Функция sprintf() идентична printf(), за исключением того, что вывод производится в массив, указанный аргументом buf. Далее создав еще один массив (который будет содержать текст надписи, выводимой впоследствии на экран), добавим в него текст с помощью функции strcpy(): char *strcpy(char *str1, const char *str2) Функция strcpy() используется для копирования содержимого str2 в str1. Аргумент str2 должен быть указателем на строку, оканчивающуюся нулем. Функция strcpy() возвращает указатель на str1. Если строки str1 и str2 перекрываются, то поведение функции strcpy() не определено. Теперь “соединим” массивы с значением максимума функции и с надписью о том, что это максимальное значение. Эту операцию выполнит функция strcat(): 6 char *strcat(char *str1, const char *str2) Функция strcat() конкатенирует (соединяет в цепочку) строку str1 и копию строки str2. В конце модифицированной строки str1 функция устанавливает нулевой символ. Нулевой символ, первоначально завершавший строку str1, замещается первым символом строки str2. Строка str2 остается в первоначальном виде. Для того, чтобы эти функции работали подключаем библиотеки string.h и stdio.h. Вывод максимального значения непосредственно на экран осуществляет уже известная ранее функция outtextxy(). Т.к. функции графической библиотеки больше не нужны, следует вызвать функцию closegraph() "закрытия" графического режима и возвращения к текстовому режиму. Эта функция освобождает память, распределенную под драйверы графики, файлы шрифтов и промежуточные данные и восстанавливает режим работы адаптера в то состояние, в котором он находился до выполнения инициализации системы. Задание. 1. Разработать программу для вывода на экран графика Sin2(x/2)+Sqrt(x) с диапазоном от 3π/2 до 15π. 2. Произвести разметку осей. 3. Найти максимальное значение функции на заданном интервале. Текст программы. #include "iostream" #include "stdio.h" #include "conio.h" #include "math.h" #include "dos.h" #include "graphics.h" #include "string.h" using namespace std; int Xmax, Ymax, X0, X1, Y0, Y1; float R, MaxF=0.; 7 функции void Foo(int N) { double x=3*3.14/2, dx=(15*3.14-(3*3.14)/2)/N; MaxF=(float)(pow((sin(x/2)),2.0)+sqrt(x)); for(int i=0;i<N;i++) { double z = x + i * dx; R = (float)(pow((sin(z/2)),2.0)+sqrt(z)); if(MaxF < R) { MaxF = R; } } for (int i=0; i<N; i++, x+=dx) { R=(float)(pow((sin(x/2)),2.0)+sqrt(x)); putpixel(i+X0+20,(Y0-(int)(R/MaxF*(float)(Y0-Y1)))/2-5,GREEN); } } int main() { int i, N; int driver, mode; driver = DETECT; initgraph(&driver,&mode,"c:\\borlandc\\bgi"); Xmax=getmaxx(); Ymax=getmaxy(); X0=20; Y0=Ymax-30; X1=Xmax-30; Y1=30; N = X1-X0; Foo(N); setlinestyle(0,1,1); line(X0+20, Y0-5, X0+20, Y1-20); line(X0+20, Y0-220, X1+20, Y0-220); outtextxy(Xmax/4,Y0-100,"sin^2(x/2)+sqrt(x)"); outtextxy(X1+3,Y0-219,"x"); for(i=1;i<23;++i) line(X0+20,Y0-i*20,X0+25,Y0-i*20); for(i=0;i<29;++i) line(X0+20+20*i,Y0-220,X0+20+20*i,Y0-225); outtextxy(X0+23,Y0-218,"1.5"); outtextxy(X0+20*5,Y0-218,"3.5"); outtextxy(X0+20*9,Y0-218,"5.5"); 8 outtextxy(X0+20*13,Y0-218,"7.5"); outtextxy(X0+20*17,Y0-218,"9.5"); outtextxy(X0+20*21,Y0-218,"11.5"); outtextxy(X0+20*25,Y0-218,"13.5"); char cMaxF[10]; sprintf(cMaxF,"%f",MaxF); char str[24]; strcpy(str,"MAX(f(x)) = "); strcat(str,cMaxF); outtextxy(Xmax/4,Y0-60,str); getch(); closegraph(); } Пример запуска программы. 9 Структурная схема аппаратных средств. Центральный процессор Оперативная память ЦП ОЗУ Графический монитор Информационная магистраль Видеоконтроллер Видеопамять Графический процессор Видеоадаптер 10