Обработка изображения в двоичных файлах

Информация о графических форматах. Хранение изображения в программе. Очередь как вспомогательная структура данных. Загрузка изображения из двоичного файла. Операции с изображением. Уменьшение разрешающей способности. Увеличение размера изображения.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 29.06.2013
Размер файла 1,1 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Министерство образования Российской Федерации

Новосибирский Государственный Технический Университет

Курсовой проект по дисциплине "Программирование"

Обработка изображения в двоичных файлах

Факультет: АВТФ

Группа: АВТ-919

Выполнил: Рожков А. Е.

Проверил: Романов Е. Л.

Новосибирск

2011

Содержание

1. Задание

2. Структурное описание разработки

2.1 Информация о графических форматах

2.2 Структура BMP файла

2.3 Хранение изображения в программе

2.4 Операции с изображением

2.5 Очередь как вспомогательная структура данных

2.5.1 Структура очереди

2.5.2 Операции с очередью

3. Функциональное описание

3.1. Класс BMP

3.1.1 Данные класса BMP

3.1.2 Методы класса BMP

3.2. Класс QUEUE(очередь)

3.2.1 Данные класса QUEUE

3.2.2 Методы класса QUEUE

4. Описание работы программы на контрольных примерах и выводы

4.1 Загрузка изображения из двоичного файла

4.2 Уменьшение разрешающей способности

4.3 Увеличение размера изображения

4.4 Выводы

5. Приложение

1. Задание

Программа «вручную» читает растровый файл изображения (bmp), выполняя заданные преобразования изображения. Допускаются ограничения на форматы обрабатываемых файлов (256-цветов и т.п).

Изменение контрастности и яркости изображения.

Изменение масштаба изображения.

Уменьшение разрешающей способности путем усреднения групп пикселей (3х3).

Искажение изображения («линза»).

Рисование элементарных графических объектов (точки, линии, окружности, треугольники, четырёхугольники, закрашенные прямоугольники).

Наложение одного изображения на другое, с прозрачностью задаваемого цвета.

Заливка.

2. Структурное описание разработки

Данная программа представляет собой консольное приложение для работы с графическими изображениями. Вначале кратко изложим информацию о графических форматах и структуре их файлов. Затем рассмотрим структурное описание созданной программы.

2.1 Информация о графических форматах

Для хранения графической информации в вычислительной технике существуют различные способы её записи, называемые графическими форматами. Графические форматы делятся на векторные и растровые.

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

В растровых форматах изображения хранятся в виде сетки пикселей или точек цветов (обычно прямоугольной). Растровых форматов очень много: BMP, ECW ,GIF, ICO, PNG, JPEG и др.

Подробно рассмотрим BMP формат. С данным форматом работает огромное количество программ, так как его поддержка интегрирована в операционные системы Windows и OS/2. Файлы формата BMP могут иметь расширения .bmp, .dib и .rle. Кроме того, данные этого формата включаются в двоичные файлы ресурсов RES и в PE-файлы.

Глубина цвета в данном формате может быть 1, 4, 8, 16, 24, 32, 48 бит на пиксел, максимальные размеры изображения 65535Ч65535 пикселов.

В формате BMP есть поддержка сжатия по алгоритму RLE, однако теперь существуют форматы с более сильным сжатием, и из-за большого объёма BMP редко используется в Интернете, где для сжатия без потерь используются PNG и более старый GIF.

2.2 Структура BMP файла

Моя программа работает с BMP форматом с глубиной цвета 24 бита на пиксель, без сжатия, без палитры. При таком хранении изображения, каждому пикселу соответствуют три последовательные байта, хранящие составляющие цвета B, G, R; (не R, G, B). Для загрузки изображения необходимо знать внутреннюю структуру файла:

24-разрядный BMP-файл состоит из трёх частей:

1) Заголовок файла

2) Заголовок изображения

3) Само изображение

В таблице 2.2 приведено подробное описание каждой части.

Таблица 2.2

Смещение от начала файла в байтах

Длина поля в байтах

Описание поля

ЗАГОЛОВОК ФАЙЛА

0

2

Код 424Dh - Буквы 'BM'

2

4

Размер файла в байтах

6

2

0 (Резервное поле)

8

2

0 (Резервное поле)

10

4

Смещение, с которого начинается само изображение (растр), равно 54

ЗАГОЛОВОК ИЗОБРАЖЕНИЯ

14

4

Размер заголовка в байтах, равно 40

18

4

Ширина изображения в пикселях

22

4

Высота изображения в пикселях

26

2

Число плоскостей, должно быть 1

28

2

Бит/пиксел: 24

30

4

Тип сжатия, равно 0

34

4

0 или размер сжатого изображения в байтах.

38

4

Горизонтальное разрешение, пиксел/м

42

4

Вертикальное разрешение, пиксел/м

46

4

Количество используемых цветов

50

4

Количество "важных" цветов, равно 0.

САМО ИЗОБРАЖЕНИЕ

Изображение сохраняется построчно СНИЗУ-ВВЕРХ. Для хранения каждой строки выделяется кратное 4 количество байт. В незначащих байтах хранится мусор. Старшему биту или тетраде соответствует самый левый пиксел.

2.3 Хранение изображения в программе

Информация о изображении храниться в виде структуры данных(BMP), состоящей из: переменных, хранящих данные о изображении и графическом файле, и двумерного динамического массива указателей(MBMP), который хранит непосредственно цвета пикселей. Его структура такова: массив указателей на biHeight массивов байтов (строк изображения), которые содержат biWidth * 3 + n элементов. Каждые 3 элемента строки представляют собой цвет пикселя в формате RGB, начиная с нулевого элемента. Размер массива с пикселями кратен 4, это обеспечивается числом n. Вышесказанное иллюстрируется рисунком 2.3.

Размещено на http://www.allbest.ru/

2.4 Операции с изображением:

Для работы с изображением предусмотрены следующие операции:

· загрузка и сохранение из двоичного файла с заданным именем (имя вводится пользователем с клавиатуры),

· создание пустого изображения (белого, с нужными размерами, которые вводятся пользователем с клавиатуры),

· получение размера файла с изображением (размер графического файла при сохранении данного изображения на жесткий диск),

· получение размера изображения (ширина и высота),

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

рис 2.4.1

· изменение яркости (на рис.2.4.2а исходное изображение, а на рис.2.4.2б с уменьшенной яркостью).

рис.2.4.2а рис 2.4.2б

· изменение контрастности (на рис.2.4.3а исходное изображение, а на рис.2.4.3б с увеличенной контрастностью).

рис.2.4.3а рис.2.4.3б

· изменение масштаба (изменение размера изображения). При увеличении изображения в n раз, каждый пиксель в стоке повторяется n раз и каждая строка повторяется n раз. При уменьшении изображения в n раз проходим исходное изображение с шагом n, и для каждой матрицы nxn считаем средний цвет, который и помещаем в новое изображение. Работу данного алгоритма иллюстрирует рис.2.4.4.

Рис.2.4.4

· наложение одного изображения на другое с прозрачностью какого-либо цвета второго (на рис.2.4.5а и рис.2.4.5б исходные изображения, а на рис.2.4.5в результат).

рис.2.4.5а

рис.2.4.5брис.2.4.5в

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

рис.2.4.6

· получение цвета пикселя, с заданными пользователем координатами,

· уменьшение разрешающей способности. Под уменьшением разрешающей способности здесь понимается усреднение всех цветов пикселей изображения, относительно их 8 соседних пикселей.

Для каждого пикселя изображения подсчитывается сумма красного, зеленого и синего каналов цвета его и всех ближайших соседей(см. рис.2.4.7 соседи обозначены 1, а текущий пиксель 2, результирующий 3), затем эти суммы делятся на количество соседей + 1. Полученные значения каналов цвета записываются в текущий пиксель. В результате получается эффект размывания изображения.

