Login

Subversion Repositories NedoOS

Rev

Rev 805 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

универсальная палитра (atmuni16.act до замены на телесные, skin16.act после, soft16.act с мягкими цветами вместо чистых+3,2,2 вместо M):
R,G,B
основные цвета, чтобы можно было сконвертить всё (можно оставить только 0RGBW + 3 телесных цвета? hue c,m,y будут только с помощью засветок):
0,0,0
0,0,3 B (1,1,2 мягче)
3,0,0 R (2,1,1 мягче)
3,0,3 M (2,1,2 мягче) (3,2,1 для 34n1) - заменить на телесный 3,2,1? (для мягких 3,2,2)
0,3,0 G (1,2,1 мягче)
0,3,3 C (1,2,2 мягче) - заменить на телесный 3,2,2?
3,3,0 Y (2,2,1 мягче) - заменить на телесный 2,1,1?
3,3,3
серые:
2,2,2
1,1,1 (new)
коррекция теней:
0,0,1 (new)
0,1,0 (new)
1,0,0 (new)
коррекция засветок:
3,3,2 (new)
3,2,3 (new)
2,3,3 (new)

палитру см. в scratch/kuler

как конвертировать в неё?
нужна таблица RGB->colorindex и таблица colorindex->RGB (по ней будет делаться floyd-steinberg)
а как делать diamond? надо как-то находить RGB->4xcolorindex, а потом между этими 4 цветами текстурить
а как делать hires? надо как-то находить 4 лучших цвета для каждой зоны и чередовать их через строчку? будут проблемы с зонами, где есть чёрный и яркие цвета, надо будет иметь 2 чёрных

какой формат хранения картинки в DOM? 24bit жирно! 16bit? или 8bit без диферинга с универсальной палитрой
какая универсальная палитра 256?
а) RRRGGGBB?
б) YYYYYUUVV?

в) разбить по насыщенностям (на ATM видно 3), на ATM видно 18/12/6 оттенков (сделаем 36, но как округлять и до 18, и до 12?), 7 яркостей (включая 0,W)
saturation2 (на ATM 18 hue): 36 hue * 5 volume (реально видно 5)
saturation1 (на ATM 6 hue): 12 hue * 5 volume (реально видно 1)
saturation0 (на ATM 1 hue): 1 hue * 5 volume (реально видно 2)
0
W
=247 цветов
проблема с округлением hue при отображении в ATM без диферинга
 чтобы иметь точки точных цветов и при этом уметь округлять одни и те же hue до 18 и до 12, надо иметь нечётные группы, но они не могут иметь соотношение 2:3! реальнее 3:4.5:
храним 54 hue
как округлять до 18 hue:
0!,1),(2,3!,4),(5,6!,7),(8,9!,10),...
как округлять до 12 hue:
0!,1,2),(3,4(,)5,6),(7,8,9!,10,11),...
 чтобы округлять одни и те же hue до 12 и до 6, надо соотношение 1:2, реальнее 3:6
