PDA

Просмотр полной версии : Конвертер изображений из PC в ZX-Spectrum



Northwood
15.02.2018, 17:23
Всем привет!

Работа над новым компьютером "Пентагон-4096" в теме http://zx-pk.ru/threads/28489-pentagon-1024-4096-ot-northwood.html, который поддерживает множество расширенных видеорежимов, требует наличия хоть какого-нибудь ПО, которое бы эти видеорежимы поддерживало. Поэтому идея написания конвертера изображений пришла довольно быстро.

В результате родилась 1-я версия конвертера. Вот возможности 1-й версии:

Назначение:
Конвертирование различных изображений из PC-х форматов в Спектрумовские.

На входе поддерживаются следующие форматы: JPEG, PNG. (В следующей версии добавлю BMP и GIF с возможностью выбора кадра);

Поддерживаемые разрешения изображения на входе: 512х384 и 256х192. (В следующей версии добавлю поддержку любых разрешений, кратных 256х192, а в будущих - планируется поддержка вообще любых);

Возможность просмотра в окне программы как оригинала изображения, так и результата, который будет на экране ZX-Spectrum;

В данной версии поддерживаются следующие видеорежимы ZX-Spectrum:

a) Стандартный (256х192, атрибут цвета на знакоместо 8х8);
б) Мультиколор (256х192, атрибут цвета на байт 8х1);
в) 512х192 цветной (512х192, атрибут цвета на узкое знакоместо 8х8);
г) 512х192 мультиколорный (512х192, атрибут цвета на "узкий" байт 8х1);
д) 16Colors (256х192, каждый пиксель своим цветом).

Из дополнительных опций видеорежимов поддерживается:

Flash-Bright (бит Flash задаёт яркость отдельно для Paper, не применимо для 16Colors).

В будущих версиях программы будут добавлены опции видеорежимов:
Flash Color (дополнительная цветовая палитра за счёт перемешивания цветов INK и PAPER в знакоместах, где автивен бит Flash, фон чёрный);
GigaScreen (наложение двух изображений с целью получения дополнительной цветовой палитры, будут 3 режима отображения изображения - смена изображений по кадрам с частотой 25 Гц как на реальном Спектруме, смена изображений от строки к строке с инверсией от кадра к кадру, как на реальном Спектруме с аппаратным Гигаскрином, и без мерцания).

Полученный результат можно сохранить в файл, пригодный для просмотра на реальном ZX-Spectrum в 2-х вариантах:

а) Само изображение без ничего лишнего;
б) Изображение + Basic-загрузчик (просмотрщик) с Hobeta-заголовком.

В текущей версии моего проекта "Пентагон-4096" реализованы 8 дополнительных видеорежимов, работающие на моём реальном доработанном Пентагоне. Как я говорил в соответствующей теме, из всех видеорежимов в схеме я не реализовывал только Flash-Bright. Меня раздирало любопытство, как же будут смотреться картинки с Flash-Bright, потому я решил эту опцию реализовать в данном конвертере. И как оказалось, я недооценил видеорежим Flash-Bright, как говорится, "почувствуйте разницу" без опции Flash-Bright и с ней. Поэтому появилось большое желание его реализовать сначала на имеющемся Пентагоне, а затем включить реализацию и в новом проекте "Пентагон-4096".


Данная программа - конвертер изображений работает под ОС Windows XP/Vista/7/8/10, но требует установленного пакета Microsoft .Net Framework версии 3.5. Наличие пакета версии 4.0 и выше значения не имеет, поэтому 3.5 устанавливать обязательно.

Northwood
18.02.2018, 17:14
Новая версия конвертера изображений, 1.2.0:

1. Программу переименовал из "ZX Screen Converter" в "ZX Image Converter";
2. Сделал масштабирование открываемого изображения. Теперь конвертировать изображения можно любых размеров и соотношений сторон, ограничений нет.
3. Добавил поддержку форматов BMP и GIF. Если изображение многослойное, например анимационный GIF, можно выбрать нужный кадр и сконвертировать его для ZX-Spectrum;
4. Теперь изображение можно поворачивать на 90 градусов в любую сторону;
5. Сделал 2 варианта алгоритма преобразования яркости, влияет на результат конвертирования в ZX форматы.