рис.2.4.7

Пример работы программы на рис.2.4.8(а - исходный, б - результат)

рис.2.4.8арис.2.4.8б

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

Пример работы программы на рис.2.4.8(а - исходный, б - результат)

рис.2.4.8а рис.2.4.8б

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

Для реализации данного алгоритма удобно использовать очередь, для хранения координат «соседей», которые ещё не проверены.

2.5 Очередь как вспомогательная структура данных

2.5.1 Структура очереди

Очередь -- структура данных с дисциплиной доступа к элементам «первый пришёл -- первый вышел» (FIFO, First In -- First Out). Добавление элемента возможно лишь в конец очереди, выборка -- только из начала очереди, при этом выбранный элемент из очереди удаляется.

При программировании метода «заливка», используется очередь, которая представлена в программе в виде отдельной структуры данных (см. рис.2.5.1).

Размещено на http://www.allbest.ru/

Рис.2.5.1

Очередь реализована в виде двухсвязного списка. Указатели beg и end типа node (элемент очереди) хранят адреса первого и последнего элемента соответственно. Целочисленная переменная sz хранит количество элементов очереди. Ниже приведена структура класса node:

Размещено на http://www.allbest.ru/

Переменные x,y - это координаты пикселя, которые необходимо хранить в очереди для алгоритма «заливка». node * next, prev - это указатели на следующий и предыдущий элемент соответственно.

2.5.2 Операции с очередью.

С очередью предусмотрены следующие операции:

· Вставка элемента в очередь.

Приведем псевдокод данного алгоритма:

Алгоритм вставки элемента в очередь(Push(x,y)):

Создаем новый элемент, с переданными значениями координат x,y

Помещаем его в конец очереди:

Если очередь пуста, то beg присвоить адрес этого элемента

Иначе добавляем перед end данный элемент

end присваиваем адрес этого элемента

увеличиваем значение счетчика элементов

Выход

· Изъятие элемента из очереди:

Приведем псевдокод данного алгоритма:

Алгоритм изъятия элемента из очереди(Pop(x,y)):

Если очередь пуста, то выход

Возвращаем значение первого элемента (координаты пиксела)

Удаляем первый элемент:

Если элемент один, то удаляем его и обнуляем указатели beg и end

Иначе перемещаем указатель beg на предыдущий элемент и удаляем первый элемент в очереди

уменьшаем значение счетчика элементов

Выход

· Получение количества элементов очереди.

3. Функциональное описание

Изображения, с которыми работает данная программа, хранятся в объектах класса BMP. В данном классе реализованы различные методы обработки изображений. Рассмотрим их функциональное описание.

3.1 Класс BMP

3.1.1 Данные класса BMP

· ИМЕНА НОВЫХ ТИПОВ ДАННЫХ

Для описания типов переменных в данном кассе вводятся новые имена типов:

typedef short WORD;

typedef unsigned DWORD;

typedef long LONG;

typedef unsigned char BYTE;

· ДАННЫЕ О ФАЙЛЕ

WORD bfType; // тип файла, символы "BM"

DWORD bfSize; // размер всего файла в байтах

WORD bfReserved1;

WORD bfReserved2; // зарезервированные, должны //содержать нули

DWORD bfOffBits; // содержит смещение в байтах от //начала заголовка до битов изображения, равен 54

· ДАННЫЕ О ИЗОБРАЖЕНИИ

DWORD biSize; // размер структуры данных о //изображении, равен 40

LONG biWidth; // ширина изображения в пикселах

LONG biHeight; // высота изображения в пикселах

WORD biPlanes; // число плоскостей, равно 1

WORD biBitCount; // указывает количество бит на пиксель, если 24 разрядное изображение то равно 24 т.к. каждый пиксель храниться в виде трёх байтов (RGB формат).

DWORD biCompression; // тип сжатия. Если рано BI_RGB //= 0, то палитра не используется

DWORD biSizeImage; // 0 или размер сжатого //изображения в байтах. При 24 разрядном равно 0.

LONG biXPelsPerMet; // Горизонтальное разрешение, //пиксел/м

LONG biYPelsPerMet; // Вертикальное разрешение, //пиксел/м

DWORD biClrUsed; // Количество используемых цветов

DWORD biClrImportant;// Количество "важных" цветов

· ИНФОРМАЦИЯ О ПИКСЕЛЯХ

BYTE **MBMP; // массив указателей на пиксели изображения

3.1.2 Методы класса BMP

Функция перевода цвета в формат RGB:

void Col_To_RGB(int, int*, int*, int*);

В функцию передается цвет, в виде целого числа(первый параметр):

0 - черный

1 - белый

2 - синий

3 - зелёный

4 - красный

5 - пурпурный

6 - желтый

7 - циановый,

Возвращается значение цвета в формате RGB(три последних параметра).

Функция загрузки изображения из двоичного файла:

int Load(char FileNames[]);

Параметр строка это имя графического файла. Функция возвращает 1, если изображение загрузилось и 0 в противном случае. Если изображение не загрузилось, старое изображение сохраняется.

Приведем псевдокод данной функции:

Загрузка изображения из файла:

Открытие файла с изображением

Чтение из двоичного файла информации о изображении: типе, размере и т.д. во временные переменные.

Если тип не соответствует 24-разрядному изображению в формате BMP, то выход

Удаление предыдущих данных изображения (запуск деструктора)

Запись новых значений о файле и изображении в объект

Создание динамического массива указателей нужного размера (количество элементов в строках массива делаем кратным 4)

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

Закрытие файла

Функция сохранения изображения в двоичный файл:

void Save(char FileNames[]);

Параметр строка это имя графического файла, в который будет сохранено изображение. Если данный файл уже существует, то он будет перезаписан.

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

Функция получения размера файла с изображением в байтах:

unsigned FileSize();

Возвращает размер файла с изображением в байтах.

Функция получения размера изображения:

void Dimensions(int *W, int *H);

Возвращаемые параметры функции это ширина(W) и высота(H) изображения в пикселах.

Функция рисования пиксела:

int PutPixel(int x, int y, int color);

В функцию передаются координаты точки x,y и цвет color в виде целого числа (см. первый параметр функции void Col_To_RGB).

Если координаты точки принадлежат изображению, то данный пиксель закрашивается и функция возвращает 1, иначе ничего не происходит и возвращается 0.

Процесс рисования происходит следующим образом: сначала цвет переводится в формат RGB при помощи функции Col_To_RGB, затем в массив указателей вносятся изменения нужной троки элементов, при этом учитывается, что в массиве строки расположены снизу-вверх и компоненты цвета расположены в порядке BGR.

Функция рисования пиксела(RGB):

int PutPixelRGB(int x,int y,int red,int green,int blue);

В функцию передаются координаты точки x,y и цвет в формате RGB(три целых числа от 0 до 255 отвечающие за яркость красного, зеленого и синего канала цвета - три последних параметра).

Если координаты точки принадлежат изображению, то данный пиксель закрашивается и функция возвращает 1, иначе ничего не происходит и возвращается 0.

Процесс рисования происходит также как в функции PutPixel, только без перевода цвета в другой формат.

Функция считывания цвета заданного пикселя:

int GetPixel(int x,int y,int *red,int *green,int *blue);

В функцию передаются координаты точки x,y. Возвращаемыми являются три последних параметра, которые представляют цвет формате RGB.

Если координаты точки принадлежат изображению, то red, green, blue примут значение цвета данного пиксела и функция возвратит 1, иначе ничего не произойдет и возвратится 0.

Функция рисования линии:

int DrawLine(int x1, int y1, int x2, int y2, int color);

Функция получает координаты начала x1,y1 и конца x2,y2 линии, цвет color в виде целого числа(см. первый параметр функции void Col_To_RGB).

