Конвертируем поней в символы!
Запилил для одного своего проекта программку, ещё весной во время кириновируса. Сейчас дошли руки приделать к ней какой-никакой интерфейс, чтобы можно было дать всем поиграться.
ГалереяLyra
Sweetie Belle
Hive
Yona
NMM & Daybreaker
Marble Pie
Adagio
Building
Подробнее о программеКак видно из скриншотов — основная цель это получить картинку в цветной ASCII графике. Всё пилю под виндой по школьной привычке, соответственно ограничен возможностями её консоли, а именно палитрой всего лишь в 16 цветов. Благо её можно выбирать для каждого рисунка отдельно, а то стандартная цветовая схема это полный трэш.
Программа состоит из следующих основных модулей:
Image осуществляет чтение/запись png-изображений, разбивку их на клетки 8х12 пикселей (стандартный шрифт в консоли семёрки) и перекрас в цвета кастомной палитры (делает это максимально в лоб, безо всякого рассеивания ошибки и прочих ухищрений).
Genetic занимается подбором палитры. Мне было очень интересно поиграть с генетическим алгоритмом на реальной задаче, поэтому взял его. Особь имеет трёхбайтную хромосому c(r,g,b) и по сути является цветом. Фитнес-функция численно равна количеству пикселей на исходной картинке, для которых квадратичная (евклидова) норма разницы цвета x с хромосомой c меньше некой величины sensitivity (этот параметр можно менять)
- ‖x-c‖2 < sensitivity.
- |x-c|max < sensitivity.
Кроссинговер однородный — цепочки из 24 бит у родителей смешиваются по рандомной битовой маске.
Исходная вероятность мутации 10% (выбирал от балды, так и не увидел внятной зависимости).
Критерий останова составной: либо по достижении 25 поколения, либо при становлении параметра мутации 90%. Вероятность мутации растёт в том случае, если фитнес-функция победителя совпала на двух идущих подряд итерациях. Это признак достижения сходимости алгоритма, соответственно возникает проблема определить — действительно ли получен глобальный максимум. После каждого следующего совпадения вероятность мутации растёт на 20%. Таким образом второй критерий срабатывает при совпадении фитнес-функций 5 раз подряд. При этом с каждым разом поиск новых максимумов идёт всё активнее благодаря мутантам. Если даже при вероятности мутации в 70% новых максимумов не обнаружено, а фитнес-функция стабильно держится пятое поколение подряд, имеет смысл говорить о достижении сходимости (с большой вероятностью в глобальный максимум).
Таким образом ищется каждый из пятнадцати цветов, причём после нахождения очередного цвета все пиксели, которые ему соответствуют, блокируются и в дальнейших расчётах фитнес-функций не учавствуют.
Анализ параметра sensitivity на примере8
8+2k
14
При маленьких значениях параметра, цвета подбираются очень строго. Соответственно, например, на двухцветный градиент при sensitivity = 8 подберётся 4 разных цвета в палитру, а при sensitivity = 20 может и вообще всего один. Отсюда вытекает два следствия:
1: чем меньше sensitivity, тем точнее идёт подбор, но тем быстрее заканчиваются свободные слоты в палитре. А у нас их, напоминаю, всего 15! (Чёрный зарезервирован под фон.) Это иллюстрирует первая картинка с подписью 8. Болото закрасилось тем же цветом что и небо, ибо слишком много слотов было занято различными оттенками тёмных цветов, коих на рисунке много и они были найдены в первую очередь. На оттенки зелёных не хватило места.
2: чем больше sensitivity, тем большие области на картинке становятся однородными. Это экономит места в палитре, однако ухудшает качество изображения. Пример — скриншот с sensitivity = 8 + 2 на каждом поколении (соответственно в конце параметр выше 30). Здесь всё тёмные тона были аппроксимированы практически двумя цветами и пиксели на изображении кончились намного быстрее слотов в палитре, отчего осталось место под различные тонкие оттенки зелёного и жёлтого.
От подобных комбинированных схем я быстро отказался. Хороший баланс конкретно для этой картинки с ульем достигается при значении 14.
На Windows 10 нет подходящего консольного шрифта, поэтому будут вытянутые, не особо красивые кракозябры, соре. Под семёркой всё должно быть нормально. Багов полно, пишите в комменты. Архив с программой лежит на гуглодоках, там внутри есть readme, плюс есть краткая справка по ключу -h (или /?) в консоли. Спрашивайте ваши ответы
(алсо теперь код залит на гитхаб, можете посмотреть или даже скомпиллировать (только сперва лучше перекреститься (никакой системы сборки, конечно же, не предоставлено)))
157 комментариев
И да, за фоновую пони респект.
Вот пример самого лучшего конвертера в текст из тех что видел — pixterm:
Спойлер
Залей на гитхаб чтоль
Примеры: 16colo.rs/pack/fuel27/
Осторожно, очень длинная картика.
Так вот, картинки распечатанные на АЦПУ мне доводилось видеть в середине 80х. Полагаю ANSI арт появился раньше, да?
Уже на матричных принтерах можно было печатать что угодно (а на некоторых — даже грузить свои шрифты, что означало, что можно было текстом печатать хоть картинки 160х100 (это когда в знакогенератор VGA/принтера загружаешь шрифт, целиком состоящий из всевозможных комбинаций из 2х4 заполненных/незаполненных квадратиков 4х4 пикселя, правда, там был некоторый drawback — в каждом таком квадратике можно было использовать только два цвета (это похоже на спектрум), т.е. нельзя было, например, сделать вертикальную последовательность квадратиков из более чем 4 цветов подряд; но если такое печатать — то там всё равно два цвета будет, и потому это было весьма годной идеей для такого).
...linux@z80 when?
(да, я знаю, что нормальному линуксу нужен MMU и прочие вкусности для умения в страничную адресацию, но вроде как его, хитро попатчив, пускали на каких-то микроконтроллерах без MMU — так что чем z80 хуже? =)
Плюс фирменная сборка плат подешевела сильно, можно уже и заказывать, и там всё что нужно запаяют, а не мучиться с ЛУТом и ручной пайкой (хотя, с другой стороны, романтика ночей, проведённых за лупой и паяльником в канифольном дыму, пропадает =)
Хотя, кажется, про малинку я перепутал, там пытались эмулировать не спектрум, а PC-8801, но суть всё равно одна — в одном Z80, в другом µPD780, оба с частотой в единицы мегагерц
Там работали на том эмуляторе, например, игрушки, которые юзали привязку к частоте развёртки (благодаря чему можно было получать больше двух цветов в квадрате 8х8)?
В терминале и анимация была
Спойлер
Но качество так себе, лучше бы конечно квадратиками.
В любом случае, годно, как настоящий кулхацкер, смотреть поней прямо в текстовой консоли, не используя обращения к фреймбуферу =)
Гитхаб думаю сообразить, когда градиентный спуск запилю для палитры. Генетический алгоритм конечно хорошо, но неэффективно. Ну и в коде прибраться не мешает, куда без этого :3
Под линуксом плюс только в том, что терминал поддерживает куда больше 16 цветов (но в старых досовских демках, емнип, тоже умели это делать, переключая палитру синхронизированно с развёрткой на мониторе; хотя преимущественно это делали в графическом режиме, получая на той же CGA не 4 цвета, а под 1024).
намджун, чонгук, чингачгук100%, 50% снизу, 50% слева, 50% справа, 50% сверху. ЧЯДНТ?Алсо, также скажу про символы 176-178: ими можно градиенты делать
Просто рисование нижней половиной ASCII-таблицы нормально работает при любой кодировке, а также позволяет делать субпиксельное (точнее, в нашем случае — субполузнакоместовое) сглаживание =)
Это у нас от шрифта зависит. Например:
consolas
courier new
DejaVu Sans Mono
"… Меня зовут Лира Хартстрингс, и вы никогда не вспомните о том, что хотели меня представить в виде раскрашенного ASCII-текста. Вы даже не вспомните этот разговор… Погодите, что?!" =)
Был тогда хвост 70-х годов прошлого века из минувшего тысячелетия…
Последние из тех работ — портрет Кира Булычёва (1980) и пирата-робота из мульта «Тайна Третьей Планеты» (1981) даже где-то сохранились, но искать их сейчас — неблагодарное дело… 888-)
А проги такой у меня не было, и компьютер появился первый позднее немножко… В 1983-м, сразу «Синклер» и «Агат»…
Приходилось всё ручками, ручками©Лира и на глазок… 888-)
И за это — отдельное спасибо!
XXX-D
Вот так судьбе!
888-Р
Ух… Звучит как адская боль в суставах пальцев.
Помянутые машинки:Украина-2:
Ятрань:
моё увожение. Умей я в искусство — с радостью бы сам тоже так делал. Но приходится создавать цифрового робота, который сделает за меня
И ситуация сменилась лишь в 1982 году с появлением «Синклеров», да в 1983 году, когда краденый Лианозовскими Мастерами «Эппл-II» превратился таки в «Агат»!..
Но и тогда добыть к ним принтер было проблемой. Игольчатый «дрюкер» (кто слышал звук, с которым оные работают — поймёт, почему именно «ДРЮКер»..)
А вот руки и машинка были тут, рядышком, и умели слегка взаимодействовать друг с другом… 888-)
Просто решил побаловаться на машинке, на которой предпочитал набирать свои рассказы (потому как почерк рукописный у меня УЖАСНЫЙ!)…
Я не могу себя заставить перестать во всякие моменты, когда я вроде бы помню, что чего-то не было, но при этом мне почему-то кажется, что оно должно было быть, задаю себе вопрос, не контактировал ли я с кем-то из неспетых в тот момент… =)
Вот блин, самая эпическая идея «Фоновой» — это то, что возможность существования кого-то уровня Лиры и других неспетых по определнию нефальсифицируема, а значит, мы никак не можем быть уверены, что их не существует, и не исключено, что вот десять минут назад до тебя кто-то отчаянно пытался докричаться, чтобы ты хоть что-то понял, а сейчас ты сидишь у компа и ни капельки не помнишь об этом =/
(ладно, заканчиваю философствовать, я просто слишком упоролся по «Фоновой» в своё время =)
Каин
Флатти
В работе это выглядит так: (только ОЧЕНЬ медленно)
Спойлер
Спойлер
Спойлер
Причём берёт оттуда прямоугольник, который в настройках задаётся.
Т.е. я вообще любую таблицу могу туда засунуть, пусть хоть смайликами рисует, главное чтобы символы были 16*16 пикселей.
Т.е. у меня нифига не каноничный ASCII, он на картинках работает =)
Хотя можно легко прикрутить вывод таки в текст, если составить таблицу символ-с-картинки -> ASCII
П.С. Главная проблема у меня в том, что оно ОЧЕНЬ медленное. Эта Тия вроде больше минуты делается.
Ибо там для каждой ячейки проверяется каждый из 16*16 пикселей картинки с каждым из 16*16 пикселей каждого из 16*16 символов. Жесть.
ИМХО, конечно, но нужно делать вот какой фокус: брать мелкий шрифт (вроде есть 8*9 в консоли), и саму картинку напротив, увеличивать перед обработкой. Получится большая детализация.
Тот же шрифт, те же настройки, но сперва исходное полотно, а потом его удвоенная копия
В идеале ещё нужно сдвигать картинку на 16 пикселей по каждой оси, попиксельно, и в каждой из 256 попыток записывать точность воспроизведения, и в конце выдавать самый точный вариант. Это к тому, что при разделении картинки на символьную матрицу разбиение может быть таким, что большая часть ячеек будет максимально неудобоваримой для ASCII, и это можно побороть небольшим сдвигом. Но тут мой алгоритм замедлится ещё в 256 раз, т.е. эта Тия будет делаться часа 4…
хз, можно как-то сравнения цветов перенести на видеокарту?
Делается меньше чем за секунду, даже для относительно больших картинок (~1366х768). Основное время тратится на подбор палитры, ибо там (для картинок в посте например) 1000 особей лазает по 400 000 пикселям картинки (это уже примерно 4 секунды) на протяжении 60 поколений. Итого примерно аж 4 минуты
идея со сдвигом интересная, она у меня была но почему-то отбросил. Надо будет реализовать
насчёт переноса на видяху — подобная обработка картинок в теории идеально параллелится, так что проблема только в умении писать расчётные проги под графическое ядро. Можно ещё распараллелить в дохрена раз и на CPU, если захардкодить векторизацию через SIMD-инструкции (опять же вопрос в умении)
А с помощью чего это происходит?
Я делаю с помощью getpixel(x,y); из встроенной граф. библиотеки Паскаля, наверное поэтому так медленно.
я юзаю libpng дабы получить двумерный массив байт (читай пикселей) и потом просто обращаюсь к массиву, примерно как pixels[x][y]. Всё это шустро работает без дополнительных прослоек и няшно оптимизируется, ибо C++
Единственное, что я смог сделать — это повысить скорость за счёт памяти. Запихал переменные, которые мешали распараллеливанию, в мегамассивы массивов интеджеров, или типа того.
Время обработки тестовой картинки уменьшилось с 19,04 с. до 15,48 с. И это с выключенным оптимизатором, который ускорял нахождение полностью чёрных/белых участков с 256 проходов до 1.
Заодно заметил странность:
Этот код
if (ut.GetPixel(x * 16 + xPixel, y * 16 + yPixel) = ascii[0, 2].GetPixel(xPixel, yPixel))
на треть быстрее, чем этот:
if (ut.GetPixel(x * 16 + xPixel, y * 16 + yPixel) = clWhite)//clWhite — константа
Хотя мне всегда казалось, что должно быть наоборот…
Провёл более подробный тест на увеличенной вдвое тестовой картинке из первого теста. Результаты шокировали:
С оптимизатором: 49,5 с.
Без оптимизатора: 61,5 с.
Версия, которую я три часа оптимизировал: 66 с.
Выводы:
1. Оптимизатор существенно ускоряет на картинках с большими однородными пространствами, но сильно замедляет на картинках со сложным рельефом.
2. Из меня вышел не просто фиговый кодер, но и очень фиговый оптимизатор.
оптимизации это вообще лютый хаос, как только масштаб проекта выходит за рамки парочки функций. Я вот пытался у себя ген. алгоритм по кэшу оптимизировать: ручками разложил в памяти массивы на свои места, классы заменил структурами, методы — процедурами. В результате стало медленнее :D
1) clWhite скрыто разыменовывается не в иммедиат, а в константу, лежащую в памяти «дальше», чем массив ascii (например, в другом сегменте в реальном режиме или в странице, в которую всё время идёт промах при страничной адресации)
2) первый код компилятор, раскручивая цикл, оптимизирует в склейку пересылок (т.е. копирует 4/8/16 байт за раз), а второй заполняет по одному байту — не догадывается, что можно сформировать (uint32_t)(char[4] {clWhite, clWhite, clWhite, clWhite}) и присвоить его сразу.
Перегоняй всё изображение в битмап в памяти и потом обращайся к каждому биту напрямую. Так у тебя быстродействие возрастёт не то, что в разы, а на порядки.
Как?
Там есть System.Drawing.Bitmap, но он такой же по скорости, как и обычная картинка. Более того, я видел на форуме мельком обсуждение это проблемы, и там пришли к выводу, что что-то куда-то так офигенно глубоко запрятано, что достать это оттуда невозможно, и вместо быстрой графики — страдай. Сейчас эту тему найти не могу, хотя там могли быть подсказки…
помню с какой-то конференции доклад был, где ребята до того дошли, что создали массив вида double x[] = {0, 1, 0.5, 0.33, 0.25, 0.2, 0.17 ...} и потом вместо 4/13 писали 4*x[13]. Сэкономили на делении
Но выяснил много нового для себя:
1. array of array работает быстрее, чем одномерный массив того же размера. Не знаю, почему. Работает в 5 раз быстрее.
2. Большая часть затрат времени в одномерном массиве — это вычисление индекса [y*size+x];
(a: array of byte; a[y*size+x],00:00:01.1568314)
(b: array of array of byte; b[x,y],00:00:00.2420561)
(c: array [0..size,0..size] of byte; c[x,y],00:00:00.4520275)
(e: array [,] of byte := new byte[size, size]; e[x,y],00:00:00.2990774)
Почему array of array почти вдвое быстрее статического массива, при этом динамический прямоугольный массив быстрее статического, но медленнее динамического лесенкой? А чёрт его знает. Придётся сейчас всё обратно переписывать в лестничные массивы.
Заменил picture на array of array of byte.
Время выполнения png -> ASCII-png преобразования снизилось с 69 секунд до 19. + 10 секунд преобразования картинки в массив байт. Разумеется, этот код не будет поддерживать цвета, но это мелочи, всё же программа пилилась изначально монохромная.
П.С. Слегка оптимизировал говнокод picture -> array of array of byte, и сэкономил 5 секунд (из 10) этой части программы. В итоге теперь вся картинка со старта до готовности делается за 22 секунды, против 69 секунд одного только финального прогона в старой версии.
П.П.С. Всё таки у меня не работает {$omp parallel for} в циклах, выдаёт ошибку. Не знаю, почему, видимо не до конца убрал критические штуковины.
Единственная проблема: где-то раз в 5-6 запусков всё равно в параллельном цикле возникает «какая-то ошибка». Никак не могу понять, с чем она связана.
P._P.P.P.s: Попробовал переводить в текст, и это не так просто, ибо 1. кодировки 2. она печатается перевёрнутой в непонятную сторону, и я сходу не могу понять, как именно это решить.
Последняя попытка выглядит вообще так:
Лиру распегасило
'���������������������������������������������������������������
''��������������������������������������������������������������
'''�������������������������������������������������������������
'''?������������������������������������������������������������
'''?�����������������������������������������������������������
''?§����������������������������������������������������������
''?'???���������������������������������������������������������
'?'?§��������������������������������������������������������
'?'?'???�������������������������������������������������������
'?'?'?§?������������������������������������������������������
'?'?''?§�����������������������������������������������������
'?''§§?'����������������������������������������������������
'?'?§??''���������������������������������������������������
'?§?''§''��������������������������������������������������
'?'??''??'''�������������������������������������������������
''?§?'''?§'''������������������������������������������������
'''?§§§?§§§'''�����������������������������������������������
''??§§§§§§§???''����������������������������������������������
''?§§§§§§?'§§§§���������������������������������������������
'''?§§§§§§?'§???§��������������������������������������������
'''§§§§?§''?'''§§�������������������������������������������
''?''????§a'''''§Ao������������������������������������������
''?''??'''?''''???�����������������������������������������
''?''?''''''''''??'??����������������������������������������
'''?'''?'''''''''''???§���������������������������������������
'''''§''''''''''§'?��������������������������������������
'''?'§§'''''?'?�������������������������������������
'''c''??§'?§'''??'������������������������������������
'''?c'?'§§§§§§§'???''�����������������������������������
'''?'?§§§§§§§§§§§§§?'''����������������������������������
'''?'u'§§§§§§§§§§§§§§§'?'���������������������������������
'''?'§§§§§§§§?§§§§§§?''§§§��������������������������������
''?'§§§§§§?''?§§§§§§§§§§§§§§�������������������������������
B??'§§§§?'''§§§§§§§§§§§§§§§?'������������������������������
§??'?'§§??'''§§§§§§§§§§§§§§§'''�����������������������������
'''''§'§§'''?§§§§§§§§§§§§§§§?'''''����������������������������
'''''?'§§?§§§§§§§§§§§§§§§§§'''''''���������������������������
''''''?§§§§§§§§§§§§§§§§§§§§§§?''''?'''��������������������������
'''''''§§§§§§§§§§§§§§§§§§§§?''?'''?�������������������������
'''''''''§§§§§§§§§§§§§§§§§§§''??''?������������������������
'''''''''§§§§§§§§§§§§§§§§§§§''r?''???�����������������������
'''''''''§§§§§§§§§§§§§§§§§§§§''r?4''?§'����������������������
'''''''''§§§§§§§§§§§§§§§§§§§§'d'??''?���������������������
'''''''''?§§§§§§§§§§§§§§§§§§§''?'§'''?'��������������������
''''''''?§§§§§§§§§§§§§§§§§§'§'§''?''�������������������
''''''''?'§§§§§§§§§§§§§§§§§§?''??'§§''?'������������������
''''''''?'§§§§§§§§§§§§§§§§§§''''''?§§§?'''�����������������
''''''''?''?§§§§§§§§§§§§§§?§'''''?§§§§§'''����������������
''''''''§'''§§§§§§§§§§§§?''?§''''?§§§§§§''f''���������������
'''''''??''§§§§§§§§§§??''''§§''''?§§§§?''''''��������������
''''''§''§§§§§§§§§§§''''''?§?'''§§§§?'?''''''�������������
'''''''?''§§§§§§§§§§§''''''§§''''§§§?''''''§������������
'''''''''''?§§§§§§§§§§§''''''§§?''''?§§§'?'''''?'�����������
''''''''''§§§§§§§§§§§§?'''''''?§§''''?§§§'''''?''����������
'''''''''§§§§§§§§§§§§§§''''''?§§''''?§§§§'?''''§''���������
'''''''''§§§§§§§§§§§§§§'''''§§?'''§§§§§?'?'''§''?��������
'''''''''?§§§§§§§§§§§§§§?'''''§§''''§?§§§?'''?'''???'�������
''''''''§§§§§§§§§§§§§§§?'''''§?''''§?§§§§''c''§???''������
'''''''''§§§§§§§§§§§§§§§§'''§§''''§''?§§§?'''???'''�����
''''''''''§§§§§§§§§§§§§§§'''?§?''''?§'§§§?''''???'����
''''''''''§§§§§§§§§§§§§§§?'§§'''''?§§§§§§''''??"???W??'���
''''''''''§§§§??????§§§§§§?'?§?'''''??§§§§§'''?'''''''''?��
''''''''''§§§§''''§§§§§§§?§§''''''?''?§§§?'''?'''''W?''�
''''''''''§§§?'''?§§§§§§§?§§?''''''??'''?§§§?'''§§§?§?"''''
Итак, по порядку.
Нашёл этот код в интернете для Дельфи, но работает на Паскале. Не очень понимаю, как оно работает, что это за «on», но благодаря этому я получил более подробные сведения об ошибке. Ошибка возникала из-за одновременно вызова ut.GetHeight.
Создал переменную
Сделал замену по всему коду ut.Height на utHeight.
и ошибки вроде пропали.
2. Возможно, у тебя битмап читается не в том направлении? Например, некоторые форматы любят хранить картинку снизу вверх, а не нормально.
Кстати, именно поэтому хранить средний цвет не подходит: нужно хранить цвет каждого пикселя. И потом сравнивать каждую ячейку с 256 символами, для каждого из которых делать 256 проверок на цветовые комбинации. Скажем так, сейчас обработка фотографий занимает до 6 секунд. В цвете это будет занимать до 30 минут. И код переписывать. Не. Не хочу.
Нет, можно просто средний цвет ячейки брать, и красить в него символ. Но по какому критерию тогда отбирать сами символы? Если хранить старые цвета, а отбирать по монохромной версии картинки, то получится упорото. Делать монохром не целой картинки, а каждой отдельной ячейки независимо? Получится ступенчатая дичь.
Но да, цвет я хранить могу.
Насчёт алгоритма — наверное, там стоит выделять два наиболее «влияющих» в этой зоне цвета, один делать цветом фона, другой — символа, и потом подбирать, какой символ наиболее хорошо им соответствует (включая и инверсные представления, т.е. 512 глифов для каждого квадрата 8х8).
а подобные ошибки
это нормальный процесс дебага. У меня, например, первый запуск проги был таким:
кек
Я бы даже сказал, что перевёрнутая Лира это не процесс дебага, а обычная путанность строк и строчек между собой. Постоянно такая проблема, что пишешь этот двумерный цикл, и путаешь, в каком порядке его читать-писать надо. Но я сейчас так плыву, что делать текстовый вывод уже не хочу. Надо для учёбы задания делать, накопил долгов немного.
Казалось бы, ещё в 8086 появилась индексная арифметика для лоадов (вот это вот mov ax, [bp + si]), а сейчас с FMA и прочими вкусностями вообще с этим никаких проблем не должно возникать, однако ж.
собсна это был пример устаревшай оптимизации с доклада про кэш от разработчика архитектуры микропроцев
Может, есть какая-нибудь библиотека, типа порт libpng для паскаля, которую можно подцепить и заюзать для такого?
Ну, в самом крайнем случае, как советуют в этой ветке, просто разок пробежаться getpixel-ом по картинке, преобразовав её в массив, а потом из массива putpixel-ом закинуть обратно.
Кстати, тебе, наверное, будет удобнее при этом хранить картинку не в виде сетки пикселей, а в виде сетки блоков 8х8, т.е. не в таком виде:
а в таком:
Так тебе будет проще работать с 64-байтными блоками, сравнивая их с нужным глифом, а не вырезать по куску из каждой из 8 занятых глифом строк.
…
…
…
Нет, я просто настолько тупой, что до сих пор даже не подозревал об этом. А у меня 16 захардкожено повсюду. Щито поделать, пойду переделывать, и заодно введу переменную symbol_size.
Чтобы увидеть буковки, откройте в новом окне и приближайте.
правильно! Переработка в радугу куда полезней
например используя зашумление | псевдотонирование
(да, даже про CSS мы тогда не знали =)
Поэтому, когда кто-то приходит опять с тем же самым, это вызывает небольшое раздражение…
А во-вторых, никто не ищёт в удалённых постах, обычно.
НО блин, ещё в 2013 году, совсем недолго до моего появления, тут сообщалось о возможности смотреть видео в консоли. И да, на винде тоже.
Поэтому я считаю, что вам не удастся сказать что-то новое в этой теме, и не следует уделять этому проекту так много времени.
Но, если полностью осознавая, что это лишь учебный проект, вы хотите хорошо чему-то научиться, то… впрочем, да хозяин-барин, вы сами господа своего времени.
И коммит-мессаги малоинформативные немножко…
А ещё я такой думаю, о, щас как напилю себе текстовых картинок, и такой иду и…
Ну ок, думаю я, привык я слишком к кроссплатформенности =(
порт на линукс у меня первый в списке дел по проекту, так что ожидайте
Просто я, как уже говорил, привык к кроссплатформенности слишком, видимо, и забываю подумать о том, что «это может не пойти на линуксе» перед тем, как сделать clone / make / make install =)
1 — тык сюда, 2 — тык туда, 3 — получаем такой то результат.
Иначе ну перегнал я этукартинку взначки
и? Картинку переименовал в NMM_DB и подогнал в пейнте по пикселям, но можно ли другие размеры перегонять?
Все, до чего я додумался это скопировать значки выделением и в итоге получил вот это:
Спойлер☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻¶◄☻☻☻♥☻☻¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻▬▬▬▬▬▬↨☻#▬▬▬"".,▬~▬☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻f►g☼☼☻☻☻☻☻☻☻☻☻☻◄◄☼g♥☼☼p◄¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻◄◄☻☻☻☻☻☻↨☻►☻☻☻☻¶◄¶☻☻☻☻☻¶◄◄►V☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♦♦◄↨►¶☻☻☻☻↨¶&♦¶☻☻☻▬↨☻☻¶☻☻☻☻L #♦♦♦♦☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻ggp☻☻☻ggg☻☻ggegg☻☻☻☻☻☻8gg☻☻☻☻☻ggggpg+~☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻M☻☻☻¶¶►☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►8☻☻☻☻☻☻☻☻☻☻☻☻☻¶☻8M☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻8♦♦☻♦◄♦ #♦♦♦☻☻☻☻☻☻☻☻♦◄¶☻☻☻☻♦♦♦¶☻☻☻☻☻♦∟¶☻#♦♦♦☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻8ggg☻☻ygggg☻☻g¶☻☻☻☻g☻☻☻¶☻☻☻☻☻p☻¶☻☻☻☻☻gy\~☻☻ggp¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►8M☻☻☻☻¶☻8☻☻☻☻¶¶☻8☻☻☻♫↨¶►8M☻☻☻☻¶►8☻☻☻☻¶¶►☻M☻☻☻¶¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►♦♦☻♦☻☻☻☻☻☻☻☻♦◄♦¶#♦♦☻☻▬♦▬☻☻☻♦♦↨L▬▬☻☻♦♦◄¶☻☻♦☻☻☻@+¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►gMgg☻☻☻☻#ggg☻y+e☻☻☻☻pg¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻g+egMg☻☻gge☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻8M☻☻☻¶¶►8M☻☻☻☻¶☻☻☻☻☻☻¶¶►8☻☻☻☻☻¶►☻☻☻☻☻☻¶►☻M☻☻☻☻¶►8☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻8♦♦♦☻▬◄☻☻☻♦♦☻☻◄►♦♦♦☻☻☻L►♦♦♦♦♦◄j►☻☻♦♦♦☻L▬☻☻☻☻☻☻L►♦¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻▬▬p▬./¶☻▬▬☻☻h 8M▬☻☻☻☻&^▬☻▬▬☻P ☻☻▬▬☻▬¶☻☻☻☻▬p▬¶►g▬☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♠↨◄☻A♥☻☻☻☻☻►A♥☻☻☻☻☻►A☻☻☻☻☻☻►A☻☻☻♠↨☻☻☻☻☻☻♠↨◄☻☻♥☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻◄◄►♦♦♦♦♦☻☻&♦♦♦☻☻↨L♦♦♦♦♦♦◄¶►♦♦♦♦♦♦j☻☻☻☻♦♦♦♦►♦♦♦♦♦◄◄♦♦¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻h,^▬▬☻p↨☻☻8▬▬☻☻p▬~▬▬▬☻p▬▬g☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻p▬▬,g▬▬▬☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♥☻☻♠↨☻☻8♥☻☻☻↨◄☻8☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻↨¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♦♦↨☻☻8♦♦♦♦♦j☻☻☻☻☻☻☻☻☻☻♦♦♦♦♦¶☻☻☻♦♦♦↨☻►♦♦♦♦♦☻☻☻☻☻☻☻☻▬◄►♦¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻#▬▬▬▬☻☻☻☻☻☻☻☻M▬▬gM▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬☻p¶☻☻☻☻☻☻☻☻&g▬▬▬☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►A♥☻☻☻☻☻☻☻M☻☻☻↨◄☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻M☻☻♠☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♠↨¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻◄►V☻☻☻☻☻☻►☻☻☻☻♫☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻M☻☻¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♫◄j☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻M▬/▬☻☻☻☻M▬/'▬☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻▬▬↨☻☻☻☻☻☻☻☻P~~▬~~▬☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☼p◄☻☻☻☻☻☼p◄☼►8☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☼p↨☻☻☻☻☼☼p☼¶►g♥☼☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻¶↨☻☻☻♥☻☻☻☻☻►V☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻◄☻►V♥☻☻¶◄j☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻M▬~☻☻☻☻▬"~▬☻☻¶►☻~~~~~~~~~~~~~~~~~~~☻"▬~~~~~"↨► ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻8♥☼☼☻☻f►g♥☻☻☻☻¶►8☼☻☼p¶f►☼♥````◄☼☼☼☻☼☻♥¶Tg♥` p☼¶►☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻8♥☻☻☻☻☻►8M☻☻☻☻¶►8☻☻☻¶◄◄►V♥_☻ ◄►V♥☻☻☻☻¶► ☻☻ ¶◄◄_☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻▬M☻☻☻☻☻►8M☻☻☻☻¶►#▬▬~▬"., ~~ ▬`'▬▬☻☻☻☻►, ~~▬▬"¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►g♥☻☻☻☻☻►8M☻☻☻☻☻►g☻☻☼p☼◄☼☼☼☼☼☼◄☼►☼☻☻☻☻☻☻►g♥☼☼p◄☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻¶►8M☻☻☻¶☻►8M☻☻☻☻☻►8☻☻☻☻☻☻☻☻☻☻☻☻☻¶☻☻☻☻☻☻☻☻☻8M☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻L▬♦♦♦♦♦◄▬¶8♦♦♦♦☻☻►8☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻@♦¶☻♦♦♦↨☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►ggggp☻☻☻gg☻☻☻☻☻☻☻☻☻☻☻~gggg☻☻☻☻bgg☻☻gp↨☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►8☻☻☻☻¶¶☻8M☻☻☻¶☻►☻☻☻☻☻☻¶☻☻☻☻☻☻☻¶►8M☻☻♫☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻►!♦☻☻☻☻▬L!¶M☻☻☻☻L▬♦♦☻♦♦♦♦♦♦♦♦♦♦◄/♦♦♦♦☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻+eg☻☻☻☻☻begggg☻☻☻☻☻ggggy+ggg☻gpyggg☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻¶¶►☻☻☻☻☻☻☻☻8M☻☻☻☻☻☻☻☻☻☻☻☻¶►8☻☻☻☻↨☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻◄+ ☻☻☻☻☻☻☻☻☻☻♦♦♦↨☻☻☻☻☻☻☻☻¶►8☻☻☻☻◄¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻y¶►☻☻☻☻☻☻☻☻☻☻☻gpy¶☻☻☻☻☻☻☻¶►g☻☻☻☻y¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♠↨¶☻☻☻☻☻☻↨☻☻A☻☻☻☻↨¶►☻☻☻☻☻☻¶►☻☻☻☻♠↨¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♦↨¶☻☻☻☻♦♦◄◄♦♦♦♦♦☻☻L►♦♦♦♦♦◄◄►♦♦♦♦♦◄◄►♦♦♦♦♦☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻p▬¶☻☻☻▬▬p☻☻☻☻▬▬▬p¶☻►g▬▬▬p▬\,g▬▬▬p"▬▬g☻▬▬p↨☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♠↨¶☻8♥☻☻☻☻☻☻☻☻☻☻♠↨☻►A♥☻☻☻☻¶►A☻☻☻♠☻☻☻☻☻☻☻♠☻¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻↨☻►☻♦♦☻☻☻☻☻☻☻☻☻♦◄j►♦♦♦♦♦◄¶►8♦♦♦♫☻☻☻☻☻☻☻☻▬◄►☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻▬p\\,gM▬☻☻☻☻☻☻☻☻☻☻▬¶►g▬▬☻p↨¶►^▬▬☻p¶☻☻☻☻☻☻☻☻►,¶☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻↨◄►A♥☻☻☻☻☻☻☻☻☻☻☻☻¶☻☻♥☻☻♠☻¶►A♥☻☻♠↨☻☻☻☻☻☻☻☻☻►A☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻♦↨☻☻☻M☻♦☻☻☻☻☻☻☻☻☻☻L♦♦M☻☻♦♦♦♦,☻☻♦☻↨☻☻☻☻☻☻☻☻☻►♦♦☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻M☻☻☻☻☻☻☻☻☻☻☻☻☻►g▬☻☻☻☻☻☻☻☻☻▬☻↨☻☻☻☻☻☻☻☻☻&^▬☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻M☼☻☻☻☻☻☻☻☻☻☻☻☻☻g♥☻☻☻☻☻☻☻☻☻☻p↨☻☻☻☻☻☻☻☻☻Tg♥☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻V♥☻☻☻☻☻☻☻☻☻☻¶◄◄►☻☻☻☻¶☻◄►V☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻
и что дальше с этим делать? как перегнать полученое изображение обратно в картинку, но на этот раз состоящую из значков?
Просто я во всем этом абсолютно не разбираюсь и краткое руководство было бы кстати.
А еще лучше — в одну папку закинул, включил программу, перегнал изображение, из другой папки достал результат.
Или я что — то не понял (что скорее всего) или эта программа просто доп. оборудование к какой — то другой программе.
— результат в символах пока что не умеет себя сохранять как изображение. Т.е. нужно либо запускать прогу каждый раз заново, либо делать скриншоты (именно так и сделаны картинки в посте)
— про доп. оборудование ты верно подметил, но в целом модуль получился довольно самостоятельный
в общем добавил генерацию картинки с результатом в список задач проекта, спасибо за отзыв!
C:\Users\RandomUser\Desktop\Новая папка (2)\conv>conv arts\NMM_DB /p 600 /s 10
libpng warning: iCCP: known incorrect sRGB profile
C:\Users\RandomUser\Desktop\Новая папка (2)\conv>pause
Для продолжения нажмите любую клавишу...
После нажатия клавиши это окно закрывается. Все.
Кстати надо еще в описание добавить что сразу после запуска надо маленькое окно разворачивать на весь экран. А то когда картинка обработана то при растягивании окна картинку развозит до безобразия.
Эта же картинка 600х600растянуто только вниз
слегка вправо
на весь экран
Во время обработки
после обработки
если после обработки выделить знак на верхней строчке и прокрутить изображение вниз и затем вверх.
Картинка 600х600
Как вообще сделать их нормального вида? без растягиваний и перекосов?
Через пейнт?
видимо мелкомягкие в десятке переработали АПИ, и оно теперь своевольничает. У меня на семёрке прога не позволяет себя так тянуть. Касательно сжатий пережатий через пейнты — программа на это не рассчитана. По задумке она просто показывает результат на один раз полюбоваться. Ну мб заскриншотить если сильно понравилось (в этом случае да, логично масштабировать исходник, чтобы умещалось на экран)
маленькое окно не предполагается разворачивать (даже не должно было быть физической возможности это сделать). Вот когда оно завершило работу, тогда да — кликнуть разворот на весь экран
Если развернуть окно после окончания то выходит Размазня
Да, у меня вин10