В следующей версии планирую поддержку расширенной палитры ZX-Spectrum используя видеорежимы FlashColor и GigaScreen.
В будущих версиях планирую:
а) расширение палитры путём текстурирования изображения;
б) возможность регулировки чувствительности каждого из каналов RGB для подстройки преобразования в ZX-форматы.

Denn
19.02.2018, 16:55
Northwood, отличный конвертер, спасибо!

Возможно ли, по просьбе трудящихся, добавить поддержку экрана ПРК "Орион" (384х256, цвет "байт на 8 точек", разворот картинки сверху-вниз, слева-направо) ?

Ещё из пожеланий: режим сохранения спрайтов, т.е. не только полного экрана.

gobuka
19.02.2018, 17:25
Задолбали вы уже своим Орионом!

Northwood
19.02.2018, 17:43
Northwood, отличный конвертер, спасибо!

Возможно ли, по просьбе трудящихся, добавить поддержку экрана ПРК "Орион" (384х256, цвет "байт на 8 точек", разворот картинки сверху-вниз, слева-направо) ?

Denn, сделать не проблема, на выходных сделаю. Сейчас после открытия любого изображения, оно масштабируется под разрешение 512х384, а уже оттуда второй раз масштабируется во время конвертирования в зависимости от выбранного видеорежима. Но нужны подробности развёртки экрана Ориона. Я давно краем уха слышал, что там атрибут цвета на байт, как в режиме Мультиколор на Спектруме, но больше ничего про развёртку экрана в Орионе мне не известно. Там как сделано - строки идут последовательно, не так как на Спектруме ? И нужна раскладка байта атрибутов. Но загрузчик под Орион я не сделаю, т.к. я не знаком с программированием на этом компьютере, да и самого Ориона у меня никогда не было. Слышал, что они бывают двух версий - на процессоре КР580ВМ80А с тактовой частотой 2.5 МГц, и на Z80 с частотой 3.5 МГц.

А зеркальный разворот полезно будет сделать для любого видеорежима.


Ещё из пожеланий: режим сохранения спрайтов, т.е. не только полного экрана.
По поводу режима сохранения спрайтов, то как я понимаю, строки должны идти последовательно и должны быть указаны размеры спрайта по X и Y ? И размеры спрайтов всегда кратно 8х8 пикселей ?

Black Cat / Era CG
19.02.2018, 17:46
разворот картинки сверху-вниз, слева-направо

А зеркальный разворот полезно будет сделать для любого видеорежима.
Не, это было про то, как оно хранится в памяти. Экран хранится столбцами (по 8 точек вроде). Сверху-вниз, слева-направо.

Denn
19.02.2018, 18:04
Northwood, спасибо за отклик.

Устройство экрана Ориона следующее:

"Область видеоОЗУ "Ориона-128" занимает в основной странице памяти адресное пространство размером 12Кб, начиная с адреса C000h (по адрес EFFFh включительно). Кроме того, если включен цветной режим, в формировании изображения участвует соответствующая ей область дополнительной страницы, расположенная в тех же адресах, и общий объем используемой под видеоОЗУ памяти становится равным 24Кб. Каждая ячейка ОЗУ экранной области соответствует восьми расположенным в горизонтальный ряд точкам одной строки растра ЭЛТ. На рис.1 в качестве примера показано увеличенное схематическое изображение левого верхнего угла экрана:

http://www.danbigras.ru/Orion/DspMem/OrDspMp1.jpg

Если компьютер работает в монохромном режиме, ячейки дополнительной страницы в формировании изображения не участвуют и изображение целиком зависит от того, какая информация в данный момент записана в ячейках видео области основной страницы. Бит, установленный в 1, дает на экране одну светящуюся точку. Если бит равен 0 - точка погашена. Так, например, чтобы получить такую картину - полностью погашенный экран и одна светящаяся точка в левом верхнем углу, необходимо заполнить всю область C000H-EFFFh байтами со значением 00h, а в ячейку С000h записать значение 80h.

Распределение ячеек по пространству экрана показано на рис.2:

http://www.danbigras.ru/Orion/DspMem/OrDspMp2.jpg