Если координаты начала и конца линии принадлежат изображению, то линия нарисуется и функция возвратит 1, иначе ничего не произойдет и возвратиться 0.

Используется алгоритм Брезенхема.

Функция рисования четырёхугольника:

int DrawQuadrangle(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int color);

В функцию передаются координаты вершин четырёхугольника x1,y1, x2,y2, x3,y3, x4,y4 и цвет color в виде целого числа(см. первый параметр функции void Col_To_RGB).

Если координаты вершин принадлежат изображению, то рисуется четырёхугольник и функция возвращает 1, иначе ничего не произойдет и возвратиться 0.

Процесс рисования происходит следующим образом: последовательно рисуются четыре линии с данными координатами.

Функция рисования треугольника:

int DrawTriangle(int x1,int y1,int x2,int y2,int x3,int y3, int color);

В функцию передаются координаты вершин треугольника x1,y1, x2,y2, x3,y3 и цвет color в виде целого числа(см. первый параметр функции void Col_To_RGB).

Если координаты вершин принадлежат изображению, то рисуется треугольник и функция возвращает 1, иначе ничего не произойдет и возвратиться 0.

Процесс рисования происходит следующим образом: последовательно рисуются три линии с данными координатами.

Функция рисования окружности:

int DrawCircle(int x0, int y0, int radius, int color);

В функцию передаются координаты центра окружности x0,y0, радиус и цвет color в виде целого числа(см. первый параметр функции void Col_To_RGB).

Если координаты центра принадлежат изображению, то рисуется окружность и функция возвращает 1, иначе ничего не произойдет и возвратиться 0.

Используется алгоритм Брезенхема для окружностей.

Функция изменения яркости изображения:

void Bright(int x);

В функцию передается коэффициент x изменения яркости от -255 до 255. При положительном коэффициенте яркость увеличивается, иначе уменьшается.

Процесс изменения яркости выполняется следующим образом: к каждой компоненте цвета всех пикселей прибавляется (уменьшение) или отнимается (увеличение) коэффициент x.

Функция изменения контрастности изображения:

void Contrast(int e);

В функцию передается коэффициент e изменения контрастности от -100 до 100. При положительном коэффициенте контрастность увеличивается, иначе уменьшается.

Процесс изменения контрастности выполняется следующим образом: вычисляется средняя яркость изображения Y, а затем все компоненты цвета всех пикселей изменяются по формуле .

Функция изменения цвета прямоугольника:

void QuadrangleRGB(int x1,int y1,int x2,int y2,int rr,int gg, int bb);

В функцию передаются координаты верхнего левого x1,y1 и нижнего правого x2,y2 углов прямоугольника и три значения цвета в формате RGB. Если компонента цвета равна -1, то данный канал останется в изображении неизменным. Если вершины прямоугольника не принадлежат изображению, то изменения цвета не произойдет.

Функция наложения одного изображения на другое:

void Imposition(BMP &T, int x, int y, int r, int g, int b);

В функцию передаются: ссылка на объект с изображением &T, которое нужно наложить, координаты верхнего левого угла x,y накладываемого изображения в исходном изображении и три значения цвета в формате RGB, который будет прозрачным в накладываемом изображении. Если значения каналов цвета равны -1 -1 -1, то прозрачными будут пиксели цвета верхнего левого угла, если -2 -2 -2, то прозрачности не будет.

Функция уменьшения разрешающей способности изображения:

void Resolution();

Функция уменьшает разрешающую способность путем усреднения групп пикселей 3х3.

Приведем данный алгоритм в псевдокоде:

Создаем временный объект, в который помещаем исходное изображение

Перебираем все пиксели временного изображения

Для каждого подсчитываем сумму каналов цвета его и 8 ближайших соседей

Находим средние значения каналов, при помощи деления сумм на 9

Помещаем полученный цвет в результирующее изображение

Выход

Функция изменения масштаба изображения:

void Zoom(int k);

В функцию передается коэффициент k изменения масштаба, если положительный, то происходит увеличение изображения в k раз, иначе уменьшение в k раз. Если k=0 ничего не происходит.

Алгоритм данной функции рассмотрен в структурном описании программы.

Функция заливки:

void FloodFill(int x, int y, int rz, int gz, int bz);

В функцию передаются координаты начальной точки заливки x,y и три значения rz,gz,bz цвета в формате RGB, которым будет заполнена область, которая содержит точку с координатами x,y и имеющая цвет этой точки.

Ниже приведен псевдокод алгоритма «заливки», использующего очередь для хранения непроверенных «соседей»:

Заливка (элемент, заменяемый цвет, цвет заливки):

Присвоить Q пустую очередь.

Если цвет элемента - не заменяемый цвет, выход.

Поместить элемент в конец Q.

До тех пор, пока Q не пуста:

Присвоить n первый элемент Q

Если цвет n - заменяемый цвет, установить его в цвет заливки.

Взять первый элемент из Q

Если цвет элемента к западу от n - заменяемый цвет:

Установить цветом этого элемента цвет заливки

Поместить этот элемент в конец Q

То же самое для остальных соседей

Выход.

Функция изменения изображения, уменьшающей линзой:

void Lens(int x, int y, int r, int k);

В функцию передаются координаты центра линзы x,y, значение её радиуса r и коэффициент уменьшения k.

Выполняется процедура искажения заданного круга с центром с координатами x,y и радиусом r, эффектом линзы. Процесс искажения реализуется следующим образом: каждой координате данного круга дается приращение по двум направлениям. Приведем фрагмент программы:

for(i = -ro; i <= ro; i++)// перебор всех точек круга

{

int ogr = sqrt((float)(ro*ro - i*i));

for(int j = -ogr; j <= ogr; j++)

{

yy = -k*sin(3.14*i/(2*ro));// искажение по y

xx = -k*sin(3.14*j/(2*abs(ogr)));// искажение по x

// если точка с новыми координатами не вышла за гравницу круга, рисуем её

if(abs(i + yy) < ro && abs(j + xx) < abs(ogr))

{

// считываем цвет точки со старыми координатами

TMP.GetPixel(x + j, y + i, r, g, b);

// записываем пиксель на новое место

PutPixelRGB(x + j + xx, y + i + yy, *r, *g, *b);

}}}

3.2 Класс QUEUE и вложенный класс NODE

Класс QUEUE представляет собой структуру данных, в которой реализован двусвязный список

3.2.1 Данные класса очередь и класса элемента очереди

int x, y - элементы класса node, предназначенные для хранения координат пикселя

node *next - элемент класса node, указывает на следующий элемент в очереди

node *prev - элемент класса node, указывает на предыдущий элемент в очереди

int sz - элемент класса QUEUE, предназначенный для хранения текущего количество элементов в очереди

node *beg, *end - элемент класса QUEUE, указывают на начало и конец очереди

3.2.2 Методы класса QUEUE

Функция, возвращающая размер очереди:

int Size();

Функция возвращает количество элементов очереди.

Функция, помещающая элемент в очередь:

void Push(int x1, int y1);

В функцию передаются два значения (координаты пиксела) x1, y1, которые помещаются в виде одного элемента в конец очереди.

Функция, изымающая элемент из очереди:

void Pop(int *x1, int *y1)

Функция возвращает два значения (координаты пиксела) x1, y1, которые являются значениями первого элемента в очереди. Данный элемент из очереди удаляется.

4. Описание работы программы на контрольных примерах

Для описания работы программы, определения производительности и чувствительности к данным протестируем ее основные методы работы с изображением, затратные по времени, а точнее: уменьшение разрешающей способности, загрузка изображения из двоичного файла, увеличение размера изображения (метод масштабирования с положительным коэффициентом).

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

4.1 Загрузка изображения из двоичного файла

Таблица 4.1

Количество точек изображения

Время работы

2250000

16

4000000

47

6250000

63

9000000

94

12250000

