Разработка графических форматов

Тип работы:
Дипломная
Предмет:
Программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

1. Описание графического формата файла

1. 1 Описание графического формата GIF

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

1.1. 1 Общие сведения

GIF — формат хранения графических изображений (от англ. GraphicsInterchangeFormat). Формат GIF способен хранить сжатые без потерь изображения в формате до 256 цветов с палитрой, и предназначен, в основном, для чертежей, графиков и т. д. [3].

Независящий от аппаратного обеспечения формат GIF был разработан в 1987 году (GIF87a) фирмой CompuServe для передачи растровых изображений по сетям. В 1989-м формат был модифицирован (GIF89a), были добавлены поддержка прозрачности для создания изображений непрямоугольной формы и анимации. Файл GIF может содержать не одно, а несколько растровых изображений, которые браузеры могут загружать друг за другом с указанной в файле частотой [1].

GIF широко используется в Internet. Формат GIF обладает рядом свойств, определивших его широкое применение при разработке Web-страниц:

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

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

— Анимация. Форматом GIF предусмотрена возможность создания анимированных изображений. Фактически это несколько изображений, записанных в один файл и чередующихся с заданным интервалом времени[4].

Основное ограничение формата GIF состоит в том, что цветное изображение может быть записано только в режиме 256 цветов.

Область применения GIF-файлов ограничивается и применяемым алгоритмом сжатия изображений (LZW-компрессия), чья эффективность зависит от разнообразия цветов в изображении, наличия одноцветных областей. Наибольшую экономию объема файла дают изображения с небольшим количеством цветов и большими одноцветными областями. Поэтому формат GIF широко используется для отображения графических меню и кнопок, а также для создания технических иллюстраций (графики, схемы, диаграммы и т. п.). В то же время использование формата GIF для отображения полноцветных фотографий практически не находит применения по причине малого количества передаваемых цветов и низкой эффективности алгоритма сжатия для таких изображений [1].

1.1. 2 Общая структура файла GIF

Таблица. Общая структура файла представлена на рисунке (см рис. 1. 1).

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

Палитра

Изображение1

ИзображениеN

Признак конца = 3В

Теперь рассмотрим каждый элемент структуры отдельно.