храним 36 hue
как округлять до 12 hue:
0!,1),(2,3!,4),(5,6!,7),(8,9!,10),...
как округлять до 6 hue:
0!,1,2),(3,4,5,6!,7,8),(9,10,11,...

храним 18 hue
как округлять до 12 hue:
0!),(1,2),(3!),(4,5),(6!),(7,8),(9!),(10,...

г) разбить по насыщенностям и яркостям (большие и малые яркости имеют меньше hue), volume 0 и 6 отдельно
насыщенностей особо много не надо? добавить только ещё одну малонасыщенную? но как её отображать без диферинга? как нулевую (переход в серый обычно не страшен) или как соседнюю? или лучше 2 малонасыщенных
/*
saturation4, volume5 (на ATM 6 hue): 36 hue
saturation4, volume4 (на ATM 12 hue): 54 hue
saturation4, volume3 (на ATM 18 hue): 54 hue
saturation4, volume2 (на ATM 12 hue): 54 hue
saturation4, volume1 (на ATM 6 hue): 36 hue
^^^^^^^^^ это уже 234!
saturation3, volume5 (на ATM 6 hue): 6 hue
saturation3, volume4 (на ATM 6 hue): 6 hue
saturation3, volume3 (на ATM 6 hue): 6 hue
saturation3, volume2 (на ATM 6 hue): 6 hue
saturation3, volume1 (на ATM 6 hue): 6 hue

saturation2, volume5 (на ATM ? hue): 6 hue
saturation2, volume4 (на ATM ? hue): 6 hue
saturation2, volume3 (на ATM ? hue): 6 hue
saturation2, volume2 (на ATM ? hue): 6 hue
saturation2, volume1 (на ATM ? hue): 6 hue

saturation1, volume5 (на ATM ? hue): 6 hue
saturation1, volume4!(на ATM ? hue): 6 hue
saturation1, volume3 (на ATM ? hue): 6 hue
saturation1, volume2!(на ATM ? hue): 6 hue
saturation1, volume1 (на ATM ? hue): 6 hue
^^^^^^^^^^ это ещё 108!
saturation0, volume5 (на ATM 1 hue): 1 hue
saturation0, volume4!(на ATM 1 hue): 1 hue
saturation0, volume3 (на ATM 1 hue): 1 hue
saturation0, volume2!(на ATM 1 hue): 1 hue
saturation0, volume1 (на ATM 1 hue): 1 hue
*/

/*
saturation2, volume5 (на ATM 6 hue): 6 hue?
saturation2, volume4 (на ATM 12 hue): 18 hue
saturation2, volume3 (на ATM 18 hue): 54 hue
saturation2, volume2 (на ATM 12 hue): 18 hue
saturation2, volume1 (на ATM 6 hue): 18 hue
^^^^^^^^^^^^ это уже 114
saturation2-, volume5 (на ATM 6 hue): 6 hue
saturation2-, volume4 (на ATM 12 hue): 18 hue
saturation2-, volume3 (на ATM 18 hue): 18 hue
saturation2-, volume2 (на ATM 12 hue): 18 hue
saturation2-, volume1 (на ATM 6 hue): 6 hue
^^^^^^^^^^ это ещё 66
saturation1, volume5 (на ATM 1 hue): 6 hue?
saturation1, volume4 (на ATM 1 hue): 6 hue
saturation1, volume3 (на ATM 1 hue): 6 hue
saturation1, volume2 (на ATM 6 hue): 18 hue
saturation1, volume1 (на ATM 1 hue): 6 hue
^^^^^^^^^^ это ещё 42 (итого уже 222)
saturation0+, volume5 (на ATM 1 hue): 1 hue?
saturation0+, volume4!(на ATM 1 hue): 6 hue
saturation0+, volume3 (на ATM 1 hue): 6 hue
saturation0+, volume2!(на ATM 1 hue): 6 hue
saturation0+, volume1 (на ATM 1 hue): 6 hue

saturation0, volume4+(на ATM 1 hue): 1 hue
saturation0, volume4!(на ATM 1 hue): 1 hue
saturation0, volume4-(на ATM 1 hue): 1 hue
saturation0, volume2+(на ATM 1 hue): 1 hue
saturation0, volume2!(на ATM 1 hue): 1 hue
saturation0, volume2-(на ATM 1 hue): 1 hue
0
W
=255 цветов, но цветов больше всего надо не при максимальной насыщенности, а при промежуточной
*/