110

16000000

156

20250000

188

Рис.4.1

4.2 Уменьшение разрешающей способности

Таблица 4.2

Количество точек изображения

Время работы

250000

203

1000000

828

2250000

1781

4000000

3172

6250000

4968

9000000

7156

12250000

9750

16000000

12656

20250000

16093

Рис.4.2

Таблица 4.3

Количество точек изображения

Количество сравнений

250000

3000000

1000000

12000000

2250000

27000000

4000000

48000000

6250000

75000000

9000000

108000000

12250000

147000000

16000000

192000000

20250000

243000000

Рис. 4.3

4.3 Увеличение размера изображения

Таблица 4.4

Коэффициент увеличения изображения

Время работы

2

125

3

265

4

406

5

578

6

843

7

1141

8

1484

Рис.4.4

Таблица 4.5

Коэффициент увеличения изображения

Количество сравнений

2

1000000

3

2250000

4

4000000

5

6250000

6

9000000

7

12250000

8

16000000

Рис.4.5

4.4 Выводы

Из приведённых таблиц и графиков, видно, что экспериментальные зависимости практически согласуются с теоретическими сведениями, а именно:

· При увеличении количества точек изображения пропорционально увеличивается количество массовых операций (в данных примерах сравнений) в программе (см. рис. 4.3, 4.5).

· Также при увеличении количества точек линейно растет «грязное» время (время с учетом всех других работ, выполняющихся в операционной системе) работы программы (см. рис. 4.1, 4.2, 4.4).

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

графический формат изображение загрузка

5. Приложение

Исходный текст программы:

Файл main.cpp

#include "BMP.h";

#include "conio.h"

#include <iostream>

#include <clocale>

void main()

{

setlocale( LC_ALL, "rus" );

// корректная работа с русским текстом

BMP *IMG1, *IMG2;

long H, W;

char name[200];

int *r = new int, *g = new int, *b = new int, *w = new int, *h = new int;

int rz, gz, bz;

int x1, y1, x2, y2, x3, y3, x4, y4;

int val;

printf(" 1 - Создать изображение\n");

printf(" 2 - Открыть изображение\n Введите номе операции:");

scanf("%d", &val);

if(val == 1)

{

printf(" Введите размеры нового изображения :");

scanf("%d %d", &H, &W);

IMG1 = new BMP(H, W);

}

if(val == 2)

{

printf(" Введите имя файла, загружаемого изображения :");

scanf("%s", name);

IMG1 = new BMP(name);

}

system("cls"); // очистка экрана

if( val == 1 || val == 2)

{

do

{

printf(" 1 - Загрузить изображение\n");

printf(" 2 - Сохранить изображение\n");

printf(" 3 - Получить размер файла изображения\n");

printf(" 4 - Получить размеры изображения\n");

printf(" -----------------------------------------\n");

printf(" 5 - Нарисовать точку\n");

printf(" 6 - Нарисовать линию\n");

printf(" 7 - Нарисовать окружность\n");

printf(" 8 - Нарисовать четырёхугольник\n");

printf(" 9 - Нарисовать треугольник\n");

printf(" 10 - Нарисовать закрашенный прямоугольник\n");

printf(" 11 - Получить цвет точки\n");

printf(" -----------------------------------------\n");

printf(" 12 - Изменение яркости\n");

printf(" 13 - Изменение контрастности\n");

printf(" 14 - Наложение другого изображения\n");

printf(" 15 - Уменьшение разрешающей способности\n");

printf(" 16 - Масштабирование\n");

printf(" 17 - Заливка\n");

printf(" 18 - Искажение изображения. Эффект линзы\n");

printf(" -----------------------------------------\n");

printf(" 0 - Выход\n");

printf("\n==========================================\n");

printf(" Введите номер операции :");

scanf("%d", &val);

switch(val)

{

case 1:

{

printf(" Введите имя файла, загружаемого изображения :");

scanf("%s", name);

if(IMG1->Load(name))printf("Изображение загружено");

else printf("Нет данного файла или его формат не подходит!");

getch();

};break;

case 2:

{

printf(" Введите имя файла, сохраняемого изображения :");

scanf("%s", name);

IMG1->Save(name);

};break;

case 3:

{

printf("Размер файла изображения %d В", IMG1->FileSize());

getch();

}break;

case 4:

{

IMG1->Dimensions(w, h);

printf(" Размер изображения %d x %d", *w, *h);

getch();

};break;

case 5:

{

printf(" Введите координаты точки: ");

scanf("%d %d", w, h);

printf(" Введите цвет в формате R G B:");

scanf("%d %d %d", r, g , b);

IMG1->PutPixelRGB(*w, *h, *r, *g, *b);

};break;

case 6:

{

printf(" Введите координаты начала: ");

scanf("%d %d", &x1, &y1);

printf(" Введите координаты конца: ");

scanf("%d %d", &x2, &y2);

printf(" Введите цвет:\n0 - черный\n1 - белый\n2 - синий\n3 - зелёный\n4 - красный\n5 - пурпурный\n6 - желтый\n7 - циановый\n");

scanf("%d", r);

IMG1->DrawLine(x1, y1, x2, y2, *r);

};break;

case 7:

{

printf(" Введите координаты центра окружности: ");

scanf("%d %d", &x1, &y1);

printf(" Введите радиус окружности: ");

scanf("%d", r);

printf(" Введите цвет:\n0 - черный\n1 - белый\n2 - синий\n3 - зелёный\n4 - красный\n5 - пурпурный\n6 - желтый\n7 - циановый\n");

scanf("%d", b);

IMG1->DrawCircle(x1, y1, *r, *b);

};break;

case 8:

{

printf(" Введите координаты первой вершины: ");

scanf("%d %d", &x1, &y1);

printf(" Введите координаты второй вершины: ");

scanf("%d %d", &x2, &y2);

printf(" Введите координаты третий вершины: ");

scanf("%d %d", &x3, &y3);

printf(" Введите координаты четвертой вершины: ");

scanf("%d %d", &x4, &y4);

printf(" Введите цвет:\n0 - черный\n1 - белый\n2 - синий\n3 - зелёный\n4 - красный\n5 - пурпурный\n6 - желтый\n7 - циановый\n");

scanf("%d", r);

IMG1->DrawQuadrangle(x1, y1, x2, y2, x3, y3, x4, y4, *r);

};break;

case 9:

{

printf(" Введите координаты первой вершины: ");

scanf("%d %d", &x1, &y1);

printf(" Введите координаты второй вершины: ");

scanf("%d %d", &x2, &y2);

printf(" Введите координаты третий вершины: ");

scanf("%d %d", &x3, &y3);

printf(" Введите цвет:\n0 - черный\n1 - белый\n2 - синий\n3 - зелёный\n4 - красный\n5 - пурпурный\n6 - желтый\n7 - циановый\n");

scanf("%d", r);

IMG1->DrawTriangle(x1, y1, x2, y2, x3, y3, *r);

};break;

case 10:

{

printf(" Введите координаты верхнего левого угла: ");

scanf("%d %d", &x1, &y1);

printf(" Введите координаты нижнего правого угла: ");

scanf("%d %d", &x2, &y2);

printf(" Введите цвет в формате R G B:( если значение равно -1,");

printf(" то исходная компонента цвета не изменяется)");

scanf("%d %d %d", r, g, b);

IMG1->QuadrangleRGB(x1, y1, x2, y2, *r, *g, *b);

};break;

case 11:

{

printf(" Введите координаты точки: ");

scanf("%d %d", &x1, &y1);

if(IMG1->GetPixel(x1, y1, r, g, b))printf(" Цвет точки с координатами (%d, %d) в формате R G B: %d %d %d", x1, y1, *r, *g, *b);

else printf(" Точки с данными координатами на рисунке нет!");

getch();

};break;

case 12:

{

printf(" Введите коеффициент изменения яркости (-255 < k < 255):");

scanf("%d", &x1);

IMG1->Bright(x1);

};break;

case 13:

{

printf(" Введите коеффициент изменения контрастности (-100 < k < 100):");

scanf("%d", &x1);

IMG1->Contrast(x1);

};break;

case 14:

{

printf(" Введите имя файла с изображением, которое будет накладываться :");

scanf("%s", name);

IMG2 = new BMP(100, 100);

if(IMG2->Load(name))

{

printf(" Введите координаты верхнего левого угла накладываемого ");

printf(" изображения в исходном изображении:");

scanf("%d %d", &x1, &y1);

printf(" Введите цвет, который будет прозрачным, у накладываемого изображения в формате R G B:");

printf(" Если ввести -1 -1 -1, то прозрачными будут пиксели цвета верхнего левого угла,");

printf(" если -2 -2 -2, то прозрачности не будет :");

scanf("%d %d %d", r, g , b);

IMG1->Imposition(*IMG2, x1, y1, *r, *g, *b);

}

else printf("Нет данного файла или его формат не подходит!");

delete IMG2;

getch();

};break;

case 15:

{

printf(" Уменьшение разрешающей способности путем\n");

printf(" усреднения групп пикселей 3x3 выполнена!");

IMG1->Resolution();

getch();

};break;

case 16:

{

printf(" Введите коеффициент масштабирования: при уменьшении k < 0,");

printf(" при увеличении масштаба k > 0 (k - целое): ");

scanf("%d", &x1);

IMG1->Zoom(x1);

};break;

case 17:

{

printf(" Введите координаты точки, принадлежащей\n");

printf(" области, которую нужно закрасить :");

scanf("%d %d", w, h);

printf(" Введите цвет заливки в формате R G B:");

scanf("%d %d %d", &rz, &gz , &bz);

IMG1->FloodFill(*w, *h, rz, gz, bz);

};break;

case 18:

{

printf(" Введите координаты центра линзы: ");

scanf("%d %d", &x1, &y1);

printf(" Введите радиус линзы: ");

scanf("%d", r);

printf(" Введите коэффициент уменьшения:");

scanf("%d", b);

IMG1->Lens(x1, y1, *r, *b);

};break;

}

system("cls"); // очистка экрана

}

while(val != 0);

}

delete IMG1;}

