mirror of
https://github.com/KrisKennaway/ii-pix.git
synced 2025-02-20 17:29:03 +00:00
Reimplement NTSC conversion to closely match openemulator output. I
can't figure out why contrast=2 is needed (openemulator uses a default value of 1, so there must be a factor of 2x somewhere), or where the slight hue rotation comes from - perhaps this is somehow introduced by the more complex band-pass filtering that openemulator does? I needed to also account for the DHGR timing difference that introduces a phase offset of 1 pixel between the memory values and displayed pixel timings. Fix a last-minute bug with palette precomputation.
This commit is contained in:
parent
e1dab91783
commit
e0b732cdaa
@ -17,15 +17,19 @@ def main():
|
||||
# For each sequence of 8 pixels, compute the RGB colour of the right-most
|
||||
# pixel, using NTSC emulation.
|
||||
for bits in range(256):
|
||||
bits8 = np.empty((8,), dtype=np.bool)
|
||||
for i in range(8):
|
||||
bitmap[0, i] = bits & (1 << i)
|
||||
bits8[i] = bits & (1 << i)
|
||||
# Double Hi-Res has a timing shift that rotates the displayed bits one
|
||||
# position with respect to NTSC phase.
|
||||
bitmap[0, :] = bits8[[3, 0, 1, 2, 7, 4, 5, 6]]
|
||||
|
||||
ntsc = s.bitmap_to_ntsc(bitmap)
|
||||
last_colour = ntsc[0, -1, :]
|
||||
colours[bits] = last_colour
|
||||
unique.add(tuple(last_colour))
|
||||
print("%d: np.array((%d, %d, %d))," % (
|
||||
bits, last_colour[0], last_colour[1], last_colour[2]))
|
||||
bits, last_colour[0], last_colour[1], last_colour[2]))
|
||||
print("}")
|
||||
print("# %d unique colours" % len(unique))
|
||||
|
||||
@ -34,6 +38,7 @@ def main():
|
||||
for x, hsv in enumerate(sorted([tuple(colour.RGB_to_HSV(c / 256)) for c in
|
||||
colours.values()])):
|
||||
im[0:128, x * 16: (x + 1) * 16, :] = colour.HSV_to_RGB(hsv) * 256
|
||||
|
||||
Image.fromarray(im).show()
|
||||
|
||||
|
||||
|
506
palette.py
506
palette.py
@ -121,263 +121,263 @@ class NTSCPalette(Palette):
|
||||
# Computed using ntsc_colours.py
|
||||
SRGB = {
|
||||
0: np.array((0, 0, 0)),
|
||||
1: np.array((0, 0, 62)),
|
||||
2: np.array((0, 18, 0)),
|
||||
3: np.array((0, 3, 28)),
|
||||
4: np.array((44, 14, 0)),
|
||||
1: np.array((0, 0, 115)),
|
||||
2: np.array((0, 37, 0)),
|
||||
3: np.array((0, 23, 88)),
|
||||
4: np.array((14, 14, 0)),
|
||||
5: np.array((0, 0, 0)),
|
||||
6: np.array((0, 32, 0)),
|
||||
7: np.array((0, 18, 0)),
|
||||
8: np.array((67, 0, 34)),
|
||||
9: np.array((22, 0, 96)),
|
||||
6: np.array((0, 52, 0)),
|
||||
7: np.array((0, 37, 0)),
|
||||
8: np.array((64, 0, 26)),
|
||||
9: np.array((49, 0, 141)),
|
||||
10: np.array((0, 0, 0)),
|
||||
11: np.array((0, 0, 62)),
|
||||
12: np.array((112, 0, 0)),
|
||||
13: np.array((67, 0, 34)),
|
||||
14: np.array((44, 14, 0)),
|
||||
11: np.array((0, 0, 115)),
|
||||
12: np.array((79, 0, 0)),
|
||||
13: np.array((64, 0, 26)),
|
||||
14: np.array((14, 14, 0)),
|
||||
15: np.array((0, 0, 0)),
|
||||
16: np.array((24, 54, 131)),
|
||||
17: np.array((0, 40, 193)),
|
||||
18: np.array((0, 73, 97)),
|
||||
19: np.array((0, 58, 159)),
|
||||
20: np.array((69, 69, 69)),
|
||||
21: np.array((24, 54, 131)),
|
||||
22: np.array((1, 87, 35)),
|
||||
23: np.array((0, 73, 97)),
|
||||
24: np.array((91, 36, 165)),
|
||||
25: np.array((47, 22, 227)),
|
||||
26: np.array((24, 54, 131)),
|
||||
27: np.array((0, 40, 193)),
|
||||
28: np.array((136, 50, 103)),
|
||||
29: np.array((91, 36, 165)),
|
||||
30: np.array((69, 69, 69)),
|
||||
31: np.array((24, 54, 131)),
|
||||
32: np.array((1, 87, 35)),
|
||||
33: np.array((0, 73, 97)),
|
||||
34: np.array((0, 105, 1)),
|
||||
35: np.array((0, 91, 63)),
|
||||
36: np.array((46, 101, 0)),
|
||||
37: np.array((1, 87, 35)),
|
||||
38: np.array((0, 120, 0)),
|
||||
39: np.array((0, 105, 1)),
|
||||
40: np.array((69, 69, 69)),
|
||||
41: np.array((24, 54, 131)),
|
||||
42: np.array((1, 87, 35)),
|
||||
43: np.array((0, 73, 97)),
|
||||
44: np.array((113, 83, 7)),
|
||||
45: np.array((69, 69, 69)),
|
||||
46: np.array((46, 101, 0)),
|
||||
47: np.array((1, 87, 35)),
|
||||
48: np.array((26, 142, 166)),
|
||||
49: np.array((0, 127, 228)),
|
||||
50: np.array((0, 160, 132)),
|
||||
51: np.array((0, 146, 194)),
|
||||
52: np.array((70, 156, 104)),
|
||||
53: np.array((26, 142, 166)),
|
||||
54: np.array((3, 174, 70)),
|
||||
55: np.array((0, 160, 132)),
|
||||
56: np.array((93, 124, 200)),
|
||||
57: np.array((48, 109, 255)),
|
||||
58: np.array((26, 142, 166)),
|
||||
59: np.array((0, 127, 228)),
|
||||
60: np.array((138, 138, 138)),
|
||||
61: np.array((93, 124, 200)),
|
||||
62: np.array((70, 156, 104)),
|
||||
63: np.array((26, 142, 166)),
|
||||
64: np.array((113, 83, 7)),
|
||||
65: np.array((69, 69, 69)),
|
||||
66: np.array((46, 101, 0)),
|
||||
67: np.array((1, 87, 35)),
|
||||
68: np.array((158, 97, 0)),
|
||||
69: np.array((113, 83, 7)),
|
||||
70: np.array((91, 116, 0)),
|
||||
71: np.array((46, 101, 0)),
|
||||
72: np.array((181, 65, 41)),
|
||||
73: np.array((136, 50, 103)),
|
||||
74: np.array((113, 83, 7)),
|
||||
75: np.array((69, 69, 69)),
|
||||
76: np.array((226, 79, 0)),
|
||||
77: np.array((181, 65, 41)),
|
||||
78: np.array((158, 97, 0)),
|
||||
79: np.array((113, 83, 7)),
|
||||
80: np.array((138, 138, 138)),
|
||||
81: np.array((93, 124, 200)),
|
||||
82: np.array((70, 156, 104)),
|
||||
83: np.array((26, 142, 166)),
|
||||
84: np.array((183, 152, 76)),
|
||||
85: np.array((138, 138, 138)),
|
||||
86: np.array((115, 171, 42)),
|
||||
87: np.array((70, 156, 104)),
|
||||
88: np.array((205, 120, 172)),
|
||||
89: np.array((161, 105, 234)),
|
||||
90: np.array((138, 138, 138)),
|
||||
91: np.array((93, 124, 200)),
|
||||
92: np.array((250, 134, 110)),
|
||||
93: np.array((205, 120, 172)),
|
||||
94: np.array((183, 152, 76)),
|
||||
95: np.array((138, 138, 138)),
|
||||
96: np.array((115, 171, 42)),
|
||||
97: np.array((70, 156, 104)),
|
||||
98: np.array((48, 189, 8)),
|
||||
99: np.array((3, 174, 70)),
|
||||
100: np.array((160, 185, 0)),
|
||||
101: np.array((115, 171, 42)),
|
||||
102: np.array((93, 203, 0)),
|
||||
103: np.array((48, 189, 8)),
|
||||
104: np.array((183, 152, 76)),
|
||||
105: np.array((138, 138, 138)),
|
||||
106: np.array((115, 171, 42)),
|
||||
107: np.array((70, 156, 104)),
|
||||
108: np.array((227, 167, 14)),
|
||||
109: np.array((183, 152, 76)),
|
||||
110: np.array((160, 185, 0)),
|
||||
111: np.array((115, 171, 42)),
|
||||
112: np.array((140, 225, 173)),
|
||||
113: np.array((95, 211, 235)),
|
||||
114: np.array((72, 244, 139)),
|
||||
115: np.array((28, 229, 201)),
|
||||
116: np.array((184, 240, 111)),
|
||||
117: np.array((140, 225, 173)),
|
||||
118: np.array((117, 255, 77)),
|
||||
119: np.array((72, 244, 139)),
|
||||
120: np.array((207, 207, 207)),
|
||||
121: np.array((162, 193, 255)),
|
||||
122: np.array((140, 225, 173)),
|
||||
123: np.array((95, 211, 235)),
|
||||
124: np.array((252, 221, 145)),
|
||||
125: np.array((207, 207, 207)),
|
||||
126: np.array((184, 240, 111)),
|
||||
127: np.array((140, 225, 173)),
|
||||
128: np.array((136, 50, 103)),
|
||||
129: np.array((91, 36, 165)),
|
||||
130: np.array((69, 69, 69)),
|
||||
131: np.array((24, 54, 131)),
|
||||
132: np.array((181, 65, 41)),
|
||||
133: np.array((136, 50, 103)),
|
||||
134: np.array((113, 83, 7)),
|
||||
135: np.array((69, 69, 69)),
|
||||
136: np.array((203, 32, 137)),
|
||||
137: np.array((159, 18, 199)),
|
||||
138: np.array((136, 50, 103)),
|
||||
139: np.array((91, 36, 165)),
|
||||
140: np.array((248, 47, 75)),
|
||||
141: np.array((203, 32, 137)),
|
||||
142: np.array((181, 65, 41)),
|
||||
143: np.array((136, 50, 103)),
|
||||
144: np.array((161, 105, 234)),
|
||||
145: np.array((116, 91, 255)),
|
||||
146: np.array((93, 124, 200)),
|
||||
147: np.array((48, 109, 255)),
|
||||
148: np.array((205, 120, 172)),
|
||||
149: np.array((161, 105, 234)),
|
||||
150: np.array((138, 138, 138)),
|
||||
151: np.array((93, 124, 200)),
|
||||
152: np.array((228, 87, 255)),
|
||||
153: np.array((183, 73, 255)),
|
||||
154: np.array((161, 105, 234)),
|
||||
155: np.array((116, 91, 255)),
|
||||
156: np.array((255, 101, 206)),
|
||||
157: np.array((228, 87, 255)),
|
||||
158: np.array((205, 120, 172)),
|
||||
159: np.array((161, 105, 234)),
|
||||
160: np.array((138, 138, 138)),
|
||||
161: np.array((93, 124, 200)),
|
||||
162: np.array((70, 156, 104)),
|
||||
163: np.array((26, 142, 166)),
|
||||
164: np.array((183, 152, 76)),
|
||||
165: np.array((138, 138, 138)),
|
||||
166: np.array((115, 171, 42)),
|
||||
167: np.array((70, 156, 104)),
|
||||
168: np.array((205, 120, 172)),
|
||||
169: np.array((161, 105, 234)),
|
||||
170: np.array((138, 138, 138)),
|
||||
171: np.array((93, 124, 200)),
|
||||
172: np.array((250, 134, 110)),
|
||||
173: np.array((205, 120, 172)),
|
||||
174: np.array((183, 152, 76)),
|
||||
175: np.array((138, 138, 138)),
|
||||
176: np.array((162, 193, 255)),
|
||||
177: np.array((118, 178, 255)),
|
||||
178: np.array((95, 211, 235)),
|
||||
179: np.array((50, 197, 255)),
|
||||
180: np.array((207, 207, 207)),
|
||||
181: np.array((162, 193, 255)),
|
||||
182: np.array((140, 225, 173)),
|
||||
183: np.array((95, 211, 235)),
|
||||
184: np.array((230, 174, 255)),
|
||||
185: np.array((185, 160, 255)),
|
||||
186: np.array((162, 193, 255)),
|
||||
187: np.array((118, 178, 255)),
|
||||
188: np.array((255, 189, 241)),
|
||||
189: np.array((230, 174, 255)),
|
||||
190: np.array((207, 207, 207)),
|
||||
191: np.array((162, 193, 255)),
|
||||
192: np.array((250, 134, 110)),
|
||||
193: np.array((205, 120, 172)),
|
||||
194: np.array((183, 152, 76)),
|
||||
195: np.array((138, 138, 138)),
|
||||
196: np.array((255, 148, 48)),
|
||||
197: np.array((250, 134, 110)),
|
||||
198: np.array((227, 167, 14)),
|
||||
199: np.array((183, 152, 76)),
|
||||
200: np.array((255, 116, 144)),
|
||||
201: np.array((255, 101, 206)),
|
||||
202: np.array((250, 134, 110)),
|
||||
203: np.array((205, 120, 172)),
|
||||
204: np.array((255, 130, 82)),
|
||||
205: np.array((255, 116, 144)),
|
||||
206: np.array((255, 148, 48)),
|
||||
207: np.array((250, 134, 110)),
|
||||
208: np.array((255, 189, 241)),
|
||||
209: np.array((230, 174, 255)),
|
||||
210: np.array((207, 207, 207)),
|
||||
211: np.array((162, 193, 255)),
|
||||
212: np.array((255, 203, 179)),
|
||||
213: np.array((255, 189, 241)),
|
||||
214: np.array((252, 221, 145)),
|
||||
215: np.array((207, 207, 207)),
|
||||
216: np.array((255, 171, 255)),
|
||||
217: np.array((255, 156, 255)),
|
||||
218: np.array((255, 189, 241)),
|
||||
219: np.array((230, 174, 255)),
|
||||
220: np.array((255, 185, 213)),
|
||||
221: np.array((255, 171, 255)),
|
||||
222: np.array((255, 203, 179)),
|
||||
223: np.array((255, 189, 241)),
|
||||
224: np.array((252, 221, 145)),
|
||||
225: np.array((207, 207, 207)),
|
||||
226: np.array((184, 240, 111)),
|
||||
227: np.array((140, 225, 173)),
|
||||
228: np.array((255, 236, 83)),
|
||||
229: np.array((252, 221, 145)),
|
||||
230: np.array((229, 254, 49)),
|
||||
231: np.array((184, 240, 111)),
|
||||
232: np.array((255, 203, 179)),
|
||||
233: np.array((255, 189, 241)),
|
||||
234: np.array((252, 221, 145)),
|
||||
235: np.array((207, 207, 207)),
|
||||
236: np.array((255, 218, 117)),
|
||||
237: np.array((255, 203, 179)),
|
||||
238: np.array((255, 236, 83)),
|
||||
239: np.array((252, 221, 145)),
|
||||
240: np.array((255, 255, 255)),
|
||||
241: np.array((232, 255, 255)),
|
||||
242: np.array((209, 255, 242)),
|
||||
243: np.array((164, 255, 255)),
|
||||
244: np.array((255, 255, 214)),
|
||||
245: np.array((255, 255, 255)),
|
||||
246: np.array((254, 255, 180)),
|
||||
247: np.array((209, 255, 242)),
|
||||
248: np.array((255, 255, 255)),
|
||||
249: np.array((255, 244, 255)),
|
||||
250: np.array((255, 255, 255)),
|
||||
251: np.array((232, 255, 255)),
|
||||
252: np.array((255, 255, 248)),
|
||||
253: np.array((255, 255, 255)),
|
||||
254: np.array((255, 255, 214)),
|
||||
255: np.array((255, 255, 255)),
|
||||
16: np.array((49, 48, 178)),
|
||||
17: np.array((34, 34, 255)),
|
||||
18: np.array((0, 86, 152)),
|
||||
19: np.array((0, 71, 255)),
|
||||
20: np.array((63, 63, 63)),
|
||||
21: np.array((49, 48, 178)),
|
||||
22: np.array((0, 101, 37)),
|
||||
23: np.array((0, 86, 152)),
|
||||
24: np.array((113, 10, 204)),
|
||||
25: np.array((98, 0, 255)),
|
||||
26: np.array((49, 48, 178)),
|
||||
27: np.array((34, 34, 255)),
|
||||
28: np.array((128, 25, 89)),
|
||||
29: np.array((113, 10, 204)),
|
||||
30: np.array((63, 63, 63)),
|
||||
31: np.array((49, 48, 178)),
|
||||
32: np.array((0, 101, 37)),
|
||||
33: np.array((0, 86, 152)),
|
||||
34: np.array((0, 139, 11)),
|
||||
35: np.array((0, 124, 126)),
|
||||
36: np.array((13, 116, 0)),
|
||||
37: np.array((0, 101, 37)),
|
||||
38: np.array((0, 154, 0)),
|
||||
39: np.array((0, 139, 11)),
|
||||
40: np.array((63, 63, 63)),
|
||||
41: np.array((49, 48, 178)),
|
||||
42: np.array((0, 101, 37)),
|
||||
43: np.array((0, 86, 152)),
|
||||
44: np.array((78, 78, 0)),
|
||||
45: np.array((63, 63, 63)),
|
||||
46: np.array((13, 116, 0)),
|
||||
47: np.array((0, 101, 37)),
|
||||
48: np.array((48, 150, 216)),
|
||||
49: np.array((33, 135, 255)),
|
||||
50: np.array((0, 188, 190)),
|
||||
51: np.array((0, 173, 255)),
|
||||
52: np.array((62, 165, 101)),
|
||||
53: np.array((48, 150, 216)),
|
||||
54: np.array((0, 203, 75)),
|
||||
55: np.array((0, 188, 190)),
|
||||
56: np.array((112, 112, 242)),
|
||||
57: np.array((98, 97, 255)),
|
||||
58: np.array((48, 150, 216)),
|
||||
59: np.array((33, 135, 255)),
|
||||
60: np.array((127, 127, 127)),
|
||||
61: np.array((112, 112, 242)),
|
||||
62: np.array((62, 165, 101)),
|
||||
63: np.array((48, 150, 216)),
|
||||
64: np.array((78, 78, 0)),
|
||||
65: np.array((63, 63, 63)),
|
||||
66: np.array((13, 116, 0)),
|
||||
67: np.array((0, 101, 37)),
|
||||
68: np.array((93, 93, 0)),
|
||||
69: np.array((78, 78, 0)),
|
||||
70: np.array((28, 131, 0)),
|
||||
71: np.array((13, 116, 0)),
|
||||
72: np.array((142, 40, 0)),
|
||||
73: np.array((128, 25, 89)),
|
||||
74: np.array((78, 78, 0)),
|
||||
75: np.array((63, 63, 63)),
|
||||
76: np.array((157, 55, 0)),
|
||||
77: np.array((142, 40, 0)),
|
||||
78: np.array((93, 93, 0)),
|
||||
79: np.array((78, 78, 0)),
|
||||
80: np.array((127, 127, 127)),
|
||||
81: np.array((112, 112, 242)),
|
||||
82: np.array((62, 165, 101)),
|
||||
83: np.array((48, 150, 216)),
|
||||
84: np.array((142, 142, 12)),
|
||||
85: np.array((127, 127, 127)),
|
||||
86: np.array((77, 180, 0)),
|
||||
87: np.array((62, 165, 101)),
|
||||
88: np.array((192, 89, 153)),
|
||||
89: np.array((177, 74, 255)),
|
||||
90: np.array((127, 127, 127)),
|
||||
91: np.array((112, 112, 242)),
|
||||
92: np.array((206, 104, 38)),
|
||||
93: np.array((192, 89, 153)),
|
||||
94: np.array((142, 142, 12)),
|
||||
95: np.array((127, 127, 127)),
|
||||
96: np.array((77, 180, 0)),
|
||||
97: np.array((62, 165, 101)),
|
||||
98: np.array((13, 218, 0)),
|
||||
99: np.array((0, 203, 75)),
|
||||
100: np.array((92, 195, 0)),
|
||||
101: np.array((77, 180, 0)),
|
||||
102: np.array((27, 233, 0)),
|
||||
103: np.array((13, 218, 0)),
|
||||
104: np.array((142, 142, 12)),
|
||||
105: np.array((127, 127, 127)),
|
||||
106: np.array((77, 180, 0)),
|
||||
107: np.array((62, 165, 101)),
|
||||
108: np.array((156, 157, 0)),
|
||||
109: np.array((142, 142, 12)),
|
||||
110: np.array((92, 195, 0)),
|
||||
111: np.array((77, 180, 0)),
|
||||
112: np.array((126, 229, 165)),
|
||||
113: np.array((112, 214, 255)),
|
||||
114: np.array((62, 255, 138)),
|
||||
115: np.array((47, 252, 253)),
|
||||
116: np.array((141, 244, 50)),
|
||||
117: np.array((126, 229, 165)),
|
||||
118: np.array((76, 255, 23)),
|
||||
119: np.array((62, 255, 138)),
|
||||
120: np.array((191, 191, 191)),
|
||||
121: np.array((176, 176, 255)),
|
||||
122: np.array((126, 229, 165)),
|
||||
123: np.array((112, 214, 255)),
|
||||
124: np.array((205, 206, 76)),
|
||||
125: np.array((191, 191, 191)),
|
||||
126: np.array((141, 244, 50)),
|
||||
127: np.array((126, 229, 165)),
|
||||
128: np.array((128, 25, 89)),
|
||||
129: np.array((113, 10, 204)),
|
||||
130: np.array((63, 63, 63)),
|
||||
131: np.array((49, 48, 178)),
|
||||
132: np.array((142, 40, 0)),
|
||||
133: np.array((128, 25, 89)),
|
||||
134: np.array((78, 78, 0)),
|
||||
135: np.array((63, 63, 63)),
|
||||
136: np.array((192, 0, 116)),
|
||||
137: np.array((178, 0, 231)),
|
||||
138: np.array((128, 25, 89)),
|
||||
139: np.array((113, 10, 204)),
|
||||
140: np.array((207, 2, 1)),
|
||||
141: np.array((192, 0, 116)),
|
||||
142: np.array((142, 40, 0)),
|
||||
143: np.array((128, 25, 89)),
|
||||
144: np.array((177, 74, 255)),
|
||||
145: np.array((162, 59, 255)),
|
||||
146: np.array((112, 112, 242)),
|
||||
147: np.array((98, 97, 255)),
|
||||
148: np.array((192, 89, 153)),
|
||||
149: np.array((177, 74, 255)),
|
||||
150: np.array((127, 127, 127)),
|
||||
151: np.array((112, 112, 242)),
|
||||
152: np.array((241, 36, 255)),
|
||||
153: np.array((227, 21, 255)),
|
||||
154: np.array((177, 74, 255)),
|
||||
155: np.array((162, 59, 255)),
|
||||
156: np.array((255, 51, 179)),
|
||||
157: np.array((241, 36, 255)),
|
||||
158: np.array((192, 89, 153)),
|
||||
159: np.array((177, 74, 255)),
|
||||
160: np.array((127, 127, 127)),
|
||||
161: np.array((112, 112, 242)),
|
||||
162: np.array((62, 165, 101)),
|
||||
163: np.array((48, 150, 216)),
|
||||
164: np.array((142, 142, 12)),
|
||||
165: np.array((127, 127, 127)),
|
||||
166: np.array((77, 180, 0)),
|
||||
167: np.array((62, 165, 101)),
|
||||
168: np.array((192, 89, 153)),
|
||||
169: np.array((177, 74, 255)),
|
||||
170: np.array((127, 127, 127)),
|
||||
171: np.array((112, 112, 242)),
|
||||
172: np.array((206, 104, 38)),
|
||||
173: np.array((192, 89, 153)),
|
||||
174: np.array((142, 142, 12)),
|
||||
175: np.array((127, 127, 127)),
|
||||
176: np.array((176, 176, 255)),
|
||||
177: np.array((161, 161, 255)),
|
||||
178: np.array((112, 214, 255)),
|
||||
179: np.array((97, 199, 255)),
|
||||
180: np.array((191, 191, 191)),
|
||||
181: np.array((176, 176, 255)),
|
||||
182: np.array((126, 229, 165)),
|
||||
183: np.array((112, 214, 255)),
|
||||
184: np.array((241, 138, 255)),
|
||||
185: np.array((226, 123, 255)),
|
||||
186: np.array((176, 176, 255)),
|
||||
187: np.array((161, 161, 255)),
|
||||
188: np.array((255, 153, 217)),
|
||||
189: np.array((241, 138, 255)),
|
||||
190: np.array((191, 191, 191)),
|
||||
191: np.array((176, 176, 255)),
|
||||
192: np.array((206, 104, 38)),
|
||||
193: np.array((192, 89, 153)),
|
||||
194: np.array((142, 142, 12)),
|
||||
195: np.array((127, 127, 127)),
|
||||
196: np.array((221, 119, 0)),
|
||||
197: np.array((206, 104, 38)),
|
||||
198: np.array((156, 157, 0)),
|
||||
199: np.array((142, 142, 12)),
|
||||
200: np.array((255, 66, 64)),
|
||||
201: np.array((255, 51, 179)),
|
||||
202: np.array((206, 104, 38)),
|
||||
203: np.array((192, 89, 153)),
|
||||
204: np.array((255, 81, 0)),
|
||||
205: np.array((255, 66, 64)),
|
||||
206: np.array((221, 119, 0)),
|
||||
207: np.array((206, 104, 38)),
|
||||
208: np.array((255, 153, 217)),
|
||||
209: np.array((241, 138, 255)),
|
||||
210: np.array((191, 191, 191)),
|
||||
211: np.array((176, 176, 255)),
|
||||
212: np.array((255, 168, 102)),
|
||||
213: np.array((255, 153, 217)),
|
||||
214: np.array((205, 206, 76)),
|
||||
215: np.array((191, 191, 191)),
|
||||
216: np.array((255, 115, 243)),
|
||||
217: np.array((255, 100, 255)),
|
||||
218: np.array((255, 153, 217)),
|
||||
219: np.array((241, 138, 255)),
|
||||
220: np.array((255, 130, 128)),
|
||||
221: np.array((255, 115, 243)),
|
||||
222: np.array((255, 168, 102)),
|
||||
223: np.array((255, 153, 217)),
|
||||
224: np.array((205, 206, 76)),
|
||||
225: np.array((191, 191, 191)),
|
||||
226: np.array((141, 244, 50)),
|
||||
227: np.array((126, 229, 165)),
|
||||
228: np.array((220, 220, 0)),
|
||||
229: np.array((205, 206, 76)),
|
||||
230: np.array((156, 255, 0)),
|
||||
231: np.array((141, 244, 50)),
|
||||
232: np.array((255, 168, 102)),
|
||||
233: np.array((255, 153, 217)),
|
||||
234: np.array((205, 206, 76)),
|
||||
235: np.array((191, 191, 191)),
|
||||
236: np.array((255, 183, 0)),
|
||||
237: np.array((255, 168, 102)),
|
||||
238: np.array((220, 220, 0)),
|
||||
239: np.array((205, 206, 76)),
|
||||
240: np.array((254, 255, 255)),
|
||||
241: np.array((240, 240, 255)),
|
||||
242: np.array((190, 255, 228)),
|
||||
243: np.array((175, 255, 255)),
|
||||
244: np.array((255, 255, 139)),
|
||||
245: np.array((254, 255, 255)),
|
||||
246: np.array((205, 255, 113)),
|
||||
247: np.array((190, 255, 228)),
|
||||
248: np.array((255, 217, 255)),
|
||||
249: np.array((255, 202, 255)),
|
||||
250: np.array((254, 255, 255)),
|
||||
251: np.array((240, 240, 255)),
|
||||
252: np.array((255, 231, 166)),
|
||||
253: np.array((255, 217, 255)),
|
||||
254: np.array((255, 255, 139)),
|
||||
255: np.array((254, 255, 255)),
|
||||
}
|
||||
# 84 unique colours
|
||||
# 85 unique colours
|
||||
|
||||
|
||||
PALETTES = {
|
||||
|
@ -34,7 +34,7 @@ def all_lab_colours():
|
||||
|
||||
|
||||
def nearest_colours(palette, all_lab, diffs):
|
||||
palette_size = len(palette)
|
||||
palette_size = len(palette.RGB)
|
||||
palette_labs = np.empty((palette_size, 3), dtype=np.float)
|
||||
for i, palette_rgb in palette.RGB.items():
|
||||
palette_labs[i, :] = rgb_to_lab(palette_rgb)
|
||||
@ -78,7 +78,8 @@ def main():
|
||||
except FileExistsError:
|
||||
pass
|
||||
out = np.memmap(filename=palette.DISTANCES_PATH, mode="w+",
|
||||
dtype=np.uint8, shape=(RGB_LEVELS ** 3, len(palette)))
|
||||
dtype=np.uint8, shape=(RGB_LEVELS ** 3,
|
||||
len(palette.RGB)))
|
||||
nearest_colours(palette, all_lab, out)
|
||||
|
||||
|
||||
|
91
screen.py
91
screen.py
@ -3,6 +3,7 @@
|
||||
import numpy as np
|
||||
import palette as palette_py
|
||||
|
||||
|
||||
# TODO: rename "4bit" variable naming now that we also have palettes with 8 bit
|
||||
# depth.
|
||||
|
||||
@ -83,77 +84,71 @@ class Screen:
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def _sin(pos, phase0=4):
|
||||
def _sin(pos, phase0=0):
|
||||
x = pos % 12 + phase0
|
||||
return 8 * np.sin(x * 2 * np.pi / 12)
|
||||
return np.sin(x * 2 * np.pi / 12)
|
||||
|
||||
@staticmethod
|
||||
def _cos(pos, phase0=4):
|
||||
def _cos(pos, phase0=0):
|
||||
x = pos % 12 + phase0
|
||||
return 8 * np.cos(x * 2 * np.pi / 12)
|
||||
return np.cos(x * 2 * np.pi / 12)
|
||||
|
||||
def _read(self, line, pos):
|
||||
if pos < 0:
|
||||
return 0
|
||||
|
||||
# Sather says black level is 0.36V and white level 1.1V, but this
|
||||
# doesn't seem to be right (they correspond to values -29 and +33)
|
||||
# which means that 0101 grey has Y value ~0, i.e. is black. These are
|
||||
# only mentioned as labels on figure 8.2 though.
|
||||
#
|
||||
# _The Apple II Circuit description_ by W. Gayler gives black=0.5V
|
||||
# and white=2.0V which is much more plausible.
|
||||
#
|
||||
# Conversion is given by floor((voltage-0.518)*1000/12)-15
|
||||
return 108 if line[pos] else 0 # -16
|
||||
return 1 if line[pos] else 0
|
||||
|
||||
def bitmap_to_ntsc(self, bitmap: np.ndarray) -> np.ndarray:
|
||||
"""
|
||||
See http://forums.nesdev.com/viewtopic.php?p=172329#p172329
|
||||
"""
|
||||
y_width = 12
|
||||
i_width = 24
|
||||
q_width = 24
|
||||
u_width = 24
|
||||
v_width = 24
|
||||
|
||||
contrast = 167941
|
||||
saturation = 144044
|
||||
contrast = 1
|
||||
# TODO: where does this come from? OpenEmulator looks like it should
|
||||
# use a value of 1.0 by default.
|
||||
saturation = 2
|
||||
# Fudge factor to make colours line up with OpenEmulator
|
||||
# TODO: where does this come from - is it due to the band-pass
|
||||
# filtering they do?
|
||||
hue = -0.3
|
||||
|
||||
yr = contrast / y_width
|
||||
ir = contrast * 1.994681e-6 * saturation / i_width
|
||||
qr = contrast * 9.915742e-7 * saturation / q_width
|
||||
|
||||
yg = contrast / y_width
|
||||
ig = contrast * 9.151351e-8 * saturation / i_width
|
||||
qg = contrast * -6.334805e-7 * saturation / q_width
|
||||
|
||||
yb = contrast / y_width
|
||||
ib = contrast * -1.012984e-6 * saturation / i_width
|
||||
qb = contrast * 1.667217e-6 * saturation / q_width
|
||||
# Apply effect of saturation
|
||||
yuv_to_rgb = np.array(
|
||||
((1, 0, 0), (0, saturation, 0), (0, 0, saturation)), dtype=np.float)
|
||||
# Apply hue phase rotation
|
||||
yuv_to_rgb = np.matmul(np.array(
|
||||
((1, 0, 0), (0, np.cos(hue), np.sin(hue)), (0, -np.sin(hue),
|
||||
np.cos(hue)))),
|
||||
yuv_to_rgb)
|
||||
# Y'UV to R'G'B' conversion
|
||||
yuv_to_rgb = np.matmul(np.array(
|
||||
((1, 0, 1.13983), (1, -0.39465, -.58060), (1, 2.03211, 0))),
|
||||
yuv_to_rgb)
|
||||
# Apply effect of contrast
|
||||
yuv_to_rgb *= contrast
|
||||
|
||||
out_rgb = np.empty((bitmap.shape[0], bitmap.shape[1] * 3, 3),
|
||||
dtype=np.uint8)
|
||||
for y in range(bitmap.shape[0]):
|
||||
ysum = 0
|
||||
isum = 0
|
||||
qsum = 0
|
||||
usum = 0
|
||||
vsum = 0
|
||||
line = np.repeat(bitmap[y], 3)
|
||||
|
||||
# color = y // (192//16)
|
||||
# line = np.repeat(np.tile((color & 1, color & 2, color & 4,
|
||||
# color & 8), 140), 3)
|
||||
for x in range(bitmap.shape[1] * 3):
|
||||
ysum += self._read(line, x) - self._read(line, x - y_width)
|
||||
isum += self._read(line, x) * self._cos(x) - self._read(
|
||||
line, x - i_width) * self._cos((x - i_width))
|
||||
qsum += self._read(line, x) * self._sin(x) - self._read(
|
||||
line, x - q_width) * self._sin((x - q_width))
|
||||
|
||||
r = min(255, max(0, ysum * yr + isum * ir + qsum * qr) /
|
||||
65536)
|
||||
g = min(255,
|
||||
max(0, (ysum * yg + isum * ig + qsum * qg) / 65536))
|
||||
b = min(255,
|
||||
max(0, (ysum * yb + isum * ib + qsum * qb) / 65536))
|
||||
usum += self._read(line, x) * self._sin(x) - self._read(
|
||||
line, x - u_width) * self._sin((x - u_width))
|
||||
vsum += self._read(line, x) * self._cos(x) - self._read(
|
||||
line, x - v_width) * self._cos((x - v_width))
|
||||
rgb = np.matmul(
|
||||
yuv_to_rgb, np.array(
|
||||
(ysum / y_width, usum / u_width,
|
||||
vsum / v_width)).reshape((3, 1))).reshape(3)
|
||||
r = min(255, max(0, rgb[0] * 255))
|
||||
g = min(255, max(0, rgb[1] * 255))
|
||||
b = min(255, max(0, rgb[2] * 255))
|
||||
out_rgb[y, x, :] = (r, g, b)
|
||||
|
||||
return out_rgb
|
||||
|
Loading…
x
Reference in New Issue
Block a user