цветов больше всего надо не при максимальной насыщенности, а при промежуточной (но отображаем её как максимальную, т.к. в saturation1 только 6 hue)
зона saturation1 должна быть широкая, чтобы в неё попадало побольше пикселей (т.е. как бы присутствует saturation 1-, а то и 1+ той же ширины?)
saturation2, volume5 (на ATM 6 hue): 6 hue
saturation2, volume4 (на ATM 12 hue): 12 hue
saturation2, volume3 (на ATM 18 hue): 18 hue
saturation2, volume2 (на ATM 12 hue): 12 hue
saturation2, volume1 (на ATM 6 hue): 6 hue
^^^^^^^^^^^^ это уже 54
saturation2-, volume5 (на ATM 6 hue): 6 hue
saturation2-, volume4 (на ATM 12 hue): 12 hue
saturation2-, volume3 (на ATM 18 hue): 54 hue (*3)
saturation2-, volume2 (на ATM 12 hue): 18 hue
saturation2-, volume1 (на ATM 6 hue): 6 hue
^^^^^^^^^^ это ещё 96
saturation1, volume5 (на ATM 1 hue): 6 hue
saturation1, volume4 (на ATM 1 hue): 6 hue
saturation1, volume3 (на ATM 1 hue): 18 hue
saturation1, volume2 (на ATM 6 hue): 30 hue? (*5)
saturation1, volume1 (на ATM 1 hue): 6 hue
^^^^^^^^^^ это ещё 66
saturation0+, volume4+(на ATM 1 hue): 1 hue
saturation0+, volume4!(на ATM 1 hue): 6 hue
saturation0+, volume4-(на ATM 1 hue): 6 hue
saturation0+, volume2+(на ATM 1 hue): 6 hue
saturation0+, volume2!(на ATM 1 hue): 6 hue
saturation0+, volume2-(на ATM 1 hue): 6 hue

saturation0, volume4+(на ATM 1 hue): 1 hue
saturation0, volume4!(на ATM 1 hue): 1 hue
saturation0, volume4-(на ATM 1 hue): 1 hue
saturation0, volume2+(на ATM 1 hue): 1 hue
saturation0, volume2!(на ATM 1 hue): 1 hue
saturation0, volume2-(на ATM 1 hue): 1 hue
0 (volume0)
W (volume6)
=255 цветов

Можно уточнять только вокруг реально используемых 16 цветов, а остальные цвета - просто RRGGBB
но уточнение - это 26 дополнительных цветов (куб 3x3x3)! (кроме тех, которые на поверхности, а на поверхности 56 из 64 цветов, 14 из 16)
 для стандартной палитры:
в углу 8 цветов - их уточняют по 4 цвета (итого 32)
на ребре 6 цветов - их уточняют по 12 цветов (итого 96)
на поверхности грани 0 цветов
внутри 2 цвета - их уточняют по 26 цветов (итого 52)
64+32+96+52 = 244
 для стандартной палитры со смягчёнными чистыми цветами (+3,2,2 вместо M):
в углу 2 цвета - их уточняют по 4 цвета (итого 8)
на ребре 6 цветов - их уточняют по 12 цветов (итого 96)
на поверхности грани 1 цвет - его уточняют 17 цветов (итого 17)
внутри 7 цветов - их уточняют по 26 цветов (итого 182)
8+96+18+182 = 303 невозможно! надо перенести 5 внутренних цветов на грани

softb16.act:
0,0,0 0
1,1,2 b
2,1,1 r
3,2,2 R телесный
1,2,0 g травяной
2,2,3 B? (2,3,1 G softc16.act) (3,2,1 O softd16.act для рубашек на картине)
2,2,1 y
3,3,3 W
серые:
2,2,2 S
1,1,1 s
коррекция теней:
0,0,1 b0
0,1,0 g0
1,0,0 r0
коррекция засветок:
3,3,2 YW
3,2,3 MW (3,3,1 Y softe16.act для лампы у джедая)
2,3,3 CW

в углу 2 цвета (0,W) - их уточняют по 4 цвета (итого 8)
на ребре 6 цветов (b0,r0,g0,YW,CW,Y) - их уточняют по 12 цветов (итого 96)
на поверхности грани 3 цвета (R,g,O) - их уточняют по 17 цветов (итого 51)
внутри 5 цветов (s,S,b,r,y) - их уточняют по 26 цветов (итого 130)
8+96+51+130 = 285 невозможно! можно убрать уточнение для g? (т.к. он оторван) будет 259
можно вместо этого убрать уточнения с поверхности фигуры, т.к. их невозможно никак отрисовать
или оставить только точки внутри фигуры (or 64 стандартных цвета), получается 263
какие 7 уточняющих цветов убрать? окрестность Y (3) и окрестность псевдоточки r0+g