Файл BMP.h:

#include <fstream>

using namespace std;

typedef short WORD;

typedef unsigned DWORD;

typedef long LONG;

typedef unsigned char BYTE;

class BMP

{

// ДАННЫЕ О ФАЙЛЕ

WORD bfType; // тип файла, символы "BM"

DWORD bfSize; // размер всего файла в байтах

WORD bfReserved1;

WORD bfReserved2;

// зарезервированные, должны содержать нули

DWORD bfOffBits; // содержит смещение в байтах от //начала заголовка до битов изображения

// ДАННЫЕ О ИЗОБРАЖЕНИИ

DWORD biSize; // размер структуры данных о изображении

LONG biWidth; // ширина изображения в пикселах

LONG biHeight; // высота изображения в пикселах

WORD biPlanes; // число плоскостей, равно 1

WORD biBitCount;

// указывает количество бит на пиксель.

DWORD biCompression;

// тип сжатия. Если рано BI_RGB, то палитра не используется

DWORD biSizeImage;

// 0 или размер сжатого изображения в байтах

LONG biXPelsPerMet;

// Горизонтальное разрешение, пиксел/м

LONG biYPelsPerMet;

// Вертикальное разрешение, пиксел/м

DWORD biClrUsed; // Количество используемых цветов

DWORD biClrImportant;// Количество "важных" цветов

// ИНФОРМАЦИЯ О ПИКСЕЛЯХ

BYTE **MBMP;

// массив указателей на пиксели изображения

void Col_To_RGB(int col, int* red, int* green, int* blue); // перевод цвета

public:

BMP(const BMP &M);

// конструктор копирования

BMP(char FileNames[]);

// конструктор с параметром строкой(имя графического фйла)

BMP(long H, long W); // конструктор с размером нового изображения

~BMP(); // деструктор

BMP* Copy();

// создание копии объекта (клонирование)

int Load(char FileNames[]);

// чтение изображения из файла

void Save(char FileNames[]);

// запись изображения в файла

unsigned FileSize(); // размер файла

void Dimensions(int *W, int *H);// размеры изображения

int PutPixel(int x, int y, int color);

// нарисовать пиксель

int GetPixel(int x, int y, int *red, int *green, int *blue); // взять цвет пикселя

int PutPixelRGB(int x, int y, int red, int green, int blue); // нарисовать пиксель, задавая цвет в формате RGB

int DrawLine(int x1, int y1, int x2, int y2, int color); // нарисовать линию

int DrawQuadrangle(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int color);

// нарисовать четырёхугольник

int DrawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color); // нарисовать треугольник

int DrawCircle(int x0, int y0, int radius, int color); // нарисовать окружности

void Bright(int x);

// изменение яркости -255 < x < 255

void Contrast(int e);

// изменение контрастности -100 < e < 100

void QuadrangleRGB(int x1, int y1, int x2, int y2, int rr, int gg, int bb); // изменение цвета прямоугольника

void Imposition(BMP &T, int x, int y, int r, int g, int b); // наложение изображений с прозрачностью цвета rgb

void Resolution(); // уменьшение разрешающей способности

void Zoom(int k); // масштабирования

void FloodFill(int x, int y, int rz, int gz, int bz); // заливка

void Lens(int x, int y, int r, int k); // эффект линзы

};

Файл BMP.cpp:

#include "BMP.h"

#include "math.h"

#include "queue.h"

BMP::BMP(const BMP &M) // конструктор копирования

{

bfType = M.bfType;

bfSize = M.bfSize;

bfReserved1 = M.bfReserved1;

bfReserved2 = M.bfReserved2;

bfOffBits = M.bfOffBits;

biSize = M.biSize;

biWidth = M.biWidth;

biHeight = M.biHeight;

biPlanes = M.biPlanes;

biBitCount = M.biBitCount;

biCompression = M.biCompression;

biSizeImage = M.biSizeImage;

biXPelsPerMet = M.biXPelsPerMet;

biYPelsPerMet = M.biYPelsPerMet;

biClrUsed = M.biClrUsed;

biClrImportant = M.biClrImportant;

int sz_line = biWidth * 3;

while(sz_line % 4 != 0) sz_line++;

// выравнивание до СЛОВА (кратно 4)

MBMP = new BYTE *[biHeight];

for(int i = 0; i < biHeight; i++)

{

MBMP[i] = new BYTE[sz_line];

for(int j = 0; j < sz_line; j++)MBMP[i][j] = M.MBMP[i][j];

}

}

BMP::BMP(char FileNames[])

// конструктор с параметрок строкой(имя графического файла)

{

bfType = 19778;

bfSize = 0;

bfReserved1 = 0;

bfReserved2 = 0;

bfOffBits = 54;

biSize = 40;

biWidth = 0;

biHeight = 0;

biPlanes = 1;

biBitCount = 24;

biCompression = 0;

biSizeImage = 0;

biXPelsPerMet = 0;

biYPelsPerMet = 0;

biClrUsed = 0;

biClrImportant = 0;

MBMP = NULL;

Load(FileNames);

}

BMP::BMP(long H, long W)

// конструктор создания пустого(белого) изображения