Ячейки памяти располагаются последовательно друг за другом вертикальными колонками по 256 (100h) в каждой. Адрес ячейки задается двумя байтами - старший определяет номер колонки, младший - номер ячейки в колонке. Так, для того, чтобы перейти от некоторой ячейки памяти к соседней, расположенной ниже, надо увеличить на единицу значение младшего байта адреса, на ячейку выше - уменьшить на единицу это значение. Аналогично, для того чтобы перейти от некоторой ячейки к соседней, расположенной справа или слева от заданной, надо проделать такие же операции со старшим байтом адреса."

Это офиц. описание устройства экрана отсюда (http://www.danbigras.ru/Orion/DspMem/VideoMem.html).

Т.е. суть похожая на синклеровскую, только один атрибут цвета окрашивает не 8х8 точек, а 8х1 (один горизонтальный "байт точек"), по типу мультиколора. Вывод на экран не горизонтальный с хитрой "расчёской", а вертикальный туполинейный, без каких-либо хитростей. Атрибуты цвета лежат в отдельной банке ОЗУ, но для конвертации в файл эта информация не требуется, это уже тонкость при выводе на самом Орионе.

Есть некоторые отличия по устройству атрибутов цвета:

http://www.danbigras.ru/Orion/DspMem/OrDspMp5.jpg

"8 точек каждой ячейки могут быть окрашены в одно из 256 сочетаний 16 цветов фона и 16 цветов переднего плана. Точками фона считаются точки, значения соответствующих битов которых в байте основной области равны 0 - в наших примерах это (считая слева направо) 2-я, 3-я, 5-я и 6-я точки, а передний план (изображение) - 1-я, 4-я, 7-я и 8-я точки. Ячейка дополнительной области в данном случае определяет, какой цвет имеют те и другие. Старшая тетрада байта этой ячейки задает окраску фона, младшая - изображения. Так, в примере на рис.5 выбрано сине-желтое сочетание."

barsik
19.02.2018, 18:52
в) 512х192 цветной (512х192, атрибут цвета на узкое знакоместо 8х8)
Не подскажете, каким образом у Вас включается такой режим? Какой на это отечественный стандарт?

Режим 512*192 впервые применён в TIMEX-2068, но там монохром (вторая плоскость читается вместо цветового атрибута из одной банки РУ5) и доп.экран на #6000. Но это не стандарт, т.к там диспетчер ОЗУ 8-ми оконный по 8 кб.

Чтобы получить цветной экран 512*192 надо иметь или 2 банки ОЗУ, как в ОРИОНЕ, или за время сдвига экранного байта читать 4 синклеровских экранных страницы. Интересует каким портом и битами включается этот режим и размещение экранных плоскостей в адресном пространстве и в ОЗУ.


Задолбали вы уже своим Орионом!
Если бы я был модератором, то забанил бы gobuka за это на недельку.

Вопрос к администрации. Чтобы отечественные компьютеры не раздражали синклеристов и не отвлекали их от дела, может быть можно ввести в профиль пользователя ключ, по установке которого в "ленте активности" изчезнут все новые посты в раздел "Отечественные компьютеры". Или даже ввести возможность выбора разделов, которые отображаются.

Northwood
19.02.2018, 19:45
Не подскажете, каким образом у Вас включается такой режим? Какой на это отечественный стандарт?

Режим 512*192 впервые применён в TIMEX-2068, но там монохром (вторая плоскость читается вместо цветового атрибута и из одной банки РУ5) и доп.экран на #6000. Но это не стандарт, т.к там диспетчер ОЗУ 8-ми оконный по 8 кб.


Цветной режим 512х192, это не совсем стандарт, его я сделал тогда, когда взялся за реализацию 16Colors (после того как уже собрал монохромный 512х192). Изучив подробно 16 Colors и начав составлять принципиальную схему в моём исполнении, и я понял, что могу сделать цветной режим 512х192, и что для него оставалось сделать совсем немного.

Для 512х192 с атрибутом цвета 8х8, раскладка по сути вообще не отличается от монохромного 512х192, только расширяется экранная область ОЗУ до области атрибутов:

#4000 - #57FF - область пикселей нечётного знакоместа;
#6000 - #77FF - область пикселей чётного знакоместа;
#5800 - #5AFF - область атрибутов нечётного знакоместа;
#7800 - #7AFF - область атрибутов чётного знакоместа.

Для дополнительного экрана используется как и раньше, 7-я страница ОЗУ.