x=g(0..9), y=b(9..0)
R=9:
1001001001 ;W
0000000011
0000000111
1001001111 ;YW
0000001111
0000001100
1001001101 ;Y (окрестность убрана)
0000000000
0000000000
1001001001

R=8:
0000000001
0000000011
0000000111
0000001111
0000011111
0000011110
0000011110
0000000000
0000000000
0000000000

R=7:
0000000001
0000000111
0000001111
0000011110
0000011110
0000111100
0000111100
0000000000
0000000000
0000000000

R=6:
1001001001 ;CW
0000000110
0000001110
1001011101
0000011100
0000111000
1001111001
0000000000
0000000000
1001001001

R=5:
0000000000
0000001100
0000011100
0000111110
0000111100
0001111100
0001111000
0011111000
0000000000
0000000000

R=4:
0000000000
0000000000
0000010000
0000110000
0001111000
0001111000
0011111100
0011111000
0111111000
0000000000

R=3:
1001001001
0000000000
0000000000
1001001001
0001000000
0011100000
1011101001
0111110000
0110110000
1101011001 ;окрестность r0+g убрана

R=2:
0000000000
0000000000
0000000000
0000000000
0010000000
0011000000
0111000000
0111100000
1111100000
1110110000 ;окрестность r0+g убрана

R=1:
0000000000
0000000000
0000000000
0000000000
0000000000
0100000000
0110000000
1111000000
1111000000
1111100000

R=0:
1001001001
0000000000
0000000000
1001001001
0000000000
0000000000
1001001001
1100000000
1110000000
1111001001

палитру256 см. в scratch/kuler

телесные цвета с фотографий вроде бы вписываются в основное пятно цветов, но точность представления недостаточная!

Нужна таблица R5G5B5 -> index256 (займёт 32K), можно R5G5B4? (16K)

для diamond выгодно уточнять не в 3 раза, а в 4

телесный цветопереход
на портрете незнакомки: 001 101 111 211 212 312 322 422 423 533 (534щека) 633 644 744 754(плохо) 854 864(плохо) 865 875(плохо) 975 976 986(плохо)
 не хватает (7.5 4.5 4) (8 5.5 4.5) (8.5 6.5 5) (9 7.5 6.5??? Photoshop не находит)
на джедае: ... 432 532 542(плохо) 643 743 753 853 (863(плохо)) 960(ужасно, надо 963, но на картинке реально с яркостью уменьшается значение B - или так совпали пятна шума)
 не хватает (5.5 3.5 2.5) (8.5 5.5 3)


диферинг из индексных цветов в экранные (буфер картинки EGA):
где хранить ошибку для следующей строки? буфер на ширину строки картинки?
диферинг только по горизонтали?
init. r,g,b = 0
0.r,g,b += pal256[pixline[x]]
1.найти цвет c16 самый близкий к r,g,b
2.scrline[x]=c16
3.r,g,b -= rgb[c16] //знаковый результат
4.x++

;hl=pixline
;??=scrline
;?=pixline low
;???=pixline step
;bc=rgb (он же адрес таблицы c16[rgb]) = %11RRRRRGGGGGBBBB, где RRRRR,GGGGG = 3..12 в норме (макс. ошибка = +-3??? к тому же, 10 значений недостаточно для телесных) (по уму ошибка не должна превышать +-6 по каждой оси, диапазон значений надо -6..+15, таблица 21x21x21 без телесных=9261, с телесными можно уточнить только одну ось или две с заходом в нижнюю память) (реально может быть вылет за углы без палитровых цветов? тогда ошибка больше?)
;de=pal256
;окна: 1=scrline, 2=pixline, 3=c16[rgb]
;или лучше промежуточный буфер для масштабирования строки и хранения ошибок? окна: 1=scrline, 2,3=c16[rgb]
/*
 абсолютный минимум:
ld e,(hl)
inc hl ;TODO ходить с масштабом
ld d,pal256/256
ld a,(de)
add a,c
ld c,a ;
inc d
ld a,(de)
adc a,b
ld b,a ;bc=rgb
inc d
ld a,(bc) ;c16
ld (..),a ;scrline[x]=c16 ;TODO сразу класть 2 пикселя
ld e,a ;mrgb[c16]
ld a,(de)
add a,c
ld c,a ;
inc d
ld a,(de)
adc a,b
ld b,a ;bc=drgb ;знаковый!
*/
 масштабирование и вычисление rgb (сгенерированный код, рисует справа налево):