Начнем с заголовка файла. Заголовок файла GIF представлен на рисунке (см рис. 1.2.). В первых трех байтах стоит метка заголовка (`GIF'). За ней следуют 3 байта с уточнением версии GIF. Далее расположен блок размером 7 байтов с описанием логического экрана.

Таблица. Заголовок файла GIF

Название поля

Размер (в байтах)

Примечание

Идентификатор GIF

3

47 49 46 («GIF»)

Номер версии

3

87а или 89а

Ширина

2

Высота

2

Флаг разрешения

1

Цвет фона

1

Специальная информация

1

Количество цветов и прочее

Специальная информация — это информация о том, есть ли глобальная палитра, сколько битов используется для RGB-представления одного цвета в палитре, сколько битов приходится на одну точку изображения (пиксель), определения последовательности высвечивания пикселей. После заголовка идет палитра, которая используется для всех изображений в файле GIF, если у изображения нет собственной палитры. Палитры изображений и глобальная палитра состоят из троек байтов RGB. Обе палитры — локальные и глобальная — не обязательны. После заголовка файла и необязательной глобальной палитры следует изображение — одно или несколько (если есть анимация). Для каждого изображения сначала записывается собственный заголовок (см. рис. 1. 3).

Таблица

Название поля

Размер (в байтах)

Примечание

Признак изображения

1

2Сhили «,» (ASCII) для изображения

Координатылевого края изображ.

2

Координаты верхнего края изображ.

2

Ширина

2

Высота

2

Специальная информация

1

Наличие локальных палитр, прочие локальные параметры изображения

Каждый дескриптор изображения начинается с символа-разделителя изображений. Роль разделителя изображений состоит просто в синхронизации при входе в дескриптор изображения. Это желательно, если GIF-файл состоит более, чем из одного изображения. Этот символ определен как шестнадцатеричное 0x2C или ',' (запятая). Как только этот символ встречается между изображениями, непосредственно за ним следует дескриптор изображения.

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

Далее идет необязательная локальная палитра изображения. Потом записываются данные. Сжатые данные хранятся в виде потока блоков размером меньше 255 байтов. Каждый блок состоит из байта длины блока и, собственно, данных. Когда данные изображения заканчиваются, идет блок нулевой длины.

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

1.1. 3 Сжатие по методу LZW

Данные файлов GIF хранятся в упакованном виде сжатым алгоритмом LZW (Lempel-ZivWelch). LZW — это способ сжатия данных, который извлекает преимущества при повторяющихся цепочках данных. Поскольку растровые данные обычно содержат довольно много таких повторений, LZW является хорошим методом для их сжатия и раскрытия.

Основные понятия:

— «Символ»: фундаментальный элемент данных — индекс, который указывает цвет данного пиксела (K).

— «Цепочка»: несколько последовательных символов. Длина цепочки может изменяться от 1 до очень большого числа символов ([… ]K).

— «Префикс»: префикс непосредственно предшествует символу, может иметь нулевую длину ([… ]).

— «Корень»: односимвольная цепочка ([… ]K, где […] - пуста).

— «Код»: число, определяемое известным количеством бит, которое кодирует цепочку.

— «Поток кодов»: выходной поток кодов, таких как «растровые данные».

— «Элемент»: код и его цепочка.

— «Таблица цепочек»: список элементов обычно, но не обязательно, уникальных.

При сжатии и раскрытии LZW манипулирует тремя объектами: потоком символов, потоком кодов и таблицей цепочек. При сжатии поток символов является входным и поток кодов — выходным. При раскрытии входным является поток кодов, а поток символов — выходным. Таблица цепочек порождается и при сжатии и при раскрытии, однако она никогда не передается от сжатия к раскрытию и наоборот.

Первым, что необходимо сделать при LZW-сжатии, является инициализация цепочки символов. Для этого необходимо выбрать код размера (количество бит), и знать, сколько возможных значений могут принимать символы. Положим код размера равным 12 битам, что означает возможность запоминания 0FFF, или 4096, элементов в таблице цепочек.

Чтобы инициализировать таблицу, установим соответствие кода #0 символу #0, кода #1 to символу #1, и т. д., до кода #31 и символа #31. Т. е. каждый код от 0 до 31 является корневым (больше в таблице не будет других кодов, обладающих этим свойством).

Начнем сжатие данных: определим «текущий префикс» и «текущую цепочку». Префикс изначально ничего не содержит. «Текущая цепочка» («[.c. ]K) образуется текущим префиксом и следующим символом в потоке символов.

Рассмотрим первый символ в потоке символов, назовем его P. Сделаем [.c. ]P текущей цепочкой, выполним поиск в таблице цепочек, чтобы определить входит ли в нее [.c. ]P. Если входит, то ничего не делаем. Затем делаем текущим префикс [.c. ]P.

Берем следующий символ из потока символов — Q, добавим текущий префикс, чтобы сформировать текущую цепочку[.c. ]Q. Выполняем поиск в таблице цепочек, чтобы определить входит ли в нее [.c. ]Q. В данном случае не входит. Добавим [.c. ]Q в таблицу цепочек под кодом #32,и выведем код для [.c.] в поток кодов. Теперь начнем опять с текущего префикса. Продолжаем добавление символов к [.c. ], чтобы сформировать [.c. ]K, до тех пор, пока не сможем найти [.c. ]K в таблице цепочек. Затем выводим код для [.c.] и добавляем [.c. ]K в таблицу цепочек.

Алгоритм компрессии LZW выглядит следующим образом (см. рис. 1. 4):

Рисунок 1.4 — Алгоритм компрессии LZW

1. 2 Описание графического формата ВМР

1.2. 1 Общие сведения

Формат файлов BMP- родной формат Windows. Он поддерживается всеми графическими редакторами, работающими под управлением этой операционной системы. Применяется для хранения растровых изображений, предназначенных для использования в Windows и, по сути, больше ни на что не пригоден. Способен хранить как индексированный (до 256 цветов), так и RGB-цвет (16. 700. 000 оттенков). Возможно применение сжатия по принципу RLE, но делать это не рекомендуется, так как очень многие программы таких файлов (они могут иметь расширение. rle) «не понимают». Существует разновидность формата ВМР для операционной системы OS/2 [2].

1.2. 2 Общая структура файла ВМР

Таблица. BMP-файл состоит из четырёх частей (см. рис. 1. 5).

Название поля

Размер (в байтах)

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

14

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

40

Палитра

Зависит от количества цветов.

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

Количество байтов опред. размерами растра и колич. битов на пиксель.

Таблица. Структура заголовка ВМР-файла

Название поля

Размер (в байтах)

Примечание

bfType

2

Код формата, соответствует «ВМ».

bfSize

4

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

bfReserved1

2

Зарезервировано. Равно 0.

bfReserved2

2

Зарезервировано. Равно 0.

bfOffBits

4

Адрес битового массива в данном файле.

Далее в файле идет еще один заголовок — заголовокизображения (BITMAPINFOHEADER, можетотсутствовать), в котором хранится описание размеров растра и цветового формата пикселов (см. рис. 1. 7).

Таблица. Структура заголовка изображения

Название поля

Размер (в байтах)

Примечание

biSize

4

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

biWidth

4

Ширина изображения.

biHeight

4

Высота изображения.

biplanes

2

Содержит 1.

biBitCount

2

Битнапиксел. Можетбыть 1, 4, 8, 16, 24 или 32.

biCompression

4

Компрессия:

0 — без компрессии;

1 — компрессия RLE8 (8 бит на пиксел);

2 — компрессия RLE4 (4 бита на пиксел);

3 — без компрессии для 16 и 32 бита на пиксел.

biSizeImage

4

Указывает размер изображения в байтах.

biXPelsPerMeter

4

Горизонтальное разрешение в пикселях на метр.

biYPelsPerMeter

4

Вертикальное разрешение в пикселях на метр.

biClrUsed

4

Количество используемых цветовых индексов в палитре.

biCrlImportant

4

Указывает количество индексов, необходимых для отображения изображения.

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

Таблица. Структура записи RGBQUAD

Название поля

Примечание

rgbBlue

Компонент Синий, от 0 до 255

rgbGreen

Компонент Зеленый, от 0 до 255

rgbRed

Компонент Красный, от 0 до 255

rgbReserved

Не используется и равно 0.

Количество записей RGBQUAD равняется количеству используемых цветов.

После палитры (если она есть) в файле ВМР записывается растр в виде битового массива [5].

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

2. Описание алгоритма отображения файла

2. 1 Открытие файла BMP

Открытие BMP файла осуществляется методом LoadFromFile, который загружает BMP-файл с заданным именем, считывая его с диска в оперативную память. В процессе загрузки сначала читается заголовок растрового файла, затем вычисляются размер заголовка информационного блока в совокупности с цветовой таблицей, который указывается в поле infoHeadSize.

Помимо этого в поле imageSize указывается вычисленный размер изображения в байтах. Полученные величины используются для указания размеров динамически выделяемой памяти под заголовок информационного блока plnfoHead и под массив пикселов aBitmapBits. После выделения указанной памяти соответсвующие компоненты растра читаются из файла.

На рисунке 2.1 показан алгоритм реализации чтения BMP файла.

2.3 Отображение изображения

Алгоритм отображения изображения представлен на рисунке

Рисунок 2.4 — Алгоритм отображение файла

Рисунок 2.3 — Алгоритм чтения BMPфайла

2. 2 Алгоритм сохранения изображения в GIF-формате

Алгоритм сохранения изображения в GIF-файл представлен на рисунке (см. рис. 2. 2).

Рисунок 2.2 — Алгоритм сохранения изображения в формат GIF

3. Описание алгоритмов реализации эффектов

3. 1 Преобразование цветов между базисами RGB и CMY

CMY (Cyan, Magenta, Yellow — голубой, пурпурный, желтый) — аппаратно-ориентированная модель, используемая в полиграфии для субтрактивного формирования оттенков, основанного на вычитании слоем краски части падающего светового потока. Цвета модели CMY являются дополнительными к цветам модели RGB, т. е. дополняющими их до белого.

Рисунок 3.1 — Цветовой куб модели CMY

Таким образом, система координат CMY — тот же куб, что и для RGB, но с началом отсчета в точке с RGB координатами (1,1,1), соответствующей белому цвету. Цветовой куб модели CMY показан на рисунке 2.4.

КонвертацияRGB в CMY: C := 255 — R; M := 255 — G; Y := 255 — B;

КонвертацияCMY в RGB: R := 255 — C; G := 255 — M; B := 255 — Y;

Рисунок3.3 — КонвертацияCMYвRGB

Рис.

3. 2 Преобразование цветов между базисами RGB и HSV

HSV (Hue, Saturation, Value — цветовой тон, насыщенность, количество света) — модель, ориентированная на человека и обеспечивающая возможность явного задания требуемого оттенка цвета (рис. 3). Подпространство, определяемое данной моделью — перевернутый шестигранный конус.

По вертикальной оси конуса задается V — светлота, меняющаяся от 0 до 1. Значению V = 0 соответствует вершина конуса, значению V = 1 — основание конуса; цвета при этом наиболее интенсивны.

Цветовой тон H задается углом, отсчитываемым вокруг вертикальной оси. В частности, 0° — красный, 60° — желтый, 120° — зеленый, 180° — голубой, 240° — синий, 300° — пурпурный, т. е. дополнительные цвета расположены друг против друга (отличаются на 180°).

Насыщенность S определяет насколько близок цвет к «чистому» пигменту и меняется от 0 на вертикальной оси V до 1 на боковых гранях шестигранного конуса.

Рисунок 3.4 — Разложение HSV

Точка V = 0, в которой находится вершина конуса, соответствует черному цвету. Значение S при этом может быть любым в диапазоне 0−1. Точка с координатами V = 1, S = 0 — центр основания конуса соответствует белому цвету. Промежуточные значения координаты V при S=0, т. е. на оси конуса, соответствуют серым цветам. Если S = 0, то значение оттенка H считается неопределенным.

Рисунок 3.5 — КонвертацияRGBвHSV

Рисунок 3.6 — КонвертацияHSV в RGB

3. 3 Зашумление составляющей M

Алгоритм зашумления изображения по составляющей Mпредставлен на рисунке 3.7.

Рисунок 3.7 — Алгоритм зашумления изображения по M

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

Если в файле нет палитры, то каждый пиксель нужно разложить на CMY, прибавить к Mзаданный шум, вернуть пиксель в предыдущий формат и сохранить полученное значение.

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

3. 4 Зашумление составляющей S

Алгоритм зашумления изображения составляющей S представлен на рисунке 3.8.

Рисунок 3.8 — Алгоритм зашумления составляющей S.

Данные в программе хранятся в базисе RGB и для зашумления составляющей S базиса HSV необходимо выполнить преобразование цвета каждого пикселя из базиса RGB в базис HSV, которое выполняет процедура RGBtoHSV. Далее требуется выполнить зашумление составляющей S, прибавлением к ней шума, заданного пользователем, и обратное преобразование из одного базиса в другой, выполняемое функцией HSVtoRGB.

3. 5 Фильтрация изображения

Для реализации фильтрации изображения использовался фильтр, который задается матрицей 3×3. Матрица изображена на рис. 3.4.

1

2

1

2

4

2

1

2

1

Рисунок 3.9 — Матрица фильтра 6

Рисунок 3. 10 — Алгоритм фильтрации изображения.

Изображение покрывается этой матрицей, в цикле попиксельно. При этом каждый элемент матрицы умножается с каждой составляющей соответствующего пикселя. При чем, если составляющая выходит за рамки 0… 255, то она приравнивается к ближайшей границе этого интервала.

Алгоритм фильтра представлен на рис. 3. 5

3. 6 Эффект наложения кругов

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

Рисунок 3. 11 — Эффект наложения кругов

4. Структура приложения

Структура системы представлена в виде схемы (см. рис. 4. 1).

Рисунок 4.1 — Структура приложения

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

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

Одним из самых популярных инструментов для создания функциональных и удобных Windows-приложений является язык программирования C++ и входящая в состав MicrosoftVisualStudio 2008, WindowsForms. Она включает в себя практически весь программный интерфейс Windows и позволяют пользоваться при программировании средствами более высокого уровня, чем обычные вызовы функций. За счет этого значительно упрощается разработка приложений, имеющих сложный интерфейс пользователя, облегчается поддержка технологии OLE и взаимодействие с базами данных.

Данная курсовая работа выполнена на объектно-ориентированном языкеС++. Это объясняется тем, что программные продукты созданные в с помощью C++наиболее просты в использовании и не требуют от пользователей глубоких знаний в управлении программами.

6. Описание основных модулей программы

Класс Formatпредназначен для работы с файлом BMP. Реализация класса показана на рисунке 6.1.

Рисунок 6.1 — Интерфейс класса Format

Кроме традиционных для класса методов, таких как конструктори деструктор, класс Format содержит методы, перечисленные ниже:

1) Метод CreateDib24 создает в памяти 24-разрядный растр с заданными шириной и высотой. В процессе создания осуществляется инициализация полей заголовкарастрового файла и заголовка информационного блока. После этого выделяетсяпамять для хранения массива пикселов. В завершение открывается дисковый файлс заданным именем, предназначенный для сохранения в нем создаваемого растра.

2) Метод SetPixel осуществляет прямой доступ к пикселам в 24-разрядном растре. Цветовая информация для синей, зеленой и красной составляющих цветапиксела записывается в соответствующие элементы массива aBitmapBits. Адресаэлементов вычисляются через номер строки развертки у и номер пиксела в строке х.

3) Метод StoreDib24 сохраняет созданный растр, записывая его на диск вформате GIF.

4) Метод LoadFromFile загружает BMP-файл с заданным именем, считывая егос диска в оперативную память. В процессе загрузки сначала читается заголовокрастрового файла, затем вычисляются размер заголовка информационного блока в совокупности с цветовой таблицей, который указывается в поле infoHeadSize. Помимо этого в поле imageSize указывается вычисленный размер изображенияв байтах. Полученные величины используются для указания размеров динамически выделяемой памяти под заголовок информационного блока plnfoHeadи под массив пикселов aBitmapBits. После выделения указанной памяти соответствующие компоненты растра читаются из файла.

5) Метод Draw выводит растр наповерхность графического устройства, используя функцию StretchDIBits.

6) Метод RgbToHlsпереводит даныые изображения из RGBв HLS.

7) Метод HlsToRgbпереводит данные изображения из HLSв RGB.

8) Метод NoiseMзашумляет составляющую M

9) Метод NoiseSпереводит данные изображения из RGBв HLS, зашумляет составляющую Sи обратно переводит из HLSв RGB.

10) Метод Filterприменяет фильтр «размытие» к изображению.

Таблица 6.1 Методы класса KDib.

Метод

Тип

Назначение

CreateDib24

BOOL

Создает GIF — файл

StoreDib24

VOID

Пересылка данных изображения

LoadFromFile

BOOL

Загружает BMP — файл

SetPixel

VOID

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

Draw

INT

Вывод на экран изображения

GetWidth

INT

Возвращает ширину

GetHeight

INT

Возвращает высоту

GetError

CHAR*

Возвращает ошибку

RGBtoHSV

VOID

Переводит из RGB в HSV

HSVToRGB

VOID

Переводит из HSV в RGB

LoadFromFile

BOOL

Загружает BMP — файл

GetA

BYTE*

Возвращает массив пикселов

Draw

INT

Вывод на экран изображения

GetWidth

INT

Возвращает ширину

GetHeight

INT

Возвращает высоту

NoiseB

VOID

ЗашумляетB

NoiseS

VOID

Защумляет S

Filter

VOID

Фильтрует

7. Тестирование, результаты работы программы

Программа написана под операционную систему от WindowsXP до WindowsVISTA. Для установки системы нет необходимости в особых настройках.

Требованияк аппаратной платформе — процессор должен быть типа Pentium или Celeron с тактовой частотой не ниже 166 МГц (рекомендуется Pentium III800 МГц), оперативной памяти — 512 Мбайт (рекомендуется 1024 Мбайт), достаточное количество свободного дискового пространства всего 50Mб.

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

Выводы

В разработанном приложении решены поставленные в техническом заданиизадачи, и реализованы требуемые возможности для работы с графическими форматами GIFи ВМР.

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

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

Приложение

Листинг программы

Format. h

class Format {

public:

BYTE* aBitmapBits; // массив пикселов

BYTE* aBitmapBits1;

BYTE* aBitmapCMY;

BYTE* aBitmapHSV;

BYTE R;

BYTE G;

BYTE B;

Format ();

~Format ();

BOOL CreateDib24(int w, int h, constchar* fileName);

void StoreDib24();

BOOL LoadFromFile (constchar* fileName);

void SetPixel (int x, int y, COLORREF color);

int Draw (HDC hdc, int xDst, int yDst, int wDst, int hDst,

int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop);

int GetWidth () { return width; }

int GetHeight () { return height; }

constchar* GetError () { return error. c_str ();}

void RGBtoCMY ();

void RGBtoHSV ();

void CMYtoRGB ();

void HSVtoRGB ();

void BazisС ();

void BazisM ();

void BazisY ();

void BazisH ();

void BazisS ();

void BazisV ();

void NoiseM ();

void NoiseS ();

void Filter ();

void Save ();

void Circ ();

void Transformtocirc (int x, int y);

int Draw1(HDC hdc, int xDst, int yDst, int wDst, int hDst,

int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop);

void TransformPix (int x, int y);

private:

int width;

int height;

int bytesPerLine;

BITMAPFILEHEADER fileHead; // заголовокрастровогофайла

BITMAPINFOHEADER infoHead; // заголовокинформационногоблока

BITMAPINFOHEADER* pInfoHead;

int fileHeadSize;

int infoHeadSize;

int imageSize;

string error;

ofstream outFile;

};

Format. cpp

#include"Format. h"

#include< math. h>

Format: :Format ()

{

fileHeadSize = sizeof (BITMAPFILEHEADER);

fileHead. bfType = 0x4d42;

aBitmapBits = NULL;

}

Format: :~Format () {

if (pInfoHead) delete [] pInfoHead;

if (aBitmapBits) delete [] aBitmapBits;

if (outFile) outFile. close ();

}

BOOL Format: :CreateDib24(int w, int h, constchar* fileName) ios: :binary

BOOL Format: :LoadFromFile (constchar* fileName) {

ifstream inpFile;

inpFile. open (fileName, ios: :in | ios: :binary);

if (!inpFile) {

error = «Неверное имя файла или каталога. «;

return FALSE;

}

inpFile. read ((char*)&fileHead, fileHeadSize);

if (fileHead. bfType ≠ 0x4d42) {

error = «Этоне BMP-файл»;

return FALSE;

}

infoHeadSize = fileHead. bfOffBits — fileHeadSize;

int fileSize = fileHead. bfSize;

imageSize = fileSize — (fileHeadSize + infoHeadSize);

pInfoHead = (BITMAPINFOHEADER*)(new BYTE [infoHeadSize]);

inpFile. read ((char*)pInfoHead, infoHeadSize);

width = pInfoHead-> biWidth;

height = pInfoHead-> biHeight;

aBitmapBits = new BYTE[imageSize];

inpFile. read ((char*)aBitmapBits, imageSize);

returntrue;

}

int Format: :Draw (HDC hdc, int xDst, int yDst, int wDst, int hDst,

int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop) {

return StretchDIBits (hdc, xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc,

aBitmapBits, (CONST BITMAPINFO*)pInfoHead, DIB_RGB_COLORS, rop);

}

void Format: :SetPixel (int x, int y, COLORREF color) {

int row = y;

int col = 3 * x;

aBitmapBits[row*bytesPerLine + col] = GetBValue (color);

aBitmapBits[row*bytesPerLine + col+1] = GetGValue (color);

aBitmapBits[row*bytesPerLine + col+2] = GetRValue (color);

aBitmapBits;

}

void Format: :StoreDib24() {

// Записьзаголовка BMP-файла

outFile. write ((char*)&fileHead, fileHeadSize);

outFile. write ((char*)&infoHead, infoHeadSize);

// Записьмассивапикселей

outFile. write ((char*)aBitmapBits, imageSize);

}

void Format: :CMYtoRGB ()

{

HDC hdc;

BYTE R, G, B, C, M, Y;

int x = GetWidth ();

int y = GetHeight ();

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

int row = y;

int col = 3 * x;

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

C = aBitmapCMY[row*bytesPerLine + col*3 + 2];

M = aBitmapCMY[row*bytesPerLine + (col*3)+ 1];

Y = aBitmapCMY[row*bytesPerLine + (col*3)];

R = 255-C;

G = 255-M;

B = 255-Y;

aBitmapBits[row*bytesPerLine + (col*3)] = B;

aBitmapBits[row*bytesPerLine + (col*3)+ 1] = G;

aBitmapBits[row*bytesPerLine + col*3 + 2] = R;

}

aBitmapBits;

}

void Format: :RGBtoCMY ()

{

BYTE R, G, B, C, M, Y;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapCMY = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

C = 255-R;

M = 255-G;

Y = 255-B;

aBitmapCMY[row*bytesPerLine + (col*3)] = Y;

aBitmapCMY[row*bytesPerLine + (col*3)+ 1] = M;

aBitmapCMY[row*bytesPerLine + col*3 + 2] = C;

}

aBitmapBits=aBitmapCMY;

}

void Format: :RGBtoHSV (){

BYTE R, G, B, H, S, V;

double rgbmin, rgbmax;

double rc, bc, gc;

double ht=0. 0, st=0. 0;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapHSV = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++)

{

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

rgbmin = min (R, min (G, B));

rgbmax = max (R, max (G, B));

if (rgbmax > 0. 0)

st = (rgbmax — rgbmin) / rgbmax;

if (st > 0. 0) {

rc = (rgbmax — R) / (rgbmax — rgbmin);

gc = (rgbmax — G) / (rgbmax — rgbmin);

bc = (rgbmax — B) / (rgbmax — rgbmin);

if (R == rgbmax) ht = bc — gc;

elseif (G == rgbmax) ht = 2 + rc — bc;

elseif (B == rgbmax) ht = 4 + gc — rc;

ht = ht * 60. 0;

if (ht < 0. 0) ht += 360. 0;

}

H = ht / 360. 0;

V = rgbmax;

S = st;

aBitmapHSV[row*bytesPerLine + (col*3)] = V;

aBitmapHSV[row*bytesPerLine + (col*3)+ 1] = S;

aBitmapHSV[row*bytesPerLine + col*3 + 2] = H;

}

}

void Format: :HSVtoRGB ()

{

BYTE R, G, B, H, S, V, i_H;

int ii;

double fr;

unsignedchar c1, c2, c3;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

i_H = aBitmapHSV[row*bytesPerLine + col*3 + 2];

S = aBitmapHSV[row*bytesPerLine + (col*3)+ 1];

V = aBitmapHSV[row*bytesPerLine + (col*3)];

if (!S)

R = G = B = V;

else

{

while (i_H >= 360)

i_H -= 360;

H = i_H;

ii = (int)(H /= 60. 0);

fr = H — ii;

c1 = (V * (255 — S)) / 255;

c2 = (V * (255 — S * fr)) / 255;

c3 = (V * (255 — S * (1.0 — fr))) / 255;

switch (ii)

{

case 0: R = V; G = c3; B = c1; break;

case 1: R = c2; G = V; B = c1; break;

case 2: R = c1; G = V; B = c3; break;

case 3: R = c1; G = c2; B = V; break;

case 4: R = c3; G = c1; B = V; break;

case 5: R = V; G = c1; B = c2; break;

} // switch

} // if (!sat)

aBitmapBits[row*bytesPerLine + (col*3)] = B;

aBitmapBits[row*bytesPerLine + (col*3)+ 1] = G;

aBitmapBits[row*bytesPerLine + col*3 + 2] = R;

}

}

void Format: :NoiseM (){

BYTE M;

int x = GetWidth ();

int y = GetHeight ();

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

M = aBitmapCMY[row*bytesPerLine + (col*3)+1];

M+=rand ();

if (M < 0) M = 0;

if (M > 255) M = 255;

aBitmapCMY[row*bytesPerLine + (col*3)+1] = M;

}

aBitmapBits = aBitmapCMY;

}

void Format: :NoiseS (){

BYTE S;

int x = GetWidth ();

int y = GetHeight ();

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

S = aBitmapHSV[row*bytesPerLine + (col*3)+1];

S+=rand ();

if (S < 0) S = 0;

if (S > 255) S = 255;

aBitmapHSV[row*bytesPerLine + (col*3)+1] = S;

}

aBitmapBits = aBitmapHSV;

}

void Format: :TransformPix (int x, int y){

BYTE NewBGR[3];

int Pixel[3];

BYTE Pix[3];

int w = GetWidth ();

int h = GetHeight ();

int count = 9;

int Matrix[9]={1,2,1,

2,4,2,

1,2,1};

int bytesPerLine = ((w * 24 + 31) / 32) * 4;

// x y

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[y*bytesPerLine + x*3 + c];

Pixel[c] = NewBGR[c] * Matrix[4];

}

// x-1 y-1

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[(y-1)*bytesPerLine + (x-1)*3 + c];

Pixel[c] += NewBGR[c] * Matrix[0];

}

// x y-1

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[y*bytesPerLine + (x-1)*3 + c];

Pixel[c] += NewBGR[c] * Matrix[1];

}

// x+1 y-1

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[(y+1)*bytesPerLine + (x-1)*3 + c];

Pixel[c] += NewBGR[c] * Matrix[2];

}

// x+1 y

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[(y+1)*bytesPerLine + x*3 + c];

Pixel[c] += NewBGR[c] * Matrix[5];

}

// x+1 y+1

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[(y+1)*bytesPerLine + (x+1)*3 + c];

Pixel[c] += NewBGR[c] * Matrix[8];

}

// x y+1

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[y*bytesPerLine + (x+1)*3 + c];

Pixel[c] += NewBGR[c] * Matrix[7];

}

// x-1 y+1

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[(y-1)*bytesPerLine + (x+1)*3 + c];

Pixel[c] += NewBGR[c] * Matrix[6];

}

// x-1 y

for (int c = 0; c < 3; c++){

NewBGR[c] = aBitmapBits[(y-1)*bytesPerLine + x*3 + c];

Pixel[c] += NewBGR[c] * Matrix[3];

}

for (int c = 0; c < 3; c++){

if (count≠0)

Pixel[c] = Pixel[c]/count;

Pix[c] = BYTE (Pixel[c]);

if (Pix[c] < 0)

Pix[c] = 0;

elseif (Pix[c] > 255)

Pix[c]=255;

aBitmapHSV[y*bytesPerLine + x*3 + c] = Pix[c];

}

}

void Format: :Filter (){

int w = GetWidth ();

int h = GetHeight ();

imageSize = w * h * 4;

aBitmapHSV = new BYTE[imageSize];

for (int y = 1; y < h-1; y++)

for (int x = 1;x < w-1; x++){

TransformPix (x, y);

}

aBitmapBits = aBitmapHSV;

}

void Format: :BazisС ()

{

BYTE R, G, B, C, M, Y;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapCMY = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

C = 255-R;

M = G-G;

Y = B-B;

aBitmapCMY[row*bytesPerLine + (col*3)] = Y;

aBitmapCMY[row*bytesPerLine + (col*3)+ 1] = M;

aBitmapCMY[row*bytesPerLine + col*3 + 2] = C;

}

aBitmapBits=aBitmapCMY;

}

void Format: :BazisM ()

{

BYTE R, G, B, C, M, Y;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapCMY = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

C = R-R;

M = 255-G;

Y = B-B;

aBitmapCMY[row*bytesPerLine + (col*3)] = Y;

aBitmapCMY[row*bytesPerLine + (col*3)+ 1] = M;

aBitmapCMY[row*bytesPerLine + col*3 + 2] = C;

}

aBitmapBits=aBitmapCMY;

}

void Format: :BazisY ()

{

BYTE R, G, B, C, M, Y;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapCMY = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++){

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

C = R-R;

M = G-G;

Y = 255-B;

aBitmapCMY[row*bytesPerLine + (col*3)] = Y;

aBitmapCMY[row*bytesPerLine + (col*3)+ 1] = M;

aBitmapCMY[row*bytesPerLine + col*3 + 2] = C;

}

aBitmapBits=aBitmapCMY;

}

void Format: :BazisH (){

BYTE R, G, B, H, S, V;

double rgbmin, rgbmax;

double rc, bc, gc;

double ht=0. 0, st=0. 0;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapHSV = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++)

{

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

rgbmin = min (R, min (G, B));

rgbmax = max (R, max (G, B));

if (rgbmax > 0. 0)

st = (rgbmax — rgbmin) / rgbmax;

if (st > 0. 0) {

rc = (rgbmax — R) / (rgbmax — rgbmin);

gc = (rgbmax — G) / (rgbmax — rgbmin);

bc = (rgbmax — B) / (rgbmax — rgbmin);

if (R == rgbmax) ht = bc — gc;

elseif (G == rgbmax) ht = 2 + rc — bc;

elseif (B == rgbmax) ht = 4 + gc — rc;

ht = ht * 60. 0;

if (ht < 0. 0) ht += 360. 0;

}

H = ht / 360. 0;

V = rgbmin;

S = 0;

aBitmapHSV[row*bytesPerLine + (col*3)] = V;

aBitmapHSV[row*bytesPerLine + (col*3)+ 1] = S;

aBitmapHSV[row*bytesPerLine + col*3 + 2] = H;

}

aBitmapBits=aBitmapHSV;

}

void Format: :BazisS (){

BYTE R, G, B, H, S, V;

double rgbmin, rgbmax;

double rc, bc, gc;

double ht=0. 0, st=0. 0;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapHSV = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++)

{

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

rgbmin = min (R, min (G, B));

rgbmax = max (R, max (G, B));

if (rgbmax > 0. 0)

st = (rgbmax — rgbmin) / rgbmax;

if (st > 0. 0) {

rc = (rgbmax — R) / (rgbmax — rgbmin);

gc = (rgbmax — G) / (rgbmax — rgbmin);

bc = (rgbmax — B) / (rgbmax — rgbmin);

if (R == rgbmax) ht = bc — gc;

elseif (G == rgbmax) ht = 2 + rc — bc;

elseif (B == rgbmax) ht = 4 + gc — rc;

ht = ht * 60. 0;

if (ht < 0. 0) ht += 360. 0;

}

H = 0. 0;

V = 0;

S = st;

aBitmapHSV[row*bytesPerLine + (col*3)] = V;

aBitmapHSV[row*bytesPerLine + (col*3)+ 1] = S;

aBitmapHSV[row*bytesPerLine + col*3 + 2] = H;

}

aBitmapBits=aBitmapHSV;

}

void Format: :BazisV (){

BYTE R, G, B, H, S, V;

double rgbmin, rgbmax;

double rc, bc, gc;

double ht=0. 0, st=0. 0;

int x = GetWidth ();

int y = GetHeight ();

int row = y;

int col = 3 * x;

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapHSV = new BYTE[imageSize];

for (int row = 0; row < y; row++)

for (int col = 0; col < x; col++)

{

R = aBitmapBits[row*bytesPerLine + col*3 + 2];

G = aBitmapBits[row*bytesPerLine + (col*3)+ 1];

B = aBitmapBits[row*bytesPerLine + (col*3)];

rgbmin = min (R, min (G, B));

rgbmax = max (R, max (G, B));

if (rgbmax > 0. 0)

st = (rgbmax — rgbmin) / rgbmax;

if (st > 0. 0) {

rc = (rgbmax — R) / (rgbmax — rgbmin);

gc = (rgbmax — G) / (rgbmax — rgbmin);

bc = (rgbmax — B) / (rgbmax — rgbmin);

if (R == rgbmax) ht = bc — gc;

elseif (G == rgbmax) ht = 2 + rc — bc;

elseif (B == rgbmax) ht = 4 + gc — rc;

ht = ht * 60. 0;

if (ht < 0. 0) ht += 360. 0;

}

H = 0. 0;

V = rgbmax;

S = 0;

aBitmapHSV[row*bytesPerLine + (col*3)] = V;

aBitmapHSV[row*bytesPerLine + (col*3)+ 1] = S;

aBitmapHSV[row*bytesPerLine + col*3 + 2] = H;

}

aBitmapBits=aBitmapHSV;

}

void Format: :Save ()

{

int x = GetWidth ();

int y = GetHeight ();

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapBits1 = new BYTE[imageSize];

aBitmapBits1=aBitmapBits;

}

int Format: :Draw1(HDC hdc, int xDst, int yDst, int wDst, int hDst,

int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop)

{

int x = GetWidth ();

int y = GetHeight ();

int bytesPerLine = ((x * 24 + 31) / 32) * 4;

imageSize = x * y * 3;

aBitmapBits = new BYTE[imageSize];

aBitmapBits=aBitmapBits1;

return StretchDIBits (hdc, xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc,

aBitmapBits1, (CONST BITMAPINFO*)pInfoHead, DIB_RGB_COLORS, rop);

}

void Format: :Circ ()

{

int Matrix[11][11]={1,1,1,1,0,0,0,1,1,1,1,

1,1,1,0,0,1,0,0,1,1,1,

1,1,0,0,1,1,1,0,0,1,1,

1,0,0,1,1,1,1,1,0,0,1,

0,0,1,1,1,1,1,1,1,0,0,

0,1,1,1,1,1,1,1,1,1,0,

0,0,1,1,1,1,1,1,1,0,0,

1,0,0,1,1,1,1,1,0,0,1,

1,1,0,0,1,1,1,0,0,1,1,

1,1,1,0,0,1,0,0,1,1,1,

1,1,1,1,0,0,0,1,1,1,1};

BYTE R, G, B;

int I=0,J=0;

int w = GetWidth ();

int h = GetHeight ();

int row = h;

int col = 3 * w;

int bytesPerLine = ((w * 24 + 31) / 32) * 4;

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

{

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

{

R = aBitmapBits[j*bytesPerLine + i*3 + 2];

G = aBitmapBits[j*bytesPerLine + (i*3)+ 1];

B = aBitmapBits[j*bytesPerLine + (i*3)];

R *=Matrix [I][J];

G *=Matrix [I][J];

B *=Matrix [I][J];

aBitmapBits[j*bytesPerLine + (i*3)] = B;

aBitmapBits[j*bytesPerLine + (i*3)+ 1] = G;

aBitmapBits[j*bytesPerLine + i*3 + 2] = R;

J++;

if (J==11)

{

J=0;

//j+=1;

}

}

I++;

J=0;

if (I==11)

{

I=0;

//i+=1;

}

}

aBitmapBits;

}

Размещено на

ПоказатьСвернуть
Заполнить форму текущей работой