{

bfType = 19778;

bfSize = H * W * 3 + 54;

bfReserved1 = 0;

bfReserved2 = 0;

bfOffBits = 54;

biSize = 40;

biWidth = W;

biHeight = H;

biPlanes = 1;

biBitCount = 24;

biCompression = 0;

biSizeImage = H * W * 3;

biXPelsPerMet = 0;

biYPelsPerMet = 0;

biClrUsed = 0;

biClrImportant = 0;

int sz_line = biWidth * 3;

while(sz_line % 4 != 0) sz_line++;

// выравнивание до СЛОВА (кратно 4)

MBMP = new BYTE *[biHeight];

for(int i = 0; i < biHeight; i++)

{

MBMP[i] = new BYTE[sz_line];

for(int j = 0; j < sz_line; j++)MBMP[i][j] = 255;

}

}

BMP::~BMP()

// деструктор

{

for(int i = 0; i < biHeight; i++)

delete MBMP[i];

delete MBMP;

MBMP = NULL;

}

BMP* BMP::Copy()// создание копии объекта (клонирование)

{

return new BMP(*this);

}

int BMP::Load(char FileNames[])

// загрузка изображения из файла

{

// ВРЕМЕННЫЕ ДАННЫЕ О ФАЙЛЕ

WORD bfTypet;

DWORD bfSizet;

WORD bfReserved1t;

WORD bfReserved2t;

DWORD bfOffBitst;

// ВРЕМЕННЫЕ ДАННЫЕ О ИЗОБРАЖЕНИИ

DWORD biSizet;

LONG biWidtht;

LONG biHeightt;

WORD biPlanest;

WORD biBitCountt;

DWORD biCompressiont;

DWORD biSizeImaget;

LONG biXPelsPerMett;

LONG biYPelsPerMett;

DWORD biClrUsedt;

DWORD biClrImportantt;

fstream F;

F.open(FileNames, ios::in | ios::binary);

// Двоичный для чтения

// ЧТЕНИЕ ДАННЫХ О ФАЙЛЕ

F.read((char*)&bfTypet,sizeof(WORD));

F.read((char*)&bfSizet,sizeof(DWORD));

F.read((char*)&bfReserved1t,sizeof(WORD));

F.read((char*)&bfReserved2t,sizeof(WORD));

F.read((char*)&bfOffBitst,sizeof(DWORD));

// ЧТЕНИЕ ДАНННЫХ О ИЗОБРАЖЕНИИ

F.read((char*)&biSizet,sizeof(DWORD));

F.read((char*)&biWidtht,sizeof(LONG));

F.read((char*)&biHeightt,sizeof(LONG));

F.read((char*)&biPlanest,sizeof(WORD));

F.read((char*)&biBitCountt,sizeof(WORD));

F.read((char*)&biCompressiont,sizeof(DWORD));

F.read((char*)&biSizeImaget,sizeof(DWORD));

F.read((char*)&biXPelsPerMett,sizeof(LONG));

F.read((char*)&biYPelsPerMett,sizeof(LONG));

F.read((char*)&biClrUsedt,sizeof(DWORD));

F.read((char*)&biClrImportantt,sizeof(DWORD));

if(biBitCountt == 24)

{

this->~BMP(); // удаление предыдущих значений

// ЗАПИСЬ НОВЫХ ЗНАЧЕНИЙ

bfType = bfTypet;

bfSize = bfSizet;

bfReserved1 = bfReserved1t;

bfReserved2 = bfReserved2t;

bfOffBits = bfOffBitst;

biSize = biSizet;

biWidth = biWidtht;

biHeight = biHeightt;

biPlanes = biPlanest;

biBitCount = biBitCountt;

biCompression = biCompressiont;

biSizeImage = biSizeImaget;

biXPelsPerMet = biXPelsPerMett;

biYPelsPerMet = biYPelsPerMett;

biClrUsed = biClrUsedt;

biClrImportant = biClrImportantt;

// чтение данных о пикселях

int sz_line = biWidth * 3;

while(sz_line % 4 != 0) sz_line++;

// выравнивание до СЛОВА (кратно 4)

MBMP = new BYTE *[biHeight];

for(int i = 0; i < biHeight; i++)

{

MBMP[i] = new BYTE[sz_line];

F.read((char*)MBMP[i], sz_line);

}

F.close();

return 1;

}

F.close();

return 0;

}

void BMP::Save(char FileNames[])

// сохранение изображение в файл

{

fstream F;

F.open(FileNames, ios::out | ios::binary);

// Двоичный для записи

// ЗАПИСЬ ДАННЫХ О ФАЙЛЕ

F.write((char*)&bfType,sizeof(WORD));

F.write((char*)&bfSize,sizeof(DWORD));

F.write((char*)&bfReserved1,sizeof(WORD));

F.write((char*)&bfReserved2,sizeof(WORD));

F.write((char*)&bfOffBits,sizeof(DWORD));

// ЗАПИСЬ ДАНННЫХ О ИЗОБРАЖЕНИИ

F.write((char*)&biSize,sizeof(DWORD));

F.write((char*)&biWidth,sizeof(LONG));

F.write((char*)&biHeight,sizeof(LONG));

F.write((char*)&biPlanes,sizeof(WORD));

F.write((char*)&biBitCount,sizeof(WORD));

F.write((char*)&biCompression,sizeof(DWORD));

F.write((char*)&biSizeImage,sizeof(DWORD));

F.write((char*)&biXPelsPerMet,sizeof(LONG));

F.write((char*)&biYPelsPerMet,sizeof(LONG));

F.write((char*)&biClrUsed,sizeof(DWORD));

F.write((char*)&biClrImportant,sizeof(DWORD));

// запись данных о пикселях

int sz_line = biWidth * 3;

while(sz_line % 4 != 0) sz_line++;

// выравнивание до СЛОВА (кратно 4)

for(int i = 0; i < biHeight; i++)

{

F.write((char*)MBMP[i], sz_line);

}

F.close();

}

unsigned BMP::FileSize()// размер файла

{

return bfSize;

}

void BMP::Dimensions(int *W, int *H)// размеры изображения

{

*W = biWidth;

*H = biHeight;

}

void BMP::Col_To_RGB(int col, int* red, int* green, int* blue) // перевод цвета

{

switch (col)

{

case 0: {*red = 0; *green = 0; *blue = 0;}break;

// черный

case 1: {*red = 255; *green = 255; *blue = 255;}break;

// белый

case 2: {*red = 0; *green = 0; *blue = 255;}break; // синий

case 3: {*red = 0; *green = 255; *blue = 0;}break; // зеленый

case 4: {*red = 255; *green = 0; *blue = 0;}break; // красный

case 5: {*red = 255; *green = 0; *blue = 255;}break; // пурпурный

case 6: {*red = 255; *green = 255; *blue = 0;}break; // желтый

case 7: {*red = 0; *green = 255; *blue = 255;}break; // циановый

default :{*red = 255; *green = 255; *blue = 255;};

}

}

int BMP::PutPixel(int x, int y, int color) // нарисовать пиксель

{

if(x < biWidth && y < biHeight)

{

int *r = new int, *g = new int, *b = new int;

Col_To_RGB(color, r, g, b);

MBMP[biHeight - y - 1][x*3] = *b;

MBMP[biHeight - y - 1][x*3 + 1] = *g;

MBMP[biHeight - y - 1][x*3 + 2] = *r;

return 1;

}

return 0;

}

int BMP::GetPixel(int x, int y, int *red, int *green, int *blue) // взять цвет пикселя

{

if(x <= biWidth && y <= biHeight && x >= 0 && y >= 0)

{

*blue = MBMP[biHeight - y - 1][x*3];

*green = MBMP[biHeight - y - 1][x*3 + 1];

*red = MBMP[biHeight - y - 1][x*3 + 2];

return 1;

}

return 0;

}

int BMP::PutPixelRGB(int x, int y, int red, int green, int blue) // нарисовать пиксель задавая цвет в формате RGB

{

if(x < biWidth && y < biHeight && x >= 0 && y >= 0)

{

MBMP[biHeight - y - 1][x*3] = blue;

MBMP[biHeight - y - 1][x*3 + 1] = green;

MBMP[biHeight - y - 1][x*3 + 2] = red;

return 1;

}

return 0;

}