add/adc hl,bc ;bc<0, CY=1
ld e,(hl) ;de=pal256+0/+256
ld a,(de)
ld (..l/h),a
inc/dec d
ld a,(de)
ld (..h/l),a
:64t/pix (каждый второй проход можно 62t через push af)
 
 диферинг:
/*
pop de
add hl,de ;hl=rgb
 set 7,h ;TODO как избежать переполнения по R?
ld a,(hl) ;c16
ld (..),a ;scrline[x]=c16 ;TODO сразу класть 2 пикселя
 ;ld (),a ;c16 чётное
 ;ld de,()
 ;add hl,de ;13+20+11=34
ld d,mrgbc16/256
ld e,a ;de=mrgb[c16]
ld a,(de)
add a,l
ld l,a
inc d
ld a,(de)
adc a,h
ld h,a ;bc=drgb ;знаковый! ;7+4+7+4+4+4+7+4+4=45
*/
pop de
add hl,de ;hl=rgb
ld a,(hl) ;c16 (left)
 ld (),a ;c16 чётное
 ld de,() ;de=mrgb[c16]
 add hl,de
pop de
add hl,de ;hl=rgb
ld e,a ;c16 (left)
ld a,(hl) ;c16 (right)
 ld (),a ;c16 чётное
ld d,a ;d=right,e=left ;de = %001rrrr0 001LLLL0
ld a,(de) ;%rlrrrlll
 ld de,() ;de=mrgb[c16]
 add hl,de
ld (bc),a ;scrline[x]=%rlrrrlll ;сразу кладём 2 пикселя
inc bc
:172t/2pix = 86t/pix

вывод картинки на экран (EGA):
надо брать байты через 4 (или через 2 распихивать в 2 блока памяти)
выводим по произвольному адресу и можем не на всю ширину картинки!
/*
Распихиваем через один байт в 2 блока памяти (di!):
pop af
ld (hl),a
inc hl
pop af
ld (de),a
inc de
;проблема с прерыванием! второй раз не прочитаем!!! читать из стека можно только через de
*/
/*
Распихиваем через один байт в 2 блока памяти (ei):
pop de
ld (hl),e
inc hl
pop de
ld a,e
ld (bc),a
inc bc
:50t/2byte = 25t/byte = 12.5t/pix
*/
Распихиваем в 4 блока памяти (di! т.к. после exx уже неактуальное de):
pop de
ld (hl),e
inc hl
ld a,d
exx
ld (bc),a
inc bc
pop de
ld (hl),e
inc hl
ld a,d
exx
ld (bc),a
inc bc
:88t/4byte = 22t/byte = 11t/pix
можно иметь 32 копии процедуры (с разными начальными x), тогда большинство inc rp можно заменить на inc r

вывод картинки в мультиколор, сначала два слоя пикселей (а потом так же - атрибуты):
pop de
ld (hl),e
set 5,h
ld (hl),d
inc hl
pop de
ld (hl),d
res 5,h
ld (hl),e
inc hl
:38t/2byte = 19t/byte
;3b/b, т.е. вся строка пикселей (она же строка атрибутов) = 3*80 = 240 b
в конце в нужном месте поставить jp (ix) сразу после ld (hl) - это нужно только один раз на всю картинку
+вход с разных мест - для разного начального положения картинки на экране


/*
по вертикали (если картинка разложена по вертикали):
pop de
ld (hl),e
add hl,bc
ld (hl),d
add hl,bc
:46t/2byte = 23t/byte = 11.5t/pix
*/

