TextGraphicsConverter
Конвертер в текстовую графику
Вас пригласили поучаствовать в разработке приложения, умеющего скачивать картинки по URL и конвертировать изображения в текстовую графику (т. е. в текст из разных символов, которые в совокупности выглядят как изображение). Вот пример его работы. Картинка на нём — это текст из мелких символов:

Скачиваем проект
Часть приложения уже написана. Ваша задача — доработать его основную логическую часть в соответствии с требованиями. Поэтому для начала работы нужно скачать заготовку проекта. Для этого откройте идею, выберите в меню . В открывшемся окне в поле URL введите , как показано на картинке, и нажмите Clone.

Если после нажатия выскочила ошибка об отсутствии гита на вашем компьютере, установите гит по этой инструкции и попробуйте снова.
После того как идея скачает проект, убедитесь, что для него выбрана версия Java. Откройте и убедитесь, что это так. Версия должна быть 11-й.

После откройте класс и запустите метод . Запуск должен завершиться ошибкой:
Exception in thread "main" java.lang.IllegalArgumentException: Серверу нужно передать в конструктор объект-конвертер, а было передано null.
at ru.netology.graphics.server.GServer.<init>(GServer.java:24)
at ru.netology.graphics.Main.main(Main.java:13)
Если вы видите эту ошибку, проект настроен верно. Если нет, напишите своему руководителю по курсовой, он подскажет с настройкой.
Структура проекта
Перед вами java-проект с несколькими незнакомыми вам папками (например, ), которые вам не нужно будет трогать. Нас будут интересовать .java-файлы, которые располагаются по пакетам:

| Класс / Интерфейс | Для чего? |
|---|---|
| Класс исключения, которое вы будете выбрасывать |
| Интерфейс цветовой схемы, который вы будете реализовывать |
| Интерфейс конвертера картинок, который вы будете реализовывать |
| Готовый класс сервера, который будет использовать ваш конвертер; вам туда не нужно |
| Запуск приложения. В нём запускается сервер, также в нём можно будет конвертировать картинки в текстовые файлы без сервера |
Требования к конвертеру
В проекте уже написан класс сервера, который будет использовать ваш конвертер. Т. к. конвертер ещё не написан, был создан специальный интерфейс , объект которого сервер ждёт параметром в :
Все требования к конвертеру описаны в интерфейсе. Чуть ниже мы их подробнее разберём. Самый главный метод — это метод , который принимает параметром URL в виде текста, например, , внутри метода качает и анализирует картинку, после чего отдаёт значение типа , в котором содержится это изображение в виде текстовой графики.
Помните, что в Java — это текст и не обязательно всего одна строчка текста. Т. е. в один объект типа можно занести многострочный текст,
а разделителем строк (по сути Enter) будет специальный символ, который пишется в коде как . В итоге у вас в конце каждой строчки текстового изображения будет символ переноса строки (запись в коде — ).
Пример работы конвертера, результат которого выводим в консоль:
В итоге мы видим такой результат, где более тёмные участки заменяются на более жирные символы, а светлые на более незаметные символы:

Также интерфейс конвертера требует от него возможность выставлять ему настройки перед конвертацией:
- максимально допустимое соотношение сторон (ширины и высоты). Если метод не вызывали, то любое соотношение допустимо;
- максимально допустимую высоту итогового изображения. Если метод не вызывали, то любая высота допустима;
- максимально допустимую ширину итогового изображения. Если метод не вызывали, то любая ширина допустима;
- текстовую цветовую схему — объект специального интерфейса, который будет отвечать за превращение степени белого (числа от 0 до 255) в символ. Если метод не вызывали, должен использоваться объект написанного вами класса как значение по умолчанию.
Например, следующий конвертер не должен конвертировать, если ширина больше длины в три раза, т. к. максимальное соотношение сторон ему выставлено в 2:
Будьте внимательны: когда вы передадите конвертер серверу, он выставит ему свои желаемые параметры, которые будут влиять на конвертацию:

При этом использовать при реализации конвертера информацию об этих конкретных числах нельзя. Ваш конвертер должен уметь работать с любыми настройками, описанными выше. Т. е. если в сервере поменяют настройки конвертеру, ваш конвертер без изменений кода должен работать с новыми значениями.
Общая схема работы метода будет соответствовать последовательности действий (подробнее описаны ниже):
- Скачиваем картинку по URL.
- Менеджеру могли выставить максимально допустимое соотношение сторон (ширины и высоты); если оно слишком большое, то конвертация не делается и выбрасывается исключение.
- При конвертации мы будем менять каждый пиксель на символ: чем пиксель темнее, тем жирнее символ, который мы подставим. Менеджеру могли выставить максимальные ширину и высоту итоговой картинки, при этом если исходная картинка больше, то нам надо уменьшить её размер, соблюдая пропорции.
- Превращаем цветное изображение в чёрно-белое, чтобы мы смотрели только на интенсивность цвета, а не подбирали для красного одни символы, для зелёного другие и т. п.
- Перебираем все пиксели изображения, спрашивая у них степень белого (число от 0 до 255, где 0 — это чёрный, а 255 — это светлый). В зависимости от этого числа выбираем символ из заранее подготовленного набора.
- Собираем все полученные символы в единую строку, отдаём как результат конвертации.
Костяк метода :
Требования к цветовой схеме
Мы написали интерфейс конвертера так, чтобы сам он не подбирал каждому цвету определённый символ, но чтобы им занимался другой объект следующего интерфейса:
Предлагается следующая логика его работы. Вот список символов от самых тёмных к самым светлым: '▇', '●', '◉', '◍', '◎', '○', '☉', '◌', '-'. Если вы программируете на Windows, рекомендуем другой список из более стандартных символов, иначе может отрисовываться криво: '#', '$', '@', '%', '*', '+', '-', '''. В зависимости от переданного значения интенсивности белого должен выбираться соответствующий символ. Например, если значение близко к 0, то выбрать надо '▇'; если к 255, то '-'. Если где-то посередине, то и выбирать надо тоже где-то посередине.
Подумайте, как это можно реализовать. Вы можете сделать это условными операторами, однако есть и решение в одну строчку. Если у вас совсем не получается придумать, как это сделать, спросите вашего руководителя по курсовой.
В итоге у вас должен быть класс, реализующий этот интерфейс. Если объекту конвертера сеттером не передали иную реализацию этого интерфейса, он должен использовать ваш класс как реализацию по умолчанию.
Внимание: Все ваши новые классы должны быть в пакете , никакие другие классы, кроме класса , менять нельзя.
Тестирование, отладка и решение проблем
После того как вы реализуете классы, откройте класс и заполните переменную для конвертера объектом вашего класса, чтобы он был передан серверу. Теперь после старта метода будет запущен сервер на строке . Сервер будет писать о происходящем в консоль. Если ему удалось успешно стартовать, страница приложения будет доступна по локальному для вашего компьютера адресу http://localhost:8888/ .
Для конвертации достаточно вставить прямую ссылку на картинку в форму и нажать . Если конвертация будет успешной, перед вами будет изображение, выполненное текстовой графикой. Его сервер получит от вашего конвертера. Если конвертер не сможет сконвертировать, то в консоли будет стек-трейс исключения, однако сервер при этом не упадёт, а продолжит работу. На веб-странице будет сообщение о том, что конвертация не удалась.
Для тестирования можете использовать URL следующих изображений:
- Простое маленькое изображение для отладки: https://raw.githubusercontent.com/netology-code/java-diplom/main/pics/simple-test.png
- Другое изображение для демонстрации: https://i.ibb.co/6DYM05G/edu0.jpg
Во время поиска проблем вы также можете в закомментировать секцию, запускающую сервер, и раскомментировать логику, выводящую сконвертированное изображение в консоль. Также вы можете воспользоваться отладчиком:

С чего начать
Вы сами выбираете, с чего вам легче начать. Ниже представлен один из таких вариантов:
- Начните реализацию с класса цветовой схемы. Создайте в пакете
класс, имплементирующий интерфейсru.netology.graphics.image.TextColorSchema - Реализуйте в нём метод конвертации цвета в символ, согласно требованиям к цветовой схеме, которые изложены выше.
- Проверьте вашу цветовую схему. Создайте в
её объект и попробуйте вызвать её метод. Правда ли, что на цветах ближе к белому будут более светлые символы и наоборот? Если это не так, проверьте работу отладчиком.Main - Приступите к реализации класса конвертера. Создайте в пакете
класс, имплементирующий интерфейсru.netology.graphics.image.TextGraphicsConverter - Сначала реализуйте просто метод convert, не обращая внимания на дополнительные требования: проверка картинки на макс. размеры и т. д.
- Создайте объект конвертера и передайте его серверу в
или протестируйте в текстовом режиме, как было описано выше. Если вы сразу не реализовывали функции масштабирования картинки, то тестируйте только на небольших картинках.main - Если конвертация работает, приступайте к реализации настроек конвертера — логики с проверкой на максимальное соотношение сторон, масштабирование картинки и т. д. Реализуйте функциональность по одной за раз, добиваясь работспособности вашего конвертера после каждой волны изменений. При возникновении трудностей пользуйтесь отладчиком.
- Перечитайте условие — все ли требования выполнены? Протестируйте конвертер на разных картинках — работает ли? Если всё хорошо, ознакомьтесь с разделом «Как сдавать» и приступайте к отправке работы на проверку.
Как сдавать
Перед отправкой работы верните класс в исходное состояние, добавив только создание конвертера, т. е. оставьте режим с запуском сервера. Все ваши новые классы должны быть в пакете , никакие другие классы, кроме класса , менять нельзя.
При отправке прикрепите файл и все созданные вами .java-файлы. Другие файлы прикреплять не нужно, также не стоит объединять все файлы в один архив, скидывать ссылку на репозиторий, реплит и прочее.