int BMP::DrawLine(int x1, int y1, int x2, int y2, int color) // нарисовать линию

{

if(x1 <= biWidth && x1 >= 0 && y1 <= biHeight && y1 >= 0 && x2 <= biWidth && x2 >= 0 && y2 <= biHeight && y2 >= 0)

{

int deltaX = abs(x2 - x1);

int deltaY = abs(y2 - y1);

int signX = x1 < x2 ? 1 : -1;

int signY = y1 < y2 ? 1 : -1;

int error = deltaX - deltaY;

while(1)

{

PutPixel(x1, y1, color);

if(x1 == x2 && y1 == y2)

return 1;

int error2 = error * 2;

if(error2 > -deltaY)

{

error -= deltaY;

x1 += signX;

}

if(error2 < deltaX)

{

error += deltaX;

y1 += signY;

}

}

}

return 0;

}

int BMP::DrawQuadrangle(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int color) // четырёхугольник

{

if(x1<=biWidth && x1>=0 && y1<=biHeight && y1>=0 && x2<=biWidth && x2>=0 && y2<=biHeight && y2>=0 && x3<=biWidth && x3>=0 && y3<=biHeight && y3>=0 && x4<=biWidth && x4>=0 && y4<=biHeight && y4>=0)

{

DrawLine(x1, y1, x2, y2, color);

DrawLine(x2, y2, x3, y3, color);

DrawLine(x3, y3, x4, y4, color);

DrawLine(x4, y4, x1, y1, color);

return 1;

}

return 0;

}

int BMP::DrawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color) // треугольник

{

if(x1<=biWidth && x1>=0 && y1<=biHeight && y1>=0 && x2<=biWidth && x2>=0 && y2<=biHeight && y2>=0 && x3<=biWidth && x3>=0 && y3<=biHeight && y3>=0)

{

DrawLine(x1, y1, x2, y2, color);

DrawLine(x2, y2, x3, y3, color);

DrawLine(x3, y3, x1, y1, color);

return 1;

}

return 0;

}

int BMP::DrawCircle(int x0, int y0, int radius, int color) // рисование окружности

{

if(x0 < biWidth && y0 < biHeight)

{

int x = 0;

int y = radius;

int delta = 2 - 2 * radius;

int error = 0;

while(y >= 0)

{

PutPixel(x0 + x, y0 + y, color);

PutPixel(x0 + x, y0 - y, color);

PutPixel(x0 - x, y0 + y, color);

PutPixel(x0 - x, y0 - y, color);

error = 2 * (delta + y) - 1;

if(delta < 0 && error <= 0)

{

++x;

delta += 2 * x + 1;

continue;

}

error = 2 * (delta - x) - 1;

if(delta > 0 && error > 0)

{

--y;

delta += 1 - 2 * y;

continue;

}

++x;

delta += 2 * (x - y);

--y;

}

return 1;

}

return 0;

}

void BMP::Bright(int x) // изменение яркости

{

for(int i = 0; i < biHeight; i++)

for(int j = 0; j < biWidth*3; j++)

{

if(MBMP[i][j] - x > 255)MBMP[i][j] = 255;

else if(MBMP[i][j] - x < 0)MBMP[i][j] = 0;

else MBMP[i][j] = MBMP[i][j] - x;

}

}

void BMP::Contrast(int e) // изменение контрастности

{

float Y0 = 0; // средняя яркость

float k = 1 + e*0.01; // коэффициент

// вычисляется средняя яркость

for(int i = 0; i < biHeight; i++)

for(int j = 0; j < biWidth*3; j = j + 3)

Y0 += MBMP[i][j] * 0.114 + MBMP[i][j + 1] * 0.587 + MBMP[i][j + 2] * 0.299;

Y0 = Y0/(biWidth*biHeight);

// изменение цветов пикселей

for(int i = 0; i < biHeight; i++)

for(int j = 0; j < biWidth*3; j++)

if(Y0 + k * (MBMP[i][j] - Y0) > 255)MBMP[i][j] = 255;

else if(Y0 + k * (MBMP[i][j] - Y0) < 0)MBMP[i][j] = 0;

else MBMP[i][j] = Y0 + floor(k * (MBMP[i][j] - Y0));

}

void BMP::QuadrangleRGB(int x1, int y1, int x2, int y2, int rr, int gg, int bb) // изменение цвета прямоугольника

{

if(x1>biWidth || x1<0 || y1>biHeight || y1<0 || x2>biWidth || x2<0 || y2>biHeight || y2<0)return;

if(rr > 255)rr = 255;

if(gg > 255)gg = 255;

if(bb > 255)bb = 255;

int *r = new int, *g = new int, *b = new int;

for(int i = y1; i < y2; i++)

for(int j = x1; j < x2; j++)

{

GetPixel(j, i, r, g, b);

if(rr > -1)*r = rr;

if(gg > -1)*g = gg;

if(bb > -1)*b = bb;

PutPixelRGB(j, i, *r, *g, *b);

}

}

void BMP::Imposition(BMP &T, int x, int y, int r, int g, int b) // наложение изображений с прозрачностью цвета rgb

{

int *rr = new int, *gg = new int, *bb = new int, *w = new int, *h = new int;

T.Dimensions(w, h);

// получить размерность изображения параметра

if(r == -1 && g == -1 && b == -1)

// прозрачными будут пиксели цвета верхнего левого угла

{

T.GetPixel(0, 0, rr, gg, bb);

// получаем цвет левого верхнего угла

r = *rr; g = *gg; b = *bb;

}

for(int i = y; i < *h + y && i < biHeight; i++)

// перебираем все пиксели накладываемого изображения

for(int j = x; j < *w + x && j < biWidth; j++)

{

T.GetPixel(j - x, i - y, rr, gg, bb);

if((r == -2 && g == -2 && b == -2) || (*rr != r || *gg != g || *bb != b))PutPixelRGB(j, i, *rr, *gg, *bb);// если не прозрачный, то рисуем

}

}

void BMP::Resolution()

// уменьшение разрешающей способности

{

// весовая маска

int maska[3][3] = {{1,1,1},{1,1,1},{1,1,1}};

int *r = new int, *g = new int, *b = new int;

int sr, sg, sb;

BMP TMP(*this);// создание временного изображения

for(int i = 0; i < TMP.biHeight; i++)

// перебор всех пикселей изображения

for(int j = 0; j < TMP.biWidth; j++)

{

sr = 0; sg = 0; sb = 0;

// обнуление суммы значений цветов пикселей

for(int k1 = -1; k1 <= 1; k1++)

// подсчитывание для каждого матрицу

for(int k2 = -1; k2 <= 1; k2++)

if(j+k2 < biWidth && i+k1 < biHeight && i+k1 >= 0 && j+k2 >= 0)

{

TMP.GetPixel(j + k2, i + k1, r, g, b);

*r = *r * maska[1 + k1][1 + k2];

*g = *g * maska[1 + k1][1 + k2];

*b = *b * maska[1 + k1][1 + k2];

sr+= *r; sg+= *g; sb+= *b;

}

// вычисление средних значений каналов цвета

sr = sr/9;

sg = sg/9;

sb = sb/9;

if(sr > 255)sr = 255;

if(sg > 255)sg = 255;

if(sb > 255)sb = 255;

PutPixelRGB(j, i, sr, sg, sb);

// помещение нового значения в результирующее изображение

}

}

void BMP::Zoom(int k) // масштабирование

