В этом задании требуется реализовать консольное приложение, позволяющее применять к изображениям различные фильтры, аналогичные фильтрам в популярных графических редакторах.
Входные и выходные графические файлы должны быть в формате BMP.
Формат BMP поддерживает достаточно много вариаций, но в этом задании будет использоваться
24-битный BMP без сжатия и без таблицы цветов. Тип используемого DIB header
- BITMAPINFOHEADER
.
Пример файла в нужном формате есть в статье на Википедии в разделе "Example 1" и в папке test_script/data.
При тестировании обязательно обращайте внимание на то, чтобы тестовое изображение было сохранено именно в 24-битном BMP.
Описание формата аргументов командной строки:
{имя программы} {путь к входному файлу} {путь к выходному файлу} [-{имя фильтра 1} [параметр фильтра 1] [параметр фильтра 2] ...] [-{имя фильтра 2} [параметр фильтра 1] [параметр фильтра 2] ...] ...
При запуске без аргументов программа выводит справку.
./image_processor input.bmp /tmp/output.bmp -crop 800 600 -gs -blur 0.5
В этом примере
- Загружается изображение из файла
input.bmp
- Обрезается до изображения с началом в верхнем левом углу и размером 800х600 пикселей
- Переводится в оттенки серого
- Применяется размытие с сигмой 0.5
- Полученное изображение сохраняется в файл
/tmp/output.bmp
Список фильтров может быть пуст, тогда изображение должно быть сохранено в неизменном виде. Фильтры применяются в том порядке, в котором они перечислены в аргументах командной строки.
В формулах далее считаем, что каждая компонента цвета
представлена вещественным числом от 0 до 1. Цвета пикселей
представлены тройками (R, G, B)
. Таким образом, (0, 0, 0)
– черный,
(1, 1, 1)
– белый.
Если фильтр задан матрицей, это означает, что значение каждого из цветов определяется взвешенной суммой значений этого цвета в соседних пикселях в соответствии с матрицей. При этом целевому пикселю соответствует центральный элемент матрицы.
Например, для фильтра, заданного матрицей
Значение каждого из цветов целевого пикселя C[x][y]
будет определяться формулой
C[x][y] =
min(1, max(0,
1*C[x-1][y-1] + 2*C[x][y-1] + 3*C[x+1][y-1] +
4*C[x-1][y] + 5*C[x][y] + 6*C[x+1][y] +
7*C[x-1][y+1] + 8*C[x][y+1] + 9*C[x+1][y+1]
))
При обработке пикселей, близких к краю изображения, часть матрицы может выходить за границу изображения. В таком случае в качестве значения пикселя, выходящего за границу, следует использовать значение ближайшего к нему пикселя изображения.
Обрезает изображение до заданных ширины и высоты. Используется верхняя левая часть изображения.
Если запрошенные ширина или высота превышают размеры исходного изображения, выдается доступная часть изображения.
Преобразует изображение в оттенки серого по формуле
Преобразует изображение в негатив по формуле
Повышение резкости. Достигается применением матрицы
Выделение границ. Изображение переводится в оттенки серого и применяется матрица
Пиксели со значением, превысившим threshold
, окрашиваются в белый, остальные – в черный.
Гауссово размытие, параметр – сигма.
Значение каждого из цветов пикселя C[x0][y0]
определяется формулой
Существуют различные варианты релализации и оптимизации вычисления этого фильтра, описание есть в Википедии.
Дополнительно надо сделать один собственный фильтр.
Фильтр должен быть нетривиальным. Идеи можно взять здесь.
Хорошие примеры: Crystallize, Glass Distortion.
Выбор собственного фильтра надо согласовать с семинаристом.
Авторы самых интересных (по мнению лектора) фильтров получат бонус к баллам.
Применять сторонние библиотеки для работы с изображениями запрещено.
Старайтесь делать все компоненты программы по возможности более универсальными и не привязанными к специфике конкретной задачи.
Все исключительные ситуации должны корректно обрабатываться с выводом понятного пользователю сообщения об ошибке. Для этого используйте механизм исключений. Никакие сценарии, включая использование файлов с форматом, не соответствующим спецификации, не должны приводить к падению программы.
Для чтения и записи файлов используйте std::ifstream и std::ofstream.
Скорее всего, вам понадобятся следующие компоненты:
- Класс, представляющий изображение и обеспечивающий работу с ним
- Классы для чтения и записи формата BMP
- Фильтры
- Контроллер, управляющий последовательным применением фильтров
Общие части следует выделить через наследование.
Подробный дизайн программы рекомендуется обсудить с преподавателем на семинарах.
Проект проверяется преподавателями. Все сдачи будут проходить код ревью. Автомерж роботом для проекта не применяется.
Вам предстоит написать всю программу с нуля.
В корневом CMakeLists.txt
задачи должен быть описан исполняемый файл с именем image_processor
,
в остальном вы можете менять файлы CMakeLists.txt
как угодно.
Для отправки кода проекта используйте ветку submits/image_processor
.
Минимальная реализация проекта оценивается в 3 балла и должна содержать:
- Класс для представления цвета
- Класс для представления изображения
- Классы или функции для загрузки изображения из формата BMP и сохранения изображения в BMP
- Один класс фильтра
Решения, не удовлетворяющие требованиям к минимальной реализации, оцениваются в 0 баллов.
Если решение удовлетворяет требованиям к минимальной реализации, дополнительно начисляется 0.6 балла за каждый реализованный базовый фильтр (кроме входящего в минимальную реализацию). Таким образом, за фильтры можно получить еще до 3 баллов.
Если реализовано не менее 5 фильтров и фильтры образуют полную иерархию наследования, начисляется еще 2 балла.
За реализованный дополнительный фильтр начисляется 1 балл. Дополнительный фильтр можно сдавать, если реализовано не менее 5 базовых фильтров.
За покрытие юнит тестами всех критичных компонентов начисляется 1 балл. Ваш семинарист поможет с определением достаточности покрытия.
Баллы могут быть сняты за серьезные недочеты, например:
- Отсутствие декомпозиции на файлы, классы, методы и функции
- Утечки памяти
- Падение программы
- на файлах неверного формата
- при вызове фильтров с некорректными аргументами
- при вызове некорректных фильтров
- Неверный результат работы фильтров
- Нечитаемый код
- Нарушение стиля кодирования
- UB на каком-либо входе или наборе аргументов функции
- Выбор неэффективных структур данных или их неэффективное использование
- Лишние копирования объектов
- Неверные сигнатуры методов
Для проекта установлен жесткий дедлайн 23:59 30.10.2023
- это означает, что решения,
отправленные после этого времени, не будут оцениваться.
Дополнительных штрафов за время сдачи нет.