В мультиколорном же варианте 512х192, пришлось задействовать 4 экранные области, на подобии как в режиме 16Colors, но немного в другой последовательности, так чтобы сохранилась совместимость с монохромным режимом:

#4000 - #57FF - область пикселей нечётного знакоместа;
#6000 - #77FF - область пикселей чётного знакоместа;
#C000 - #D7FF (стр.4 ОЗУ) - область атрибутов нечётного знакоместа;
#E000 - #F7FF (стр.4 ОЗУ) - область атрибутов чётного знакоместа.

Для дополнительного экрана используются соответственно 7-я и 6-я страницы ОЗУ.

Данный мультиколорный видеорежим 512х192 очень напоминает расширенный видеорежим Profi-1024, но без использования 4-й нижней "трети" экрана, т.е. без расширения разрешения по вертикали.

Выбор страниц для экрана я оставил таким же, как и в стандартном видеорежиме 16Colors.

Последовательность же экранных областей в 16Colors такая:

#С000 - #D7FF (стр.4 ОЗУ) - пиксели № 1 и 2;
#4000 - #57FF - пиксели № 3 и 4;
#E000 - #F7FF (стр.4 ОЗУ) - пиксели № 5 и 6;
#6000 - #77FF - пиксель № 7 и 8;

- - - Добавлено - - -



Чтобы получить цветной экран 512*192 надо иметь или 2 банки ОЗУ, как в ОРИОНЕ, или за время сдвига экранного байта читать 4 синклеровских экранных страницы. Интересует каким портом и битами включается этот режим и размещение экранных плоскостей в адресном пространстве и в ОЗУ.


У меня ОЗУ турбировано до 7 МГц, это даёт в 2 раза больше циклов доступа, используется не только цветными видеорежимами 512х192, а и 16Colors, который тоже требует 4 цикла чтения за такое же время. Все подробности в теме про новый Пентагон-4096:
http://zx-pk.ru/threads/28489-pentagon-1024-4096-ot-northwood.html

gobuka
20.02.2018, 09:49
Вопрос к администрации. Чтобы отечественные компьютеры не раздражали синклеристов и не отвлекали их от дела, может быть можно ввести в профиль пользователя ключ, по установке которого в "ленте активности" изчезнут все новые посты в раздел "Отечественные компьютеры". Или даже ввести возможность выбора разделов, которые отображаются.
Раздел - утилиты/эмуляция ZX-Spectrum. Свои хотелки по компам, не относящимся к ZX-Spectrum, публикуйте в соответствующем разделе. Или Вам своего раздела мало?

Если бы я был модератором
Если бы у бабушки...

Shiny
20.02.2018, 10:03
Кстати, о Спектруме. А в чем преимущество к известным утилитам bp2scr и другим?

Black Cat / Era CG
20.02.2018, 10:14
Кстати, о Спектруме. А в чем преимущество к известным утилитам bp2scr и другим?
Поддержка конвертирования во все режимы, реализуемые в Пентагоне от автора конвертера. Об чем и написано в 1 посте :)

mastermind
20.02.2018, 13:42
Похожая утилита, опенсорс, Windows/Linux/macOS: https://github.com/jarikomppa/img2spec
Может лучше ее допиливать?

Shiny
20.02.2018, 14:33
Может лучше ее допиливать?
еще бы её с фичами bmp2scr подружить. Например - масштабирование картинки итпф.

AzAtom
25.03.2018, 15:18
Какой-нибудь dithering планируется? Алгоритм Флойда-Стейнберга или сеткой (не знаю точно как он называется) были бы уместны.

- - - Добавлено - - -

Готовые черно-белые картинки плохо получаются, некоторые целые знакоместа выходят полностью черные. И если в знакоместе есть черные точки, то яркость знакоместа получается обычная, а не повышенная.

NEO SPECTRUMAN
11.06.2019, 04:47
Flash Color
А ГДЕ ЖО ФЛЕШ КОЛОР? :v2_dizzy_vodka:
НЕМЕДЛЕННО ФПИЛИТЬ! :v2_dizzy_vodka2:



очень напоминает расширенный видеорежим Profi-1024
а где прочитать про его видео режимы?
и тожо бы не помешало впилить поддержку

...


Последняя активность 13.07.2018
мда :v2_dizzy_sleep2:

Black Cat / Era CG
13.06.2019, 17:11
Он вроде бы где-то писал, что у него там какие-то проблемы, завал. В общем, ему временно не до хобби.

Serdjuk
05.08.2019, 23:24
Не подскажите где почитать за алгоритмы конвертации любой цветной картинки в 2-х цветную (wbmp например) с % дизеринга ?

Upd:


https://m.habr.com/ru/post/326936/

Dwa83
16.02.2020, 11:13
Не подскажите где почитать за алгоритмы конвертации любой цветной картинки в 2-х цветную

У себя делал так:



for (int y = 0; y < 192; y += 8) //цикл по высоте(по знакоместам)
for (int x = 0; x < 256; x += 8) //цикл по ширине(по знакоместам)
{
map<TColor,int> cmap; // создаём map в которой ключ - цвет, значение - количество пикселей данного цвета в знакоместе

for (int yy = 0; yy < 8; yy++)//цикл по пикселям знакоместа
for (int xx = 0; xx < 8; xx++)
{
TColor c = ColorMod(Canvas->Pixels[x+xx][y+yy]); // модификация цвета пикселя в отдельной функции
Canvas->Pixels[260+x+xx][y+yy] = c; // выведем преобразованную картинку рядом с оригиналом(цвета уже ZX, но не 2 цвета на знакоместа)
cmap[c]++; // увеличим счётчик данного цвета в мапе
}

map<TColor,int>::iterator it;

TColor ink = TColor(0);// цвет INK пока что чёрный
int ci = 0; // переменная для сравнения количества пикселей разных цветов

// найдём цвет, который в знакоместе встречается чаще всех, и сделаем INK
for (it = cmap.begin(); it != cmap.end(); it++) // пройдёмся по map с сохранёнными цветами
{
if (it->second > ci) //если количество пикселей данного цвета больше чем предыдущее сохранённое количество
{
ci = it->second; //сохраним наибольшее количество
ink = it->first; // сохраним сам цвет, который соответствует этому количеству
}
}

// удалим с мапы найденый цвет
cmap.erase(ink);

TColor paper = TColor(0);
int cp = 0;

// найдём второй цвет, который в знакоместе встречается чаще всех после INK, и сделаем его цветом PAPER
for (it = cmap.begin(); it != cmap.end(); it++)
{
if (it->second > cp)
{
cp = it->second;
paper = it->first;
}
}

// все остальные цвета, отличные от PAPER и INK, будем выводить либо тем, либо вторым цветом.
bool cur = false; // если истина - INK, если ложь - PAPER(так появится зернистость, чередование цвета INK и PAPER в тех местах, где цвета отличные от данных)

// опять пройдёмся по изображению
for (int yy = 0; yy < 8; yy++)
for (int xx = 0; xx < 8; xx++)
{
TColor c = Canvas->Pixels[260+x+xx][y+yy];
// далее чередование цветов
if (c != ink && c != paper)
{
if (cur) c = ink;
else c = paper;
cur = !cur;
}

Canvas->Pixels[260+x+xx][y+yy] = c;
}

}

И вспомогательные функции


// принимает компонент RGB цвета
int Compr(int c)
{
if (c < 96) return 0; // если меньше 96, то этот цвет ближе к чёрному
if (c >= 224) return 255; // если больше 224, то цвет ближе к цвету повышенной яркости, чем к обычному
return 192;// иначе цвет обычной яркости
}

// принимает RGB цвет
TColor ColorMod(TColor c)
{
// выделим компоненты
int r = Compr(GetRValue(c));
int g = Compr(GetGValue(c));
int b = Compr(GetBValue(c));

// тут два варианта преобразования
int brig = (r!=192 && g!=192 && b!=192) ? 255 : 192; // повышенная яркость только тогда, когда все компоненты с повышенной яркостью(либо 0)
//int brig = (r==255 || g==255 || b==255) ? 255 : 192; // если хотябы 1 компонент повышеной яркости, то всё знакоместо будем считать повышенной яркости, иначе всё знакоместо обычной яркости
if (r != 0) r = brig;
if (g != 0) g = brig;
if (b != 0) b = brig;

return (TColor)RGB(r, g, b);
}


Результаты(оригинал - вариант 1 - вариант 2):
https://zx-pk.ru/attachment.php?attachmentid=71533&d=1581841327
71531