{

int *r = new int, *g = new int, *b = new int, end;

if(k > 1)

{

BMP TMP(*this);// создание временного изображения

this->~BMP();

// задание новых размеров и изменение данных о изображении

biWidth = biWidth * k;

biHeight = biHeight * k;

bfSize = biHeight * biWidth * 3 + 54;

biSizeImage = biHeight * biWidth * 3;

int sz_line = biWidth * 3;

while(sz_line % 4 != 0) sz_line++;

// выравнивание до СЛОВА (кратно 4)

MBMP = new BYTE *[biHeight];

for(int i = 0; i < biHeight; i++)

{

MBMP[i] = new BYTE[sz_line];

for(int j = 0; j < sz_line; j++)MBMP[i][j] = 255;

}

// перебор всех пикселей изображения

for(int i = 0; i < TMP.biHeight; i++)

for(int j = 0; j < TMP.biWidth; j++)

{

TMP.GetPixel(j, i, r, g, b);

for(int k1 = 0; k1 < k; k1++)

for(int k2 = 0; k2 < k; k2++)

PutPixelRGB(j*k + k1, i*k + k2, *r, *g, *b);

}

return;

}

if(k < 0)

{

BMP TMP(*this);// создание временного изображения

this->~BMP();

// задание новых размеров и изменение данных о изображении

biWidth = biWidth / -k;

biHeight = biHeight / -k;

bfSize = biHeight * biWidth * 3 + 54;

biSizeImage = biHeight * biWidth * 3;

int sz_line = biWidth * 3;

while(sz_line % 4 != 0) sz_line++;

// выравнивание до СЛОВА (кратно 4)

MBMP = new BYTE *[biHeight];

for(int i = 0; i < biHeight; i++)

{

MBMP[i] = new BYTE[sz_line];

for(int j = 0; j < sz_line; j++)MBMP[i][j] = 255;

}

// перебор всех пикселей изображения

int sr, sg, sb;

for(int i = 0; i < biHeight; i++)

for(int j = 0; j < biWidth; j++)

{

if(-k % 2 == 0)end = -k/2;

else end = -k/2 + 1;

sr = 0; sg = 0; sb = 0;

// обнуление суммы значений цветов пикселей

for(int k1 = k/2; k1 < end; k1++)

for(int k2 = k/2; k2 < end; k2++)

if(-j*k+k2 < TMP.biWidth && -i*k+k1 < TMP.biHeight && -i*k+k1 >= 0 && -j*k+k2 >= 0)

{

TMP.GetPixel(-j*k + k2, -i*k + k1, r, g, b);

sr+= *r; sg+= *g; sb+= *b;

}

sr = sr/(k*k);

sg = sg/(k*k);

sb = sb/(k*k);

if(sr > 255)sr = 255;

if(sg > 255)sg = 255;

if(sb > 255)sb = 255;

PutPixelRGB(j, i, sr, sg, sb);

// помещаем новое значение в результирующую матрицу

}

return;

}

}

void BMP::FloodFill(int x, int y, int rz, int gz, int bz) // заливка

{

QUEUE Q;

int *rn = new int, *gn = new int, *bn = new int;

GetPixel(x, y, rn, gn, bn);// заменяемый цвет

int *xx = new int, *yy = new int, *r = new int, *g = new int, *b = new int;

Q.Push(x, y); // поместить в очередь

PutPixelRGB(x, y, rz, gz, bz);

while(Q.Size() != 0)

{

Q.Pop(xx, yy);// изъять из очереди

// пиксель слева

if(GetPixel(*xx - 1, *yy, r, g ,b))// если этот //цвет заменяемый, то установить его в цвет заливки

if(*r == *rn && *g == *gn && *b == *bn)

{

PutPixelRGB(*xx - 1, *yy, rz, gz, bz);

Q.Push(*xx - 1, *yy);

}

// пиксель справа

if(GetPixel(*xx + 1, *yy, r, g ,b))// если этот //цвет заменяемый, то установить его в цвет заливки

if(*r == *rn && *g == *gn && *b == *bn)

{

PutPixelRGB(*xx + 1, *yy, rz, gz, bz);

Q.Push(*xx + 1, *yy);

}

// пиксель сверху

if(GetPixel(*xx, *yy - 1, r, g ,b))// если этот //цвет заменяемый, то установить его в цвет заливки

if(*r == *rn && *g == *gn && *b == *bn)

{

PutPixelRGB(*xx, *yy - 1, rz, gz, bz);

Q.Push(*xx, *yy - 1);

}

// пиксель снизу

if(GetPixel(*xx, *yy + 1, r, g ,b))// если этот //цвет заменяемый, то установить его в цвет заливки

if(*r == *rn && *g == *gn && *b == *bn)

{

PutPixelRGB(*xx, *yy + 1, rz, gz, bz);

Q.Push(*xx, *yy + 1);

}

}

}

void BMP::Lens(int x, int y, int ro, int k) // эффект линзы

{

BMP TMP(*this); // временное изображение

int *r = new int, *g = new int, *b = new int;

int xx, yy, i;

for(i = -ro; i <= ro; i++)// перебор всех точек круга


Подобные документы

  • Описание этапов создания анимированного GIF изображения мультипликационного героя "Винни-Пуха" в программе Adobe Photoshop CS6. Создание дубликата слоя изображения и подготовка кадров для GIF анимации. Настройка эффектов анимации и результат GIF-файла.

    лабораторная работа [1,2 M], добавлен 05.03.2015

  • Методы кодирования изображения: кодированием длины серии, частотно-зависимое кодирование, метод Лемпеля-Зива. Размер строки при 16-битном цвете. Расчет размера всего исходного изображения. Примеры качественного и некачественного сжатия изображения.

    презентация [2,0 M], добавлен 22.10.2013

  • Компьютерная графика и её виды. Векторный графический редактор CorelDraw. Создание изображения панели осциллографа, разработка наглядного изображения. Особенности графических редакторов, изображение панели осциллографа в программе Adobe Illustrator.

    курсовая работа [4,2 M], добавлен 04.05.2023

  • Разработка программы, предназначенной для сжатия или компрессии полутонового изображения международным стандартом JPEG. Описание метода JPEG, выдача результатов в виде декодированного изображения. Обзор методов компрессии полутонового изображения.

    курсовая работа [43,5 K], добавлен 14.10.2012

  • Описание алгоритма поворота изображения. Вычисление синуса и косинуса угла поворота изображения. Алгоритм и реализация функции поворота изображения вокруг центра на заданный пользователем угол. Проверка на соответствие диапазону допустимых значений.

    курсовая работа [1,3 M], добавлен 23.01.2015

  • Разработка приложения, целью которого ставится преобразование черно-белых полутоновых изображений в цветные. Обзор методики обработки изображения, способов преобразования изображения с помощью нейронной сети. Описания кластеризации цветового пространства.

    дипломная работа [6,3 M], добавлен 17.06.2012

  • Механизм графического представления данных. Виды компьютерной графики: фрактальная, трехмерная, растровая, векторная. Разрешение экранного изображения, понятие линиатуры. Связь между параметрами изображения и размером файла. Динамический диапазон.

    реферат [38,6 K], добавлен 27.12.2012

  • Изучение истории развития компьютерной графики и особенностей её применения. Написание программы, реализующей смещение и поворот изображения на заданный градус по любой из осей координат. Обработка, хранение и передача сканируемых пиксельных изображений.

    практическая работа [361,4 K], добавлен 04.02.2013

  • Компьютерная графика. Пиксели, разрешение, размер изображения. Типы изображений. Черно-белые штриховые и полутоновые изображения. Индексированные цвета. Полноцветные изображения. Форматы файлов. Цвет и его модели. Цветовые модели: RGB, CMYK, HSB.

    реферат [18,1 K], добавлен 20.02.2009

  • Интерфейс программы Adobe Photoshop. Внесение изменений в изображение. Инструменты изменения оттенка и искажения изображения. Последовательность формирования изображения. Тоновая и цветовая коррекция изображения, работа с фильтрами и функциями.

    курсовая работа [2,8 M], добавлен 14.12.2011

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.