Как делать диферинг в хайрез?
Нужно найти 2 набора по 2 цвета (для чётных и нечётных строк) и конвертить в эти палитры с распространением ошибки вправо и вниз!
большинство знакомест имеют чёрный или белый фон? (достаточно найти один чёрный пиксель для paper=0 или один белый пиксель для ink=1) (а как найти второй цвет? должно отличаться для чётных и нечётных строк)
из остальных большинство цветопереходы? как найти для них 2 цвета? должно отличаться для чётных и нечётных строк?
по идее надо найти 2 самых дальних друг от друга цвета?
если просто искать minR,maxR и т.п. по каждой составляющей, то непонятно, какую диагональ брать
надо поэтому по каждой оси искать минимум, максимум и соответствующие им цвета
потом взять ось с самым большим расстоянием и цвета из неё
для этого надо только уметь быстро считать R,G,B от пикселя

ошибка при этом может быть очень большая! может ли накапливаться при продвижении (тогда нужно усечение)? ошибка должна размываться по всему нижеследующему знакоместу или не влиять на него (тогда надо другую логику для поиска палитры нечётных строк)?

Как конвертить rgb в 2 заданных цвета? палитр может быть очень много, страничек не хватит под таблицы bit[curpal,rgb]!!!
тогда надо искать расстояние от rgb до заданного цвета, надо 16 страничек под таблицы dist[color16,rgb]!!!
переключение страничек - это долго, можно попробовать sum(distr,distg,distb), где distX = abs[r[rgb]-colorr], но три таблицы от rgb - жирно, придётся вручную выделять биты из rgb!
это значит, что диапазон цветовой составляющей должен быть 0..15 (необходимо ручное усечение) или 0..31
или отказаться от флойда-стейнберга, придумать быстрый алгоритм для diamond? bit = f(curpal,rgb,xyphase)

для знакомест с чёрным или белым фоном можно перед конверсией нормировать цвета в уровни 0(чёрный или цвет)..1(белый или цвет)
для знакомест с двумя цветами можно перед конверсией нормировать цвета в уровни 0(цвет1)..1(цвет2)
тогда диферинг тривиален, хоть флойд, хоть diamond
как нормировать? 2 цвета нельзя нормировать по яркости
а проекция на линию - жирно
выбрать одну цветовую составляющую (где самая большая разница) и по ней нормировать? (ту же, по которой искали 2 самых далёких цвета)
пусть это оказалась R:
R = R(pixel) ;округлено так же, как Rmin,Rmax!
inklevel = (R-Rmin)/maxdist
bit = (inklevel > chunklevel[x%4][y%4])
деление .5/.5 (отрицательные приводим к 0? или не будет вне 0..1, т.к. берём Rmin и Rmax)

Надо перед конверсией строки (или строки знакоместа) копировать её (в нужном масштабе) в нижнюю память в виде R(+0),G(+8),B(+16), иначе проблемы с окнами памяти и лишними конверсиями?
Это можно сделать в 3 прохода (с разными таблицами R(rgb)) или лучше делать таблицы R(index256)


        macro DITHERMC ch0,ch1,ch2,ch3
;поиск 2 цветов (запоминаем положения рекордных цветов, чтобы потом их прочитать):
        ld hl,chrbuf
_=(chrbuf+8)&0xff
        ld de,_*257
        ld c,(hl) ;Rmin
        ld b,c ;Rmax
_=_+1
        dup 7
        inc l
        ld a,(hl) ;R(pixel)
        cp c ;Rmin
        jr nc,$+2+1+2
         ld c,a ;Rmin
         ld e,_ ;Rmincolor = положение текущего цвета
        cp b ;Rmax
        jr c,$+2+1+2
         ld b,a ;Rmax
         ld d,_ ;Rmaxcolor = положение текущего цвета
_=_+1
        edup
        push de ;ld (Rminmaxcolor),de
        ld a,b
        sub c
        push af

        inc l ;ld hl,chrbuf+8
_=(chrbuf+8)&0xff
        ld de,_*257
        ld c,(hl) ;Gmin
        ld b,c ;Gmax
