Программа цифровой обработки растровых графических изображений
Описание математических методов представления и обработки графических изображений. Описание разработанного программного дополнения. Описание функций и их атрибутов. Представление и обработка графических изображений. Результаты тестирования программы.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 27.01.2015 |
Размер файла | 1,7 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru
Содержание
- Введение
- 1. Постановка задачи
- 2. Описание математических методов представления и обработки графических изображений
- 2.1 Представление графических изображений:
- 2.2 Обработка графических изображений:
- 3. Описание разработанного програмного дополнения
- 3.1 Описание модулей программы
- 3.2 Описание основных функций и их атрибутов
- 3.3 Результаты тестирования программы
- Заключение
- Список литературы
Введение
Компьютерная графика (также машинная графика) -- область деятельности, в которой компьютеры используются в качестве инструмента как для синтеза (создания) изображений, так и для обработки визуальной информации, полученной из реального мира.
В данной курсовой работе рассматривается возможность реализации программ цифровой обработки растровых графических изображений, методы изменения положения изображения, таких как масштабирование, зеркальное отображение и перемещение части изображения. А так же были изучены и реализованы алгоритмы считывания и записи графических файлов в форматах BMP и TGA. Данный вопрос является актуальным, так как цифровая обработка изображений все более часто используется в повседневной жизни. Рассматриваемые алгоритмы очень популярны, так как решают задачи встречающиеся очень часто.
1. Постановка задачи
В курсовой работе необходимо создать программу, реализующую следующие задачи:
1. Считать информацию из графического файла заданного формата.
2. Реализовать обработку информации согласно задаче.
3. Организовать сохранение измененного изображения в заданном формате.
Программа должна работать для любых размеров изображений.
При написании программы нельзя использовать готовые компоненты, которые решают поставленные задачи.
Необходимо привести в ПЗ все теоретические сведения с указанием источника, необходимые для решения задачи
Необходимо привести в ПЗ таблицы с описанием основных переменных, функций, модулей, классов и т.п.
Рекомендуется называть основные переменные так, как они названы в приведенном теоретическом материале.
Форматы файлов по желанию можно дополнить или изменить на новые, такие, что не используются в задачах.
2. Описание математических методов представления и обработки графических изображений
2.1 Представление графических изображений
Растровое изображение представляет из себя мозаику из очень мелких элементов -- пикселей. Растровый рисунок похож на лист клетчатой бумаги, на котором каждая клеточка закрашена определённым цветом, и в результате такой раскраски формируется изображение.
Растровая графика работает с сотнями и тысячами пикселей, которые формируют рисунок. Пиксели «не знают», какие объекты (линии, эллипсы, прямоугольники и т. д.) они составляют.
В компьютерной графике термин «пиксель», вообще говоря, может обозначать разные понятия:
· наименьший элемент изображения на экране компьютера;
· отдельный элемент растрового изображения;
· точка изображения, напечатанного на принтере.
Поэтому, чтобы избежать путаницы, будем пользоваться следующей терминологией:
· видеопиксель-- наименьший элемент изображения на экране;
· пиксель -- отдельный элемент растрового изображения;
· точка -- наименьший элемент, создаваемый принтером.
При этом для изображения одного пикселя на экране компьютера может быть использован один или несколько видеопикселей .
Экран дисплея разбит на фиксированное число видеопикселей , которые образуют графическую сетку (растр) из фиксированного числа строк и столбцов. Размер графической сетки обычно представляется в форме NxM , где N -- количество видеопикселей по горизонтали, а М -- по вертикали. На современных дисплеях используются, например, такие размеры графической сетки: 640 х 480, 800 х 600, 1024 х 768, 1240 х 1024 и др. Изображение на экране дисплея создается путем избирательной засветки электронным лучом определенных видеопикселей экрана. Чтобы изображение могло восприниматься глазом, его необходимо составить из сотен или тысяч видеопикселей , каждый из которых должен быть подсвечен.
Растровую графику редактируют с помощью растровых графических редакторов. Создается растровая графика фотоаппаратами, сканерами, непосредственно в растровом редакторе, также путем экспорта из векторного редактора или в виде снимка экрана.
Достоинства:
· Растровая графика позволяет создать (воспроизвести) практически любой рисунок, вне зависимости от сложности, в отличие, например, от векторной, где невозможно точно передать эффект перехода от одного цвета к другому без потерь в размере файла.
· Распространённость -- растровая графика используется практически везде: от маленьких значков до плакатов.
· Высокая скорость обработки сложных изображений, если не нужно масштабирование.
· Растровое представление изображения естественно для большинства устройств ввода-вывода графической информации, таких как мониторы (за исключением векторных), матричные и струйные принтеры, цифровые фотоаппараты, сканеры, а также мобильные телефоны.
Недостатки:
· Большой размер файлов с простыми изображениями.
· Невозможность идеального масштабирования.
· Невозможность вывода на печать на плоттер.
Из-за этих недостатков для хранения простых рисунков рекомендуют вместо даже сжатой растровой графики использовать векторную графику.
Форматы:
Растровые изображения обычно хранятся в сжатом виде. В зависимости от типа сжатия может быть возможно или невозможно восстановить изображение в точности таким, каким оно было до сжатия (сжатие без потерь или сжатие с потерями соответственно). Так же в графическом файле может храниться дополнительная информация: об авторе файла, фотокамере и её настройках, количестве точек на дюйм при печати и др. графический изображение программный изображение
BMP (от англ. Bitmap Picture) -- формат хранения растровых изображений, разработанный компанией Microsoft.
С форматом BMP работает огромное количество программ, так как его поддержка интегрирована в операционную систему Windows. Файлы формата BMP могут иметь расширения .bmp, .dib и .rle. Кроме того, данные этого формата включаются в двоичные файлы ресурсов RES и в PE-файлы.
Компания Microsoft так же разработала для своих нужд форматы ICO и CUR, которые имеют похожую на BMP структуру. Кроме этого, структуры из этого формата используются некоторыми WinAPI-функциями подсистемы GDI.
Глубина цвета в данном формате может быть 1, 2, 4, 8, 16, 24, 32, 48 бит на пиксель, но глубина 2 бита на пиксель официально не поддерживается. При этом для глубины цвета меньше 16 бит используется палитра с полноцветными компонентами глубиной 24 бита.
В формате BMP изображения могут храниться как есть или же с применением некоторых распространённых алгоритмов сжатия. В частности, формат BMP поддерживает RLE-сжатие без потери качества, а современные операционные системы и программное обеспечение позволяют использовать JPEG и PNG (эти форматы встраиваются в BMP как в контейнер). JPEG очень широко используемый формат изображений. Сжатие основано на усреднении цвета соседних пикселей (информация о яркости при этом не усредняется) и отбрасывании высокочастотных составляющих в пространственном спектре фрагмента изображения. При детальном рассмотрении сильно сжатого изображения заметно размытие резких границ и характерный муар вблизи них.
JPEG (произносится «джейпег», англ. Joint Photographic Experts Group, по названию организации-разработчика) -- один из популярных графических форматов, применяемый для хранения фотоизображений и подобных им изображений. Файлы, содержащие данные JPEG, обычно имеют расширения (суффиксы) .jpeg, .jfif, .jpg, .JPG, или .JPE. Однако из них .jpg является самым популярным на всех платформах. MIME-типом является image/jpeg.
Алгоритм JPEG позволяет сжимать изображение как с потерями, так и без потерь (режим сжатия lossless JPEG).
Алгоритм JPEG в наибольшей степени пригоден для сжатия фотографий и картин, содержащих реалистичные сцены с плавными переходами яркости и цвета. Наибольшее распространение JPEG получил в цифровой фотографии и для хранения и передачи изображений с использованием сети Интернет.
С другой стороны, JPEG малопригоден для сжатия чертежей, текстовой и знаковой графики, где резкий контраст между соседними пикселами приводит к появлению заметных артефактов. Такие изображения целесообразно сохранять в форматах без потерь, таких как TIFF, GIF или PNG.
JPEG (как и другие методы искажающего сжатия) не подходит для сжатия изображений при многоступенчатой обработке, так как искажения в изображения будут вноситься каждый раз при сохранении промежуточных результатов обработки.
JPEG не должен использоваться и в тех случаях, когда недопустимы даже минимальные потери, например, при сжатии астрономических или медицинских изображений. В таких случаях может быть рекомендован предусмотренный стандартом JPEG режим сжатия Lossless JPEG (который, к сожалению, не поддерживается большинством популярных кодеков) или стандарт сжатия JPEG-LS.
Сжатие
При сжатии изображение преобразуется из цветового пространства RGB в YCbCr (YUV). Следует отметить, что стандарт JPEG (ISO/IEC 10918-1) никак не регламентирует выбор именно YCbCr, допуская и другие виды преобразования (например, с числом компонентов[2], отличным от трёх), и сжатие без преобразования (непосредственно в RGB), однако спецификация JFIF (JPEG File Interchange Format, предложенная в 1991 году специалистами компании C-Cube Microsystems, и ставшая в настоящее время стандартом де-факто) предполагает использование преобразования RGB->YCbCr.
После преобразования RGB->YCbCr для каналов изображения Cb и Cr, отвечающих за цвет, может выполняться "прореживание" (subsampling), которое заключается в том, что каждому блоку из 4 пикселов (2х2) яркостного канала Y ставятся в соответствие усреднённые значения Cb и Cr (схема прореживания "4:2:0"). При этом для каждого блока 2х2 вместо 12 значений (4 Y, 4 Cb и 4 Cr) используется всего 6 (4 Y и по одному усреднённому Cb и Cr). Если к качеству восстановленного после сжатия изображения предъявляются повышенные требования, прореживание может выполняться лишь в каком-то одном направлении -- по вертикали (схема "4:4:0") или по горизонтали ("4:2:2"), или не выполняться вовсе ("4:4:4").
Стандарт допускает также прореживание с усреднением Cb и Cr не для блока 2х2, а для четырёх расположенных последовательно (по вертикали или по горизонтали) пикселов, то есть для блоков 1х4, 4х1 (схема "4:1:1"), а также 2х4 и 4х2 (схема "4:1:0"). Допускается также использование различных типов прореживания для Cb и Cr, но на практике такие схемы применяются исключительно редко.
Далее яркостной компонент Y и отвечающие за цвет компоненты Cb и Cr разбиваются на блоки 8х8 пикселов. Каждый такой блок подвергается дискретному косинусному преобразованию (ДКП). Полученные коэффициенты ДКП квантуются (для Y, Cb и Cr в общем случае используются разные матрицы квантования) и пакуются с использованием кодов Хаффмана. Стандарт JPEG допускает также использование значительно более эффективного арифметического кодирования, однако из-за патентных ограничений (патент на описанный в стандарте JPEG арифметический QM-кодер принадлежит IBM) на практике оно используется редко. В популярную библиотеку libjpeg последних версий включена поддержка арифметического кодирования, но с просмотром сжатых с использованием этого метода изображений могут возникнуть проблемы.
Матрицы, используемые для квантования коэффициентов ДКП, хранятся в заголовочной части JPEG-файла. Обычно они строятся так, что высокочастотные коэффициенты подвергаются более сильному квантованию, чем низкочастотные. Это приводит к огрублению мелких деталей на изображении. Чем выше степень сжатия, тем более сильному квантованию подвергаются все коэффициенты.
К недостаткам сжатия по стандарту JPEG следует отнести появление на восстановленных изображениях при высоких степенях сжатия характерных артефактов: изображение рассыпается на блоки размером 8x8 пикселов (этот эффект особенно заметен на областях изображения с плавными изменениями яркости), в областях с высокой пространственной частотой (например, на контрастных контурах и границах изображения) возникают артефакты в виде шумовых ореолов. Следует отметить, что стандарт JPEG (ISO/IEC 10918-1, Annex K, п. K.8) предусматривает использование специальных фильтров для подавления блоковых артефактов, но на практике подобные фильтры, несмотря на их высокую эффективность, практически не используются. Однако, несмотря на недостатки, JPEG получил очень широкое распространение из-за достаточно высокой (относительно существовавших во время его появления альтернатив) степени сжатия, поддержке сжатия полноцветных изображений и относительно невысокой вычислительной сложности.
2.2 Обработка графических изображений
Существует множество способов изменения и редактирования изображений, с помощью цифровых методов. Результат обработки изображений при этом зависит от того, какие операции вы можете произвести с изображением, после того, как оно попало на ваш компьютер: вы можете редактировать RGB компоненты цветов, с целью получения наилучшего цветового баланса. Вы можете увеличить или уменьшить яркость изображения, редактировать его резкость или размывать отдельные элементы с помощью различных графических фильтров. Мы рассмотрим повсеместно используемые в компьютерной графике методы изменения положения изображения:
Масштабирование
Зеркальное отображение
Выделение простой области
Перемещение
Масштабирование
Масштаб -- в общем случае отношение двух линейных размеров. Во многих областях практического применения, масштабом называют отношение размера изображения к размеру изображаемого объекта.
Масштабирование -- изменение размера изображения с сохранением пропорций.
Под масштабированием подразумевается, как увеличение, так и уменьшение размеров изображения. В настоящее время масштабирование выполняется с помощью компьютерной техники. При этом, в зависимости от типа графики (растровая, векторная), масштабирование производится по разным алгоритмам. Если графика векторная, то масштабирование происходит без потерь качества изображения, если растровая, то при масштабировании происходит потеря качества изображения.
Размер изображения может быть изменён несколькими способами. Рассмотрим удвоение размера следующего изображения (Рис 2.2.1):
Рисунок 2.2.1 - Исходное изображение
Простейшим способом удвоения размера является метод копирования ближайшего пиксела, заменяющий каждый пиксель четырьмя пикселями того же цвета (Рису 2.2.2):
Рисунок 2.2.2 - Метод копирования ближайшего пикселя
Полученное изображение больше оригинала, и сохраняет его детали, но приобретает нежелательный лестничный эффект. Диагональные линии буквы W, к примеру, имеют характерную форму "лесенки".
Другие методы лучше подходят для сохранения гладких контуров изображения. К примеру, билинейная интерполяция даёт следующий результат (Рис. 2.2.3):
Рисунок 2.2.3 - Билинейная интерполяция
Линейная (или билинейная) интерполяция обычно лучше чем метод копирования ближайшего пиксела для изменения размеров изображения, но иногда вызывает нежелательные эффекты сглаживания деталей и всё равно порождает довольно заметный эффект лестницы. Более совершенным методом является использование, к примеру, бикубической интерполяции (Рис.2.2.4):
Рисунок 2.2.4 - Бикубическая интерполяция.
Также существуют сглаживающие алгоритмы, подходящие для обработки фото и многоцветных растровых изображений с эффектом лесенки, которые называются supersampling (сглаживание методом "сверхмасштаба").
В программе реализован метод билинейной интерполяции изображения. Этот метод дает гораздо более лучшие результаты, нежели метод ближайших соседей и при высокой степени интерполирования изображения мало чем уступает методу бикубической интерполяции.
Ключевая идея заключается в том, чтобы провести обычную линейную интерполяцию сначала в одном направлении, затем в другом.
Пример билинейной интерполяции в единичном квадрате. Значения вершин составляют 0, 1, 1 и 0.5. Интерполированные значения в каждой точке представлены цветом Рис(2.2.5):
Рисунок 2.2.5
Допустим, что необходимо интерполировать значение функции f в точке P = (x, y). Для этого необходимо знать значения функций в (окружающих P) точках Q11 = (x1, y1), Q12 = (x1, y2), Q21 = (x2, y1), и Q22 = (x2, y2).
Первым шагом интерполируется (линейно) значение вспомогательных точек и вдоль оси абсцисс, где
Теперь проводится линейная интерполяция между вспомогательными точками и .
Это и есть приблизительное значение функции в точке P, то есть f(x, y).
Стоит заметить, что данный метод не лишен недостатков, главным из которых является факт увеличения в N раз изображения размером W на H пикселей, т.е. будет получено изображение размером не NW на NH пикселей, а ( N ( W - 1) + 1 ) на ( N ( H - 1 ) + 1 ) пикселей. Связано это с тем, что в исходном изображении, например по горизонтали имеется W точек, т.е. (W-1) смежных пар. При увеличении изображения в N раз между парой основных точек вставляется по (N-1) дополнительных точек (то есть при увеличении вдвое между основными точками вставляется еще по одной, при увеличении втрое -- по две и т. д.). Итого в результате ширина результирующего изображения будет равна сумме количества основных и дополнительных точек.
Зеркальное отображение изображения
Изображение можно зеркально отобразить относительно вертикальной или горизонтальной оси. Зеркальное отображение позволяет просмотреть элементы изображения с противоположной стороны от их реального положения. Функция зеркального отображения полезна для негативов, которые могли быть вставлены в рамки наоборот и отсканированы в зеркально отображенном виде.
В программе зеркальное отображение осуществлено с помощью двух циклов, которые перебирают все пиксели изображения и меняют их местами в зависимости от типа отображения. Если это отображение по оси Y, т.е. вертикальное отображение, то меняются местами пиксели, расположенные по оси Y, и наоборот.
Выделение простой области и её перемещение
Так же в программе реализовано выделение простой области и её перемещение. Алгоритм данной функции состоит в том, что изначально выделяется область (для этого указываются координаты крайней левой точки области, ширина и высота области). После чего создаётся контейнер, в который клонируются пикселя из этой области. Таким способом мы получаем отдельный выбранный фрагмент изображения. В дальнейшем этот контейнер можно переместить в другую область изображения.
Программа позволяет сохранить изображение с выделенной областью, перемещенной в любое место изображения. Это возможно благодаря «наложению» одного изображения на другое, вследствие чего, пиксели, находящиеся на месте наложения у родительского изображения заменятся пикселями дочернего изображения.
3. Описание разработанного программного дополнения
3.1 Описание модулей программы
В разработанной программе по обработке цифровых растровых изображений имеется два главных класса, которые постоянно взаимодействуют и выполняют все основные функции.
Первый класс - ImageProcessing. Данный класс отвечает за пользовательский интерфейс и в нём вызываются основные методы второго класса - ImageHandler, без которых невозможно выполнение главных задач программы.
Так же программа содержит вспомогательные формы CropForm и ImageInfo. Первая форма служит для того, чтобы пользователь задал координаты, ширину и высоту выделяемой области. Вторая форма служит для выведения информации об изображении.
3.2 Описание основных функций и их атрибутов
К основным функциям программы можно отнести:
Такие функции класса ImageProcessing, как:
menuItemOpen_Click(object sender, EventArgs e)
menuItemExit_Click(object sender, EventArgs e)
menuItemUndo_Click(object sender, EventArgs e)
menuItemImageInfo_Click(object sender, EventArgs e)
menuItemZoom50_Click(object sender, EventArgs e)
menuItemZoom100_Click(object sender, EventArgs e)
menuItemZoom200_Click(object sender, EventArgs e)
menuItemZoom300_Click(object sender, EventArgs e)
menuItemZoom400_Click(object sender, EventArgs e)
menuItemZoom500_Click(object sender, EventArgs e)
menuItemFlipH_Click(object sender, EventArgs e)
menuItemFlipV_Click(object sender, EventArgs e)
pictureBox1_KeyDown(object sender, KeyEventArgs e)
menuItem2_Click(object sender, EventArgs e)
menuItem3_Click(object sender, EventArgs e)
menuItem6_Click(object sender, EventArgs e)
menuItem1_Click(object sender, EventArgs e)
button1_Click(object sender, EventArgs e)
отвечают за поведение программы при взаимодействии пользователя с интерфейсом.
ImageProcessing_Paint(object sender, PaintEventArgs e) - отвечает за прорисовку изображения на экране.
AlphaBlending(Image xx, Image yy, float percent) - отвечает за наложение фрагмента изображения на изображение и сохранение полученного изображения.
menuItemCrop_Click(object sender, EventArgs e) - отвечает за вырезание выбранного фрагмента из изображения.
ResetBitmap() - возвращает изображение перед последним его изменением.
SaveBitmap(string saveFilePath) - сохраняет изображение.
RotateFlip(RotateFlipType rotateFlipType) - служит для зеркального отображения изображения.
DrawOutCropArea(int xPosition, int yPosition, int width, int height) - выделяет выбранную область, которую в дальнейшем, при подтверждении можно вырезать.
RemoveCropAreaDraw() - удаляет выбранную область.
3.3 Результаты тестирования программы
Для тестирования программы мы используем графический файл формата JPEG с разрешением изображения 800х600 пикселя:
1. Загрузим файл в программу.
Изменим масштаб изображения.
Отобразим зеркально изображение
2. Отменим последний шаг изменения сочетанием клавиш Ctrl+Z.
3. Выделим фрагмент изображения и переместим его.
4. Сохраним файл в формате BMP.
Данная программа выполнила все пункты, указанные в индивидуальном задании.
Заключение
В результате выполнения курсовой работы, была разработана программа, которая может быть практически использована в виде узкофункционального графического редактора. Решенные здесь задачи актуальны, так как цифровая обработка изображений встречается повсеместно в наши дни. В программе реализована возможность цифровой обработки растровых графических изображений, а именно, масштабирование, зеркально отображение, выделение фрагмента изображения и его перемещение. А в ходе её создания были изучены и реализованы алгоритмы считывания и записи графических файлов в форматах BMP и JPEG.
Список литературы
Методическая литература:
1. Методи та засоби комп'ютерних та інформаційних технологій. Конспект лекцій. /Укл.: М.В. Привалов - Донецьк: ДНТ.
Литература по теме:
2. Графические форматы. Материал из Википедии -- свободной энциклопедии / Ел. ресурс: http://ru.wikipedia.org/wiki/Графические_форматы
3. Никулин Е. А. Компьютерная геометрия и алгоритмы машинной графики. -- СПб: БХВ-Петербург, 2003. -- 560 с. -- 3000 экз. -- ISBN 5-94157-264-6
Приложение
Листинг программы
namespace ImageProcessing
{ public partial class ImageProcessing : Form
{OpenFileDialog oDlg;//переменная типа диалогового окна открытия файла
SaveFileDialog sDlg1;//переменная типа диалогового окна сохранения файла
SaveFileDialog sDlg2;//переменная типа диалогового окна сохранения файла
private MenuItem cZoom;//переменная для меню увеличения изображения
Bitmap temp;//переменная для хранения временного изображения
Bitmap cloneBitmap;//переменная для хранения выделенной области
int cropX = 0, cropY = 0, widthImgCrop = 100, heightImgCrop = 100;//переменные для хранения координат выделяемого изображения, ширины и высоты
ImageHandler imageHandler = new ImageHandler();//создание экземпляра класса imageHandler
public ImageProcessing()
{
InitializeComponent();
oDlg = new OpenFileDialog();//создание диалогового окна для открытия файла
oDlg.RestoreDirectory = true;
oDlg.InitialDirectory = "C:\\";
oDlg.FilterIndex = 1;
oDlg.Filter = "jpg Files (*.jpg)|*.jpg";
/*************************/
sDlg1 = new SaveFileDialog();//создание диалогового окна для сохранения файла
sDlg1.RestoreDirectory = true;
sDlg1.InitialDirectory = "C:\\";
sDlg1.FilterIndex = 1;
sDlg1.Filter = "bmp Files (*.bmp)|*.bmp";
/*************************/
sDlg2 = new SaveFileDialog();//создание диалогового окна для сохранения файла с выделенным изображением
sDlg2.RestoreDirectory = true;
sDlg2.InitialDirectory = "C:\\";
sDlg2.FilterIndex = 1;
sDlg2.Filter = "bmp Files (*.bmp)|*.bmp";
cZoom = menuItemZoom50;
}
private void ImageProcessing_Paint(object sender, PaintEventArgs e)//функция выводит изображение на форму
{
if(imageHandler.IsPicture)
{
e.Graphics.DrawImage(imageHandler.GetBitmap(), new Rectangle(this.AutoScrollPosition.X, this.AutoScrollPosition.Y,Convert.ToInt32(imageHandler.Width),Convert.ToInt32(imageHandler.Height)));
}
}
private void menuItemOpen_Click(object sender, EventArgs e)//функция попиксельно считывает выбранное изображение и создает битмап
{
if (DialogResult.OK == oDlg.ShowDialog())
{
imageHandler.SetBitmap((Bitmap)Bitmap.FromFile(oDlg.FileName));
imageHandler.BitmapPath = oDlg.FileName;
this.AutoScroll = true;
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height));
this.Invalidate();
menuItemImageInfo_Click(0,e);//вывод информации о изображении
}
}
private void menuItemUndo_Click(object sender, EventArgs e)//функция отмены действия
{
imageHandler.ResetBitmap();
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height ));
//пересчитываем минимальную область для прокрутки
this.Invalidate();//перерисовываем изображение
}
private void menuItemImageInfo_Click(object sender, EventArgs e)//функция вывода информации о изображении
{
menuItemImageInfo.Enabled = true;
ImageInfo imgInfo = new ImageInfo(imageHandler);
imgInfo.Show();
}
private void menuItemZoom50_Click(object sender, EventArgs e)
{
cZoom.Checked = false;
menuItemZoom50.Checked = true;
cZoom = menuItemZoom50;
imageHandler.BiInterp((int)(imageHandler.TrueWidth * 0.5), (int) (imageHandler.TrueHeight * 0.5));
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height ));
this.Invalidate();
}
private void menuItemZoom100_Click(object sender, EventArgs e)
{
cZoom.Checked = false;
menuItemZoom100.Checked = true;
cZoom = menuItemZoom100;
imageHandler.BiInterp(imageHandler.TrueWidth , imageHandler.TrueHeight );
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height ));
this.Invalidate();
}
private void menuItemZoom150_Click(object sender, EventArgs e)
{
cZoom.Checked = false;
menuItemZoom150.Checked = true;
cZoom = menuItemZoom150;
imageHandler.BiInterp((int)(imageHandler.TrueWidth * 1.5), (int)(imageHandler.TrueHeight * 1.5));
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width), Convert.ToInt32(imageHandler.Height));
this.Invalidate();
}
private void menuItemZoom200_Click(object sender, EventArgs e)
{
cZoom.Checked = false;
menuItemZoom200.Checked = true;
cZoom = menuItemZoom200;
imageHandler.BiInterp(imageHandler.TrueWidth * 2, imageHandler.TrueHeight * 2);
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height ));
this.Invalidate();
}
private void menuItemZoom300_Click(object sender, EventArgs e)
{
cZoom.Checked = false;
menuItemZoom300.Checked = true;
cZoom = menuItemZoom300;
imageHandler.BiInterp(imageHandler.TrueWidth * 3, imageHandler.TrueHeight*3);
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height ));
this.Invalidate();
}
private void menuItemZoom400_Click(object sender, EventArgs e)
{
cZoom.Checked = false;
menuItemZoom400.Checked = true;
cZoom = menuItemZoom400;
imageHandler.BiInterp(imageHandler.TrueWidth * 4, imageHandler.TrueHeight * 4);
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height ));
this.Invalidate();
}
private void menuItemZoom500_Click(object sender, EventArgs e)
{
cZoom.Checked = false;
menuItemZoom500.Checked = true;
cZoom = menuItemZoom500;
imageHandler.BiInterp(imageHandler.TrueWidth * 5, imageHandler.TrueHeight * 5);
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height ));
this.Invalidate();
}
private void menuItemFlipH_Click(object sender, EventArgs e)
{
imageHandler.RotateFlip(RotateFlipType.RotateNoneFlipX);//Задает отсутствие поворота по часовой стрелке с последующим зеркальным отражением по горизонтали
this.Invalidate();
}
private void menuItemFlipV_Click(object sender, EventArgs e)
{
imageHandler.RotateFlip(RotateFlipType.RotateNoneFlipY);//Задает отсутствие поворота по часовой стрелке с последующим зеркальным отражением по вертикали
this.Invalidate();
}
private void pictureBox1_KeyDown(object sender, KeyEventArgs e)//функция вызывается при перемещении выделенной области
{
if (e.KeyCode == Keys.Right)
{
pictureBox1.Location = new System.Drawing.Point(cropX + 10, cropY);//перемещает pictureBox1 по X на 10 вправо
cropX = cropX + 10;
}
if (e.KeyCode == Keys.Left)
{
pictureBox1.Location = new System.Drawing.Point(cropX - 10, cropY);//перемещает pictureBox1 по X на 10 влево
cropX = cropX - 10;
}
if (e.KeyCode == Keys.Up)
{
pictureBox1.Location = new System.Drawing.Point(cropX, cropY - 10);//перемещает pictureBox1 по Y на 10 вниз
cropY = cropY - 10;
}
if (e.KeyCode == Keys.Down)
{
pictureBox1.Location = new System.Drawing.Point(cropX, cropY + 10);//перемещает pictureBox1 по Y на 10 вверх
cropY = cropY + 10;
}
}
private void menuItemCrop_Click(object sender, EventArgs e)//функция вызывается при выделении области
{
bool flag = false;//объявления флага на случай выхода области выделения за приделы изображения
CropForm cpFrm = new CropForm();//создаем форму для определения параметров выделения
do
{
flag = false;
cpFrm.CropXPosition = 0;
cpFrm.CropYPosition = 0;
cpFrm.CropWidth = imageHandler.Width;//отображаем на форме выделения ширину
cpFrm.CropHeight = imageHandler.Height;//и высоту изображения для удобства определения параметров
if (cpFrm.ShowDialog() == DialogResult.OK)
{
Rectangle rec = new Rectangle(cpFrm.CropXPosition, cpFrm.CropYPosition, cpFrm.CropWidth, cpFrm.CropHeight);//создаем прямоугольник с саданными параметрами выделения
this.Cursor = Cursors.WaitCursor;//курсор в режиме ожидания
imageHandler.RestorePrevious();//точка сохранения для возврата
imageHandler.DrawOutCropArea(cpFrm.CropXPosition, cpFrm.CropYPosition, cpFrm.CropWidth, cpFrm.CropHeight);//вызов функции выделения выбранной области
this.Invalidate();
if (MessageBox.Show("Выделить выбранную область?", "ImageProcessing", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
{
try
{
cropX = cpFrm.CropXPosition; cropY = cpFrm.CropYPosition; widthImgCrop = cpFrm.CropWidth; heightImgCrop = cpFrm.CropHeight;
temp = (Bitmap)imageHandler.GetBitmap();
Bitmap bmap = (Bitmap)temp.Clone();// копия картинки
Graphics gr = Graphics.FromImage(bmap);//создает объект Graphics из картинки
RectangleF cloneRect = new RectangleF(cropX, cropY, widthImgCrop, heightImgCrop);// прямоугольник соотв выделеной области
System.Drawing.Imaging.PixelFormat format = bmap.PixelFormat;//
cloneBitmap = bmap.Clone(cloneRect, format);// вырезка куска из картинке по выделеной области cloneRect
pictureBox1.Location = new System.Drawing.Point(cropX, cropY);// устанавливаем pictureBox для вывода картинок в коордиаты Х У т. е. на месте где и была выделена область
pictureBox1.Image = cloneBitmap;// помещаем картинку
pictureBox1.Size = new System.Drawing.Size(Convert.ToInt32(widthImgCrop), Convert.ToInt32(heightImgCrop));//размеры штуки для вывода
pictureBox1.Visible = true;//pictureBox1 с выделенным изображением становится видимой
imageHandler.RemoveCropAreaDraw();
this.saveImgImg.Enabled = true;
this.deleteCrop.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(this,"Выделена область вне картинки!", "Внимание", MessageBoxButtons.OK);
flag=true;
}
}
else
{
imageHandler.RemoveCropAreaDraw();//отмена выделения выбранной области
}
this.AutoScroll = true;
this.AutoScrollMinSize = new Size(Convert.ToInt32(imageHandler.Width ), Convert.ToInt32(imageHandler.Height));
this.Invalidate();
this.Cursor = Cursors.Default;
imageHandler.RemoveCropAreaDraw();
this.Invalidate();
}
}
while(flag==true);
this.Invalidate();
this.Cursor = Cursors.Default;
}
private void saveImg_Click(object sender, EventArgs e)//сохранение изображения без выделенной области
{
if (DialogResult.OK == sDlg1.ShowDialog())
{
imageHandler.SaveBitmap(sDlg1.FileName);
}
}
private void saveImgImg_Click(object sender, EventArgs e)
{
{
if (DialogResult.OK == sDlg2.ShowDialog())
{
imageHandler.PasteTogether(cloneBitmap, cropX, cropY).Save(sDlg2.FileName);//сохраняю изображение
}
}
}
private void deleteCrop_Click_1(object sender, EventArgs e)
{
pictureBox1.Visible = false;//pictureBox1 делаем невидимым
saveImgImg.Enabled = false;
deleteCrop.Enabled = false;
}
private void menuItemExit_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
namespace ImageProcessing
{
public class ImageHandler
{
private string _bitmapPath;//переменная для хранения адресса для сохр изображения
public Bitmap _currentBitmap = null;//текущее изображение
int[][] colorOfPixel; // матрица для хранения значений пикселей текущего (обрабатываемого) изображения
int[][] beforeProcessing; // матрица для хранения значений пикселей изображения перед изменением
int trueWidth; // начальная длинна изображения
int trueHeight;// начальная высота изображения
bool isPicture = false;// наличие обрабатываемой картинки
public bool IsPicture//проверка на наличие обрабатываемой картинки в классе
{
get { return isPicture; }
}
public int Width//получение ширины текущего изображения
{
get { return colorOfPixel.Length; }
}
public int Height//получение высоту текущего изображения
{
get { return colorOfPixel[0].Length; }
}
public int TrueWidth//получение ширины начального изображения
{
get { return trueWidth; }
}
public int TrueHeight//получение высоты начального изображения
{
get { return trueHeight; }
}
public Bitmap GetBitmap()//получение текущего изображения
{
return _currentBitmap;
}
public string BitmapPath//получение пути к изображению
{
get { return _bitmapPath; }
set { _bitmapPath = value; }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//РАБОТА С ПОЛУЧЕНИЕМ ИЗ ИЗОБРАЖЕНИЯ МАТРИЦЫ ПИКСЕЛЕЙ И ПОЛУЧЕНИЯ ИЗОБРАЖЕНИЯ ИЗ МАТРИЦЫ ПИКСЕЛЕЙ
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void SetBitmap(Bitmap bitmap)//задание обрабатываемого изображения
{
isPicture = true;
trueWidth = bitmap.Width;
trueHeight = bitmap.Height;
colorOfPixel = MakeMatrixs(bitmap);
beforeProcessing = (int[][])colorOfPixel.Clone() ;
CreateBitmap();
}
void CreateBitmap()//замена текущего изображения на полученной из массива пикселей colorOfPixel
{
_currentBitmap = MakeBitmap(colorOfPixel, colorOfPixel.Length, colorOfPixel[0].Length);
}
int[][] MakeMatrixs(Bitmap bitmap)//получение матрицы пикселей из картинки
{
int height = bitmap.Height;
int width = bitmap.Width;
int[][] colorOfPixel = new int[width][];//выделение места под матрицу
for (int i = 0; i < width; i++)
{
colorOfPixel[i] = new int[height];//выделение места под матрицу
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
colorOfPixel[j][i] = bitmap.GetPixel(j, i).ToArgb();//копирование пикселей
}
}
return colorOfPixel;//возврат матрицы
}
public Bitmap MakeBitmap(int[][] matrix, int width, int height)//функция собирает изображение из массива пикселей
{
Bitmap bm = new Bitmap(width, height);//оздание изображения с нужным размером
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
bm.SetPixel(j, i, Color.FromArgb(matrix[j][i]));//заполнение изображения
}
}
return bm;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ОТОБРАЖЕНИЕ ИЗОБРАЖЕНИЯ
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void RotateFlip(RotateFlipType rotateFlipType)//функция зеркального отображения изображения
{
beforeProcessing = colorOfPixel;
int[][] arry = new int[colorOfPixel.Length][];//выделение места под матрицу
for (int i = 0; i < colorOfPixel.Length; i++)
{
arry[i] = new int[colorOfPixel[0].Length];//выделение места под матрицу
}
if (rotateFlipType == RotateFlipType.RotateNoneFlipX)
{
for (int i = 0; i < colorOfPixel[0].Length; i++)
{
for (int j = 0; j < colorOfPixel.Length; j++)
{
arry[colorOfPixel.Length - j - 1][i] = colorOfPixel[j][i]; //перемещение по оси Х
}
}
}
if (rotateFlipType == RotateFlipType.RotateNoneFlipY)
{
for (int i = 0; i < colorOfPixel[0].Length; i++)
{
for (int j = 0; j < colorOfPixel.Length; j++)
{
arry[j][colorOfPixel[0].Length - i - 1] = colorOfPixel[j][i]; //перемещение по оси У
}
}
}
colorOfPixel = null;
colorOfPixel = arry;
arry = null;
CreateBitmap();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ВЫДЕЛЕНИЕ ОБЛАСТИ
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void DrawOutCropArea(int xPosition, int yPosition, int width, int height)//выделения выбранной области
{
Bitmap bmap = _currentBitmap;//копируем текущую картинку
Graphics gr = Graphics.FromImage(bmap);//Graphics из рисунка
Brush cBrush = new Pen(Color.FromArgb(150, Color.White)).Brush;//кисть для закраски изображения
Rectangle rect1 = new Rectangle(0, 0, _currentBitmap.Width, yPosition);//выделяю
Rectangle rect2 = new Rectangle(0, yPosition, xPosition, height);//четыре
Rectangle rect3 = new Rectangle(0, (yPosition + height), _currentBitmap.Width, _currentBitmap.Height);//прямоугольника без
Rectangle rect4 = new Rectangle((xPosition + width), yPosition, (_currentBitmap.Width - xPosition - width), height);//выделенной области
gr.FillRectangle(cBrush, rect1);//закрашиваем
gr.FillRectangle(cBrush, rect2);//эти
gr.FillRectangle(cBrush, rect3);//прямоугольники
gr.FillRectangle(cBrush, rect4);//в более светлый оттенок
}
public Bitmap PasteTogether(Bitmap bmp, int x, int y)// склеивание изображения с текущим У и Х - координаты положения
//склеиваемого изображения относительно точки (0,0) текущего
{
int maxX = colorOfPixel.Length, maxY = colorOfPixel[0].Length;
int[][] matrixBmp = MakeMatrixs(bmp);
int[][] newMatrixs;
if (maxX < x + bmp.Width)//определение длинны новой картинки
{
maxX = x + bmp.Width;
}
if (maxY < y + bmp.Height)//опред. высоты новой картинки
{
maxY = y + bmp.Height;
}
newMatrixs = new int[maxX][];//выделение места под массив новой картинки
for (int i = 0; i < maxX; i++)//выделение места под массив новой картинки
{
newMatrixs[i] = new int[maxY];
}
for (int i = 0; i < colorOfPixel[0].Length; i++)
{
for (int j = 0; j < colorOfPixel.Length; j++)
{
newMatrixs[j][i] = colorOfPixel[j][i];//копирование текущей картинки в новую
}
}
for (int i = 0; i < bmp.Height; i++)
{
for (int j = 0; j < bmp.Width; j++)
{
newMatrixs[j + x][i + y] = colorOfPixel[j][i];//наложение склеиваемой картинки
}
}
return MakeBitmap(newMatrixs, maxX, maxY);//получение изобржения по масиву пикселей
}
public void RemoveCropAreaDraw()//отмена выделения выбранной области
{
CreateBitmap();//замена текущего изображения на сделанное по хранящейся матрице
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//БИЛИНЕЙНАЯ ИНТЕРПОЛЯЦИЯ
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void BiInterp(int newX, int newY) //увеличение | уменьшение картинки newX - новая длинна, newY - новая высота
{
colorOfPixel = Resample(colorOfPixel, colorOfPixel.Length, colorOfPixel[0].Length, newX, newY);
CreateBitmap();
}
int[][] Resample(int [][] colorOfPixel,int width, int height, int newX, int newY)//билинейная интерполяция
{
int i, j;
int h, w;
float t;
float u;
float tmp;
float d1, d2, d3, d4;//коэфициенты
int p1, p2, p3, p4; /* Окрестные пикселы */
int p1Col, p2Col, p3Col, p4Col; //для отбора составляющего цвета
int red, green, blue;
int[][] newMatrix = new int[newX][];
for ( i = 0; i < newX; i++)
{
newMatrix[i] = new int[newY];
}
for (j = 0; j < newY; j++)
{
tmp = (float) (j) / (newY - 1) * (height - 1);
h = (int) Math.Floor(tmp);
if (h < 0)
{
h = 0;
}
else
{
if (h >= height - 1)
{
h = height - 2;
}
}
u = tmp - h;
for (i = 0; i < newX; i++)
{
tmp = (float)(i) / (newX - 1) * (width - 1);
w = (int) Math.Floor(tmp);
if (w < 0)
{
w = 0;
}
else
{
if (w >= width - 1)
{
w = width - 2;
}
}
t = tmp - w;
/* Коэффициенты */
d1 = (1 - t) * (1 - u);
d2 = t * (1 - u);
d3 = t * u;
d4 = (1 - t) * u;
/* Окрестные пиксели: a[i][j] */
p1 = colorOfPixel[w][h];
p2 = colorOfPixel[w + 1][h];
p3 = colorOfPixel[w + 1][h + 1];
p4 = colorOfPixel[w][h + 1];
p1Col = p1 & 255; // отбираем значение blue
p2Col = p2 & 255;
p3Col = p3 & 255;
p4Col = p4 & 255;
blue = (byte)(p1Col * d1 + p2Col * d2 + p3Col * d3 + p4Col * d4);
p1Col = p1 & 65280; /* отбираем значение green*/ p1Col >>= 8;// сдвигаем в начало переменной
p2Col = p2 & 65280; p2Col >>= 8;
p3Col = p3 & 65280; p3Col >>= 8;
p4Col = p4 & 65280; p4Col >>= 8;
green = (byte)(p1Col * d1 + p2Col * d2 + p3Col * d3 + p4Col * d4);
p1Col = p1 & 16711680; /* отбираем значение red */ p1Col >>= 16; // сдвигаем в начало переменной
p2Col = p2 & 16711680; p2Col >>= 16;
p3Col = p3 & 16711680; p3Col >>= 16;
p4Col = p4 & 16711680; p4Col >>= 16;
red = (byte)(p1Col * d1 + p2Col * d2 + p3Col * d3 + p4Col * d4);
newMatrix[i][j] = (255 << 24) | (red << 16) | (green << 8) | blue;// составление цвета 255 - значение альфа канала
}
}
return newMatrix;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//РАБОТА С ВОЗВРАТОМ НА ШАГ НАЗАД
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void ResetBitmap()//Возврат на шаг назад
{
if (beforeProcessing != null && colorOfPixel != null)//если текущее изображение не равно нулю и изображение до выполнения процесса не равно нулю
{
int[][] arry = colorOfPixel;
colorOfPixel = beforeProcessing;
beforeProcessing = arry;
CreateBitmap();
arry = null;
}
}
public void SaveBitmap(string saveFilePath)//функция сохранения изображения
{
_bitmapPath = saveFilePath;
if (System.IO.File.Exists(saveFilePath))
System.IO.File.Delete(saveFilePath);
GetBitmap().Save(saveFilePath);
}
public void RestorePrevious()//функция сохранения изображения до выполнения выделения области
{
beforeProcessing = (int[][])colorOfPixel.Clone();//изображения до выполнения выделения=текущему изображения
}}}
Размещено на Allbest.ru
Подобные документы
Общие сведения о графических редакторах, понятия компьютерной растровой и векторной графики, форматов. Обзор и сравнительный анализ современных программ обработки и просмотра графических изображений: Paint, Corel Draw, Adobe Photoshop, MS PowerPoint.
дипломная работа [283,9 K], добавлен 09.08.2010Общая информация о графическом формате. Описание формата Microsoft Windows Bitmap. Структура файла DDВ исходного формата ВМР. Преобразования графических файлов. Просмотр и редактирование растровых изображений. Создание многодокументного приложения.
дипломная работа [1,5 M], добавлен 06.06.2010Характеристика цифровых изображений, применяющиеся в издательской деятельности. Отличительные особенности растровых и векторных изображений, понятие цветового охвата, изучение моделей для описания отраженных цветов. Форматы и виды графических файлов.
контрольная работа [22,9 K], добавлен 16.09.2010Основные категории изображений: растровые и векторные. Программы, работающие с растровыми изображениями. Инструменты для работы с обоими типами графики в программе Photoshop. Обзор современных программ обработки и просмотра графических изображений.
курсовая работа [49,0 K], добавлен 20.09.2010Виды компьютерной графики. Photoshop – программа для создания и обработки растровой графики. Пакет программ для работы с векторной графикой CorelDraw. Обработка растровых изображений с использованием Photoshop. Этапы создания коллажа на тему "Музыка".
курсовая работа [2,3 M], добавлен 27.12.2014Редактирование аналоговых и цифровых изображений. Описание графических форматов файла. Алгоритм отображения файла и реализации эффектов. Программа для работы с графическими форматами. Назначение и взаимодействие модулей. Перечень процедур и функций.
курсовая работа [516,8 K], добавлен 28.05.2013Растровая графика, составление графических изображений из отдельных точек (пикселей). Растровые графические редакторы. Векторная графика - построение изображения из простых объектов. Достоинства, недостатки и применение растровой и векторной графики.
презентация [7,8 K], добавлен 06.01.2014Виды графических редакторов. Форматы файлов для хранения растровых графических изображений. Среда графического редактора. Панели инструментов и режимы работы графических редакторов. Инструменты редактирования рисунка. Изменение шрифта текста на рисунке.
контрольная работа [246,6 K], добавлен 16.12.2010Обработка изображений на современных вычислительных устройствах. Устройство и представление различных форматов изображений. Исследование алгоритмов обработки изображений на базе различных архитектур. Сжатие изображений на основе сверточных нейросетей.
дипломная работа [6,1 M], добавлен 03.06.2022Общие сведения о графической информации. Характеристика растровой, векторной и демонстрационной графики. Обзор программ обработки и просмотра графических изображений Paint, Adobe Photoshop, MS Power Point, ACDSee. Возможности графических редакторов.
курсовая работа [55,7 K], добавлен 01.07.2010