Водяной знак на BMP (командный проект)
Командный проект на троих: программа на C++ накладывает водяной знак на 24-битное BMP, работа ведётся в общем репозитории на GitHub, сборку и тесты проверяет GitHub Actions.
Задание
Командный проект на троих: программа на C++, которая накладывает водяной знак (второе BMP-изображение) на исходное BMP и сохраняет результат в новый файл. Вся работа ведётся в общем репозитории на GitHub, сборку и тесты проверяет GitHub Actions.
Цель — не только сама программа, но и совместная работа с Git: ветки, слияния, разрешение конфликтов, Pull Request’ы и код-ревью, понятная история коммитов от каждого участника.
Роли в команде
Студент 1 — класс для BMP
- Класс (например,
ImageBMP) с полями ширины, высоты, глубины цвета и массивом пикселей, методыload(filename)иsave(filename). - Чтение и запись через
std::ifstream/std::ofstreamс флагомstd::ios::binary, проверкаis_open()и того, что прочитано столько байт, сколько ожидалось. - Разбор заголовков вручную, без готовых библиотек для изображений:
#pragma pack(push, 1)-структуры подBITMAPFILEHEADERиBITMAPINFOHEADERили чтение полей по одному. - Учёт порядка строк bottom-up и выравнивания строк до 4 байт (подробнее — ниже).
- При сохранении — пересчёт
bfSizeиbiSizeImage, запись padding’а в конце каждой строки. - Комментарии к неочевидным шагам: разбор заголовка, смещение до пикселей, padding.
Студент 2 — наложение водяного знака
- Функция
applyWatermark(base, mark)или метод класса, который смешивает два изображения, загруженных классом студента 1. - Если водяной знак меньше основного изображения — разместить его в выбранной области (правый нижний угол, центр) и менять только её; если больше — наложить по пересечению или вернуть ошибку.
- Небольшие проверочные примеры: картинки 5×5 или 10×10, наложение белого, чёрного, самого на себя.
- Своя ветка (например,
watermark-feature) и слияние с кодом студента 1 без потери чужих изменений, лучше через Pull Request.
Студент 3 — интеграция, сборка, CI и README
- Ревью кода студентов 1 и 2, исправления или замечания авторам.
main.cpp: пути к исходному изображению, водяному знаку и результату (черезargvили ввод с консоли), загрузка, наложение, сохранение, сообщения о ходе работы.- Понятные ошибки: подсказка по использованию без аргументов, «Файл водяного знака не найден», «Размеры изображений не совпадают» и т. п. Программа не должна падать на несуществующем файле.
- Сборка через CMake (или по согласованию с преподавателем), раскладка по папкам,
.gitignoreдля сборочных файлов и бинарников. - Workflow GitHub Actions, тесты, бейдж статуса и
README.md.
Формат BMP
Достаточно поддержать несжатый 24-битный BMP (Windows Bitmap v3 с заголовком BITMAPINFOHEADER):
| Часть | Размер | Что внутри |
|---|---|---|
BITMAPFILEHEADER | 14 байт | сигнатура BM, размер файла, зарезервированные поля, смещение до пикселей bfOffBits |
BITMAPINFOHEADER | 40 байт | размер структуры, ширина, высота, число плоскостей, бит на пиксель (24), сжатие (BI_RGB = 0), размер изображения (может быть 0), разрешение, число цветов |
| Пиксели | с bfOffBits (обычно 54) | по 3 байта на пиксель в порядке B, G, R |
padding = (4 - width * 3 % 4) % 4.Порядок байтов в BMP — little-endian, на x86 он совпадает с порядком в памяти, поэтому структуры можно читать напрямую.
Алгоритм наложения
Для каждого пикселя области водяного знака новый цвет — смесь исходного и цвета метки:
При это просто среднее: (orig + mark) / 2. Чтобы знак был прозрачнее, берут : 70% оригинала и 30% метки. Значение и его выбор стоит объяснить в комментарии.
uint8_t не помещается в байт: 200 + 100 превратится в 44. Считайте в int (или float для ) и только в конце приводите результат обратно к uint8_t в диапазоне 0–255.Проверки здравого смысла при : белый водяной знак осветляет картинку наполовину, чёрный — затемняет, изображение, наложенное само на себя, не меняется.
Git и GitHub
- Один общий репозиторий на GitHub (например,
bmp-watermark-project), у всех троих есть доступ: Collaborators или организация. - Работа в ветках по задачам (
bmp-class-dev,watermark-feature,integration), слияние в основную ветку, по возможности через Pull Request с ревью. - Частые коммиты с осмысленными сообщениями. В истории должен быть виден вклад каждого: класс BMP — коммиты студента 1, наложение — студента 2,
main, CI и README — студента 3.
CI на GitHub Actions
Workflow (например, .github/workflows/ci.yml) запускается на push и pull_request в основную ветку, собирает проект на ubuntu-latest и гоняет тесты:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
- run: cmake --build build
- run: ctest --test-dir build --output-on-failureБез CMake шаг сборки может быть прямым вызовом компилятора, например g++ -std=c++17 -Wall -Wextra -O2 -o watermark main.cpp bmp.cpp watermark.cpp. После первого прогона скопируйте бейдж статуса из вкладки Actions в начало README.
Тесты
- Тестовые изображения в репозитории (папка
examples/илиtests/):original.bmp,watermark.bmpи ожидаемыйexpected.bmp. - Unit-тест смешивания: функция вроде
blendPixel(orig, mark)на известных значениях. - Синтетический тест: в коде создать зелёное и красное изображения, наложить и проверить несколько пикселей результата.
- Обратная проверка: сохранить результат, загрузить снова и убедиться, что размеры и заголовок верные, а пиксели изменились только в области наложения.
Порядок работы
- Создать репозиторий с
README.md, сделать первый коммит иpush, выдать доступ остальным. - Вместе спланировать архитектуру: классы и функции, коэффициент , позицию знака, тестовые файлы, порядок слияния веток.
- Студент 1 реализует и отлаживает чтение и запись BMP на маленьких картинках (2×2, 3×3), вливает в основную ветку.
- Студент 2 подтягивает класс, реализует наложение в своей ветке, проверяет на примерах и открывает Pull Request.
- Студент 3 делает ревью, пишет
main, обработку ошибок, CMake, workflow и тесты, разрешает конфликты. - Прогон на настоящих картинках: фотография и небольшой логотип, проверка результата в просмотрщике.
- README, финальный коммит, зелёный статус Actions.
Требования
- Программа на C++17 или новее читает 24-битные BMP без сжатия и сохраняет результат в новый BMP, который открывается обычным просмотрщиком.
- Разбор BMP написан самостоятельно, без библиотек для изображений; учтены порядок строк bottom-up и padding.
- Наложение полупрозрачное: водяной знак виден, исходное изображение просматривается; нет переполнения при смешивании цветов.
- Код разнесён по заголовкам и файлам реализации, функции короткие, неочевидные места прокомментированы, стиль именования единый.
- Ошибки обрабатываются с понятными сообщениями: нет аргументов, файл не найден, неподдерживаемый формат, несовместимые размеры.
- Сборка через CMake, Makefile или описанную команду; в репозитории нет сборочных файлов и бинарников (
.gitignore). - Workflow GitHub Actions собирает проект и запускает тесты на
pushиpull_request, статус последнего коммита — зелёный. - В репозитории есть тестовые изображения и ожидаемый результат.
- В истории Git — много осмысленных коммитов от каждого из трёх участников.
README.mdописывает задачу, устройство решения, алгоритм смешивания, сборку и запуск с примером, тесты, состав команды и роли, результаты «до и после», возможные улучшения.
Как сдавать
Ссылка на публичный репозиторий на GitHub с зелёным статусом Actions. На защите — показать запуск программы, результат в просмотрщике, историю коммитов и Pull Request’ы; каждый участник рассказывает свою часть.

Комментарии0
Пока никто ничего не написал.
Войдите, чтобы оставить комментарий