_=_+1
        dup 7
        inc l
        ld a,(hl) ;G(pixel)
        cp c ;Gmin
        jr nc,$+2+1+2
         ld c,a ;Gmin
         ld e,_ ;Gmincolor = положение текущего цвета
        cp b ;Gmax
        jr c,$+2+1+2
         ld b,a ;Gmax
         ld d,_ ;Gmaxcolor = положение текущего цвета
_=_+1
        edup
        push de ;ld (Gminmaxcolor),de
        ld a,b
        sub c
        push af

        inc l ;ld hl,chrbuf+16
_=(chrbuf+8)&0xff
        ld de,_*257
        ld c,(hl) ;Bmin
        ld b,c ;Bmax
_=_+1
        dup 7
        inc l
        ld a,(hl) ;B(pixel)
        cp c ;Bmin
        jr nc,$+2+1+2
         ld c,a ;Bmin
         ld e,_ ;Bmincolor = положение текущего цвета
        cp b ;Bmax
        jr c,$+2+1+2
         ld b,a ;Bmax
         ld d,_ ;Bmaxcolor = положение текущего цвета
_=_+1
        edup
        ;ld (Bminmaxcolor),de
        ld a,b
        sub c

;выбираем лучшую ось и её minmaxcolor:
        ld c,a ;maxdist
        pop af ;Gmax-Gmin
        pop hl ;Gminmaxcolor
        cp c ;>=maxdist?
        jr c,$+2+1+1
         ld c,a ;maxdist
         ex de,hl
        pop af ;Rmax-Rmin
        pop hl ;Rminmaxcolor
        cp c ;>=maxdist?
        jr c,$+2+1
         ex de,hl

;d=maxcolor
;e=mincolor
;берём рекордные цвета (в виде color16):
;чтобы получить color16, надо сначала color64(=BBGGRR), потом по таблице из него
        ld h,chrbuf/256
        ld l,d ;maxcolor
;округлять вверх! +32 (найдено подбором)
        ld a,(hl) ;G
         add a,32
         jr nc,$+3
         sbc a,a
        ld c,a
        res 3,l
        ld a,(hl) ;R
         add a,32
         jr nc,$+3
         sbc a,a
        ld b,a
        set 4,l
        ld a,(hl) ;B
         add a,32
         jr nc,$+3
         sbc a,a
        rlca
        rlca
        rl c
        rla
        rl c ;g
        rla
        rl b
        rla
        rl b ;r
        rla ;BBGGRR
        and 0x3f
        ld l,a
        ;ld h,t64to16ink/256
        ld d,(hl) ;d=maxcolor16=ink
        ld l,e ;mincolor
        ;ld h,chrbuf/256
;округлять вниз! -32 (найдено подбором)
        ld a,(hl) ;G
         sub 64
         jr nc,$+3
         xor a
        ld c,a
        res 3,l
        ld a,(hl) ;R
         sub 64
         jr nc,$+3
         xor a
        ld b,a
        set 4,l
        ld a,(hl) ;B
         sub 64
         jr nc,$+3
         xor a
        rlca
        rlca
        rl c
        rla
        rl c ;g
        rla
        rl b
        rla
        rl b ;r
        rla ;BBGGRR
        or 0xc0
        ld l,a
        ;ld h,t64to16paper/256
        ld a,(hl) ;a=mincolor16=paper
        or d
;a=attr
        exx
        ld (hl),a ;записать attr
        inc hl
        exx

;по реальным атрибутам заново пересчитать maxaxis, min, maxdist! (проверено, что без этого получается пятнистость):
        ld l,a
        ld h,tmaxaxis/256
        ld d,(hl) ;maxdistdiv
        inc h
        ld b,(hl) ;min
        inc h
        ld l,(hl) ;maxaxis*3
        ld h,chrbuf/256

