Здесь речь пойдёт о том, как определить величины
a0a7 (яркость цветов 07 при
bright=0) и b0b7 (яркость тех
же цветов при bright=1), когда изображение выводится в
Очевидно, эти величины могут быть различны для разных моделей ZX Spectrum,
для разных преобразователей цветного сигнала в
Что можно сказать сразу?
| 1. | Самый тёмный цвет чёрный: |
a0 = 0, b0 = 0.
| 2. | Самый яркий цвет белый при bright=1: |
b7 = 255.
| 3. | Яркость всех остальных цветов принимает промежуточные значения: |
0 < (а1а7, b1b6) < 255.
| 4. | С увеличением номера цвета яркость возрастает: |
| a1 > a0, | b1 > b0, | |
| a2 > a1, | b2 > b1, | |
| ....... | ....... | |
| a7 > a6, | b7 > b6. |
| 5. | Для каждого цвета, кроме чёрного, яркость при bright=1 больше, чем при bright=0: |
| b1 > a1, |
| b2 > a2, |
| ....... |
| b7 > a7. |
Итак,
![]() |
Выше мы говорили «яркость», а каков физический смысл этого
понятия? Определим его так: яркость некоторого цвета (точнее, яркость
градации, соответствующей этому цвету при
Если вывести в одной половине экрана
| x = k y + (1 k) z, | (1) |
| где | x яркость исходного цвета, |
| y яркость тёмного цвета, | |
| z яркость светлого цвета, | |
| k доля пикселов тёмного цвета, | |
| 1 k доля пикселов светлого цвета. |
Например, если яркости уравнялись при заполнении второй половины экрана текстурой 4x4, в которой 3 пиксела тёмного цвета и 13 пикселов светлого цвета, это будет записано так:
| x = 3/16 y + 13/16 z. |
Используем вышеизложенное для вычисления искомых яркостей a0a7 и b0b7. Сначала выразим яркость каждого из цветов b1b6 через яркость соседних с ним цветов:
b1 = k1b0 + (1k1)b2, (2)
b2 = k2b1 + (1k2)b3,
.....................
b6 = k6b5 + (1k6)b7.
|
Из (2) следует:
b1k1b0
b2 = -------.
1k1
|
И далее:
b2k2b1
b3 = -------,
1k2
b3k3b2
b4 = -------,
1k3
.............
b6k6b5
b7 = -------.
1k6
|
Таким образом, зная b0 и b1, а также k1k6 (находимые опытным путём), можно последовательно вычислить b2b7.
Значение b0 нам известно это 0. Значение b1 неизвестно, зато мы знаем, что b7=255. Можно выразить b7 через b1, затем определить b1 и далее вычислить b2b6. Но этот путь связан с громоздкими преобразованиями. Поступим проще. Заметим, что b2b7 линейно зависят от b1. В этом нетрудно убедиться из вышеприведённых формул (не забывая, что b0=0). Примем b1=1 и вычислим b2b7. Тогда достаточно определить, во сколько раз получившееся значение b7 оказалось меньше 255, и затем умножить каждое из вычисленных значений b1b7 на эту величину, чтобы получить их истинные значения.
После того, как яркости цветов с bright=1 известны, остаётся определить яркости цветов с bright=0 (a1a7). Для этого достаточно найти опытным путём для каждого из этих цветов эквивалентную по яркости смесь двух цветов с bright=1, после чего воспользоваться формулой (1).
Это была теория, а теперь перейдём к практике. Рассмотрим, как я определял уровни яркости на своём компьютере и что для этого использовал.
Сначала я написал процедуру, которая заполняет верхнюю часть экрана одним цветом, а нижнюю смесью пикселов двух других цветов (с помощью текстуры 4x4). Вот она:
LD H,1 ;Исходный цвет.
LD D,0 ;Тёмный цвет.
LD E,2 ;Светлый цвет.
LD L,4 ;Номер текстуры (0-16).
;Заполняем верхнюю половину экрана:
LD A,H
ADD A,A
ADD A,A
ADD A,A
ADD A,H
;Если исходный цвет - с повышенной яркостью (bright=1), то
;следует команда ADD A,#40, иначе она не нужна (можно заменить
;на ADD A,0):
ADD A,#40
EXX
LD HL,#5800
LD DE,#5801
LD BC,#180
LD (HL),A
LDIR
EXX
;Заполняем нижнюю половину экрана:
LD A,D
ADD A,A
ADD A,A
ADD A,A
ADD A,E
ADD A,#40
EXX
LD BC,#17F
LD (HL),A
LDIR
EXX
;Заполнение текстурой:
LD H,0
ADD HL,HL
ADD HL,HL ;*4
LD DE,TEXTURES
ADD HL,DE
EX DE,HL
;DE указывает на первый байт текстуры.
LD B,24
LD HL,#4880
M2 PUSH DE
PUSH BC
LD B,4
M1 LD A,(DE)
PUSH BC
PUSH DE
PUSH HL
LD D,H
LD E,L
LD (HL),A
INC DE
LD BC,#1F
LDIR
POP HL
POP DE
POP BC
CALL DOWN_HL
INC DE
DJNZ M1
POP BC
POP DE
DJNZ M2
RET
DOWN_HL INC H
LD A,H
AND 7
RET NZ
LD A,L
ADD A,#20
LD L,A
RET C
LD A,H
SUB 8
LD H,A
RET
TEXTURES DB %00000000
DB %00000000
DB %00000000
DB %00000000
DB %00000000
DB %01000100
DB %00000000
DB %00000000
DB %00000000
DB %01000100
DB %00000000
DB %00010001
DB %00000000
DB %01010101
DB %00000000
DB %00010001
DB %00000000
DB %01010101
DB %00000000
DB %01010101
DB %00000000
DB %01010101
DB %00100010
DB %01010101
DB %10001000
DB %01010101
DB %00100010
DB %01010101
DB %10101010
DB %01010101
DB %00100010
DB %01010101
DB %10101010
DB %01010101
DB %10101010
DB %01010101
DB %10101010
DB %01110111
DB %10101010
DB %01010101
DB %10101010
DB %01110111
DB %10101010
DB %11011101
DB %10101010
DB %01110111
DB %10101010
DB %11111111
DB %10101010
DB %11111111
DB %10101010
DB %11111111
DB %10101010
DB %11111111
DB %11101110
DB %11111111
DB %10111011
DB %11111111
DB %11101110
DB %11111111
DB %11111111
DB %11111111
DB %11101110
DB %11111111
DB %11111111
DB %11111111
DB %11111111
DB %11111111
Чтобы было удобнее сравнивать яркости половин экрана, когда на одной половине яркость равномерная, а на другой текстура, я рассматривал изображение через полупрозрачную полиэтиленовую плёнку (для этого годится обычный пакет).
С помощью вышеприведённой процедуры были получены следующие соотношения:
b1 = 9/16 b0 + 7/16 b2, b2 = 10/16 b1 + 6/16 b3, b3 = 8/16 b2 + 8/16 b4, b4 = 13/16 b3 + 3/16 b5, b5 = 9/16 b4 + 7/16 b6, b6 = 10/16 b5 + 6/16 b7, |
a1 = 3/16 b0 + 13/16 b1, a2 = 9/16 b1 + 7/16 b2, a3 = 9/16 b2 + 7/16 b3, a4 = b3, a5 = 9/16 b4 + 7/16 b5, a6 = 11/16 b5 + 5/16 b6, a7 = 11/16 b6 + 5/16 b7. |
Затем я написал программу, вычисляющую на основе этих данных искомые значения a0a7 и b0b7:
10 DIM k(6): DIM a(7): DIM b(7)
20 LET k(1)=9/16: LET k(2)=10/16: LET k(3)=8/16: LET k(4)=
13/16: LET k(5)=9/16: LET k(6)=10/16
30 REM CALCULATE b(1)-b(7)
40 LET b(1)=1
50 LET b(2)=1/(1-k(1))
60 FOR i=3 TO 7
70 LET b(i)=(b(i-1)-k(i-1)*b(i-2))/(1-k(i-1))
80 NEXT i
90 LET n=255/b(7)
100 FOR i=1 TO 7
110 LET b(i)=b(i)*n
120 NEXT i
130 REM CALCULATE a(1)-a(7)
140 LET a(1)=13/16*b(1)
150 LET a(2)=9/16*b(1)+7/16*b(2)
160 LET a(3)=9/16*b(2)+7/16*b(3)
170 LET a(4)=b(3)
180 LET a(5)=9/16*b(4)+7/16*b(5)
190 LET a(6)=11/16*b(5)+5/16*b(6)
200 LET a(7)=11/16*b(6)+5/16*b(7)
210 REM PRINT RESULT
220 PRINT "a0=0",0
230 FOR i=1 TO 7
240 PRINT "a";i;"=";a(i), INT (a(i)*256+0.5)
250 NEXT i
260 PRINT
270 PRINT "b0=0",0
280 FOR i=1 TO 7
290 PRINT "b";i;"=";b(i), INT (b(i)*256+0.5)
300 NEXT i
Результаты работы программы: в левом столбце вычисленные
значения яркостей, в правом они же, но в
а0 = 0 0 а1 = 4,344111 1112 а2 = 8,3540597 2139 а3 = 17,233232 4412 а4 = 23,677792 6062 а5 = 56,855343 14555 а6 = 104,72922 26811 а7 = 181,85936 46556 b0 = 0 0 b1 = 5,3465982 1369 b2 = 12,220796 3129 b3 = 23,677792 6062 b4 = 35,134788 8995 b5 = 84,781772 21704 b6 = 148,61361 38045 b7 = 255 65280 |
А вот как это выглядит на графике:
![]() |
Как видите, это отличается от первоначальных предположений (рис. 18). Значения располагаются неравномерно: чем меньше
яркость, тем ближе они друг к другу. Чем это можно объяснить? Очевидно, при
преобразовании цветного изображения в