;b=R/G/Bmin
;hl на начале буфера R/G/B
;d=maxdistdiv
;в диферинге ходим только по одной составляющей, остальные не читаем:
        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch0 ;chunklevel[x%4][y%4]
        rl c ;bits
        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch1 ;chunklevel[x%4][y%4]
        rl c ;bits
        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch2 ;chunklevel[x%4][y%4]
        rl c ;bits
        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch3 ;chunklevel[x%4][y%4]
        rl c ;bits

        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch0 ;chunklevel[x%4][y%4]
        rl c ;bits
        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch1 ;chunklevel[x%4][y%4]
        rl c ;bits
        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch2 ;chunklevel[x%4][y%4]
        rl c ;bits
        ld a,(hl) ;R(pixel)
        inc l
        sub b ;Rmin
         rra ;на случай отрицательных
        ld e,a ;d=maxdistdiv
        ld a,(de) ;inklevel
        cp ch3 ;chunklevel[x%4][y%4]
        ld a,c
        rla ;bits
        exx
        ld (de),a ;записать bits
        inc de
        exx
        endm
;таких 4 шт (для разных фаз y)

 ;0 бессмысленно (всегда NC), поэтому все значения увеличены на 1:
dithermcy0
        DITHERMC 0x1, 0xd, 0x3, 0xf
        ret
dithermcy1
        DITHERMC 0x9, 0x5, 0xb, 0x7
        ret
dithermcy2
        DITHERMC 0x4, 0x10, 0x2, 0xe
        ret
dithermcy3
        DITHERMC 0xc, 0x8, 0xa, 0x6
        ret

tmaxdistdiv:
h=maxdist/4=0..63
l=R-Rmin=0..255
out: 0..16 = (R-Rmin)/maxdist
команды cp будет в диапазоне 1..16, все могут выдать C/NC

        
куда записывать attr и c?
все окна свободны! (можно одно окно = tmaxdistdiv)
можно класть подряд: attreven, bitseven, attrodd, bitsodd
тогда вывод на экран будет как в 16ц
а можно разделить на блок атрибутов и блок битов
тогда вывод на экран такой:
        pop de
        ld (hl),e
        set 5,h
        ld (hl),d
        inc hl
        pop de
        ld (hl),d
        res 5,h
        ld (hl),e
        inc hl
:38t/2byte = 19t/byte = 9.5t/pix


        align 256
t64to16ink
        dup 64
;%00003210 => %.3...210
_3=$&8
_210=$&7
        nop ;db (_3*0x08) + (_210*0x01) ;надо генерировать из заданной палитры
        edup
chrbuf
        ds 8 ;R
        ds 8 ;G
        ds 8 ;B
        ds 256-64-24-64
t64to16paper
        dup 64
;%00003210 => %3.210...
_3=$&8
_210=$&7
        nop ;db (_3*0x10) + (_210*0x08) ;надо генерировать из заданной палитры
        edup

Картинка выглядит лучше, если чётные строчки округляют макс. цвета вверх на +32, а нечётные округляют мин. цвета вниз на -32
Дилемма:
если выбирать мин и макс с запасом, то простые надписи получаются на фоне шума
а если выбирать без запаса, то плохо на цветопереходах

       
в jpeg RTAB,GTAB,BTAB не используются?

TODO в jpeg строки >1024, для этого рендерить блоки строк в один поток длиной несколько страниц с чередованием цветовых составляющих (Y,U,V -> после пересчёта становится R,G,B)
можно просто не рендерить каждую вторую строку, но тогда нельзя будет увеличить

girl.jpg 23.02.2019 71680t = 71.82 s (JPEG v0.50 ч/б = 39 s, RGB = 83.79 s)


TODO показ картинок в EGA, т.к. diamond смотрится плохо даже в hires
перевести весь интерфейс в EGA?

TODO при конверсии gif свопиться, а то может не хватать памяти на коегоне даже при захвате рамдиска (gif использует буфер текущей картинки в RGB (не index!) для реализации прозрачности)


TODO в gif попробовать:
add a,a
call z,readbyte
adc hl,hl ;result

TODO key_esc во время конверсии gif (хотя бы после кадра)
и во время конверсии jpeg (хотя бы после блока строк)