1706
|
1 *
|
|
2 * GIFcolors: Analyze GIF color map, generate CoCo palette and Gif->coco
|
|
3 * translation tables. Expects X to point to GIF color map, D to hold
|
|
4 * number of palettes in that color map, and U to point to buffer
|
|
5 * to receive translation table.
|
|
6 *
|
|
7 * Data structures
|
|
8 * Color translation table contains three bytes for each GIF color:
|
|
9 * primary color, secondary color, fraction of secondary color for dither
|
|
10 *
|
|
11 * Algorithm
|
|
12 * First, convert each GIF color to closest CoCo color, and choose
|
|
13 * 16 "furthest" apart from those for the palette.
|
|
14 * For each GIF color in the original GIF palette, interpolate it
|
|
15 * between 2 closest colors in the palette.
|
|
16 *
|
|
17 * Notes&Assumptions
|
|
18 * There are no more than 256 colors in the GIF palette. So, B holds
|
|
19 * the number of palettes, where 0 indicates 256.
|
|
20 *
|
|
21 ifp1
|
|
22 use /dd/defs/os9defs.a
|
|
23 endc
|
|
24
|
|
25 psect view_gifcol_a,0,0,0,0,0
|
|
26
|
|
27 check macro
|
|
28 pshs b,cc
|
|
29 ldb #\1
|
|
30 os9 F$PErr
|
|
31 puls b,cc
|
|
32 endm
|
|
33
|
|
34 vsect dp
|
|
35 numpals rmb 1
|
|
36 endsect
|
|
37
|
|
38 GIFcolors:
|
|
39 pshs a,b,x,y,u
|
|
40 pshs a
|
|
41 lda <format
|
|
42 cmpa #GIFBWFormat Or if GIFBW format specified.
|
|
43 beq GIFcol0
|
|
44 lda <type
|
|
45 cmpa #5 Was type 5,6,7 forced?
|
|
46 blo GIFcol1 Illegal mode, do auto-determine
|
|
47 cmpa #7
|
|
48 bhi GIFcol1 Type 8, use full color.
|
|
49 GIFcol0
|
|
50 puls a
|
|
51 bsr bwpals If yes, convert pals to grey scales, gen b/w palette.
|
|
52 bra GIFcol2
|
|
53
|
|
54 GIFcol1
|
|
55 puls a
|
|
56 leau linebuff,y Temporary storage.
|
|
57 bsr copypals Copy the palettes over.
|
|
58 tfr u,x
|
|
59 lbsr genpals Use GIF palettes to generate a CoCo palette
|
|
60 GIFcol2
|
|
61
|
|
62 ldx 2,s
|
|
63 ldu 6,s
|
|
64 lbsr gentable Generate a GIF->CoCo translation table
|
|
65
|
|
66 lbsr palconv Now convert actual palette values
|
|
67
|
|
68 lda <type
|
|
69 cmpa #5
|
|
70 blo GIFcol3 If legal screen type already, skip this.
|
|
71 cmpa #8
|
|
72 bls GIFcolend
|
|
73 GIFcol3
|
|
74 lda #8 Default to type 8 screen
|
|
75 ldb numpals
|
|
76 cmpb #4
|
|
77 bhi GIFcolend
|
|
78 lda #7 Use type 7 if 4 or fewer palette colors.
|
|
79 GIFcolend
|
|
80 sta <type
|
|
81
|
|
82 puls a,b,x,y,u,pc
|
|
83
|
|
84 * Copy D pals from X to U
|
|
85 copypals
|
|
86 pshs a,b,x,y,u
|
|
87 tfr d,y
|
|
88 leay d,y
|
|
89 leay d,y
|
|
90 copyloop
|
|
91 lda ,x+
|
|
92 sta ,u+
|
|
93 leay -1,y
|
|
94 bne copyloop
|
|
95 puls a,b,x,y,u,pc
|
|
96
|
|
97 * Convert palettes to grey scale values.
|
|
98 * D pals pointed to by X.
|
|
99 bwpals
|
|
100 pshs a,b,x,u
|
|
101 tfr x,u
|
|
102 pshs b
|
|
103 bwpals1
|
|
104 ldb ,u
|
|
105 lda #5
|
|
106 mul
|
|
107 tfr d,x
|
|
108 ldb 1,u
|
|
109 lda #3
|
|
110 mul
|
|
111 leax d,x
|
|
112 ldb 2,u
|
|
113 lda #1
|
|
114 mul
|
|
115 leax d,x
|
|
116 lda #9
|
|
117 lbsr div168
|
|
118 stb ,u+
|
|
119 stb ,u+
|
|
120 stb ,u+
|
|
121 dec ,s
|
|
122 bne bwpals1
|
|
123 puls b
|
|
124
|
|
125 clra
|
|
126 leax palette,y
|
|
127 bwpals2
|
|
128 sta ,x+
|
|
129 sta ,x+
|
|
130 sta ,x+
|
|
131 adda #$55
|
|
132 bcc bwpals2
|
|
133 lda #4
|
|
134 sta numpals
|
|
135
|
|
136 lda <type Type 5 only has 2 colors
|
|
137 cmpa #5
|
|
138 bne bwpals3
|
|
139 leax palette+3,y
|
|
140 ldb #$ff
|
|
141 stb ,x+ Set 2nd color to white
|
|
142 stb ,x+
|
|
143 stb ,x+
|
|
144 lda #2
|
|
145 sta numpals
|
|
146 bwpals3
|
|
147
|
|
148 puls a,b,x,u,pc
|
|
149
|
|
150 *
|
|
151 * Use D pals pointed to by X to create a CoCo palette stored in "palette"
|
|
152 * in 3-byte format. (one byte each of R, G, B)
|
|
153 genpals
|
|
154 pshs a,b,x,y,u
|
|
155 lbsr normpals Normalize palettes
|
|
156 leau palette,y
|
|
157 clra
|
|
158 bsr copypal First one we get for free
|
|
159 inca
|
|
160 * X points to GIF palettes, U points to palettes, A holds number
|
|
161 * of palettes we've generated so far.
|
|
162 genloop
|
|
163 ldb 1,s
|
|
164 ldx 2,s
|
|
165 bsr minmax Get the farthest palette from the ones already chosen.
|
|
166 tstb
|
|
167 beq genpend If dist is zero, quit now.
|
|
168 bsr copypal Copy it to the palette.
|
|
169 inca
|
|
170 cmpa #16
|
|
171 bne genloop
|
|
172 genpend
|
|
173 sta numpals
|
|
174 puls a,b,x,y,u,pc
|
|
175
|
|
176 * From the B many GIF palettes at [X], choose the one farthest from the A many
|
|
177 * palettes already selected at [U].
|
|
178 * Local vars: ,s -- counts down GIF palettes
|
|
179 * 1,s -- Max dist so far
|
|
180 * 2:3,s -- Farthest palette seen so far.
|
|
181 minmax
|
|
182 pshs a,y,u
|
|
183 pshs x Init farthest to first
|
|
184 clr ,-s Init max dist to zero
|
|
185 pshs b Init counter
|
|
186 minmaxloop
|
|
187 bsr setdist Get distance from first palette to set of pals.
|
|
188 cmpb 1,s Is it further??
|
|
189 bls minmaxend If no farther, keep going.
|
|
190 stb 1,s Set new dist, palette.
|
|
191 stx 2,s
|
|
192 minmaxend
|
|
193 leax 3,x
|
|
194 dec ,s Count down palettes.
|
|
195 bne minmaxloop
|
|
196 puls b Remove null counter.
|
|
197 puls b Get distance into B.
|
|
198 puls x Get pointer to farthest one.
|
|
199 puls a,y,u,pc
|
|
200
|
|
201 * X points to a palette, U points to A many palettes.
|
|
202 * Return (in B) the minimum distance from [X] to [U]
|
|
203 setdist
|
|
204 pshs u
|
|
205 bsr closest
|
|
206 puls u,pc
|
|
207
|
|
208 vsect dp
|
|
209 nextclose rmb 2
|
|
210 nextdist rmb 1
|
|
211 endsect
|
|
212 * X points to one palette, U to A many palettes.
|
|
213 * Return minimum distance in B, pointer to closest in U.
|
|
214 closest
|
|
215 pshs a,x
|
|
216 pshs a Number of pals on stack.
|
|
217 ldb #$ff Min dist starts out as $FF.
|
|
218 pshs b,u Store the min so far on the stack
|
|
219 stb nextdist ... and in the 2nd closest vars.
|
|
220 stu nextclose
|
|
221 setdistloop
|
|
222 bsr distance
|
|
223 cmpb ,s Is this one closer than the closest so far?
|
|
224 bhs setdist1
|
|
225 lda ,s Yes, make old closest into 2nd closest.
|
|
226 sta nextdist
|
|
227 stb ,s and make this closest.
|
|
228 ldd 1,s
|
|
229 std nextclose
|
|
230 stu 1,s
|
|
231 bra setdist2
|
|
232 setdist1
|
|
233 cmpb nextdist Is it closer than the 2nd closest so far?
|
|
234 bhs setdist2
|
|
235 stb nextdist Yes, store it.
|
|
236 stu nextclose
|
|
237 setdist2
|
|
238 leau 3,u
|
|
239 dec 3,s
|
|
240 bne setdistloop
|
|
241 puls b,u Get the minimum into B, and the closest in U.
|
|
242 puls a
|
|
243 puls a,x,pc
|
|
244
|
|
245 * Copy one palette from [X] to [3*A,U]
|
|
246 copypal
|
|
247 pshs a,u,x
|
|
248 leau a,u
|
|
249 leau a,u
|
|
250 leau a,u
|
|
251 lda ,x+
|
|
252 sta ,u+
|
|
253 lda ,x+
|
|
254 sta ,u+
|
|
255 lda ,x+
|
|
256 sta ,u+
|
|
257 puls a,u,x,pc
|
|
258
|
|
259 * Return the distance from the palette value pointed to by X to the value
|
|
260 * pointed to by U in B
|
|
261 distance
|
|
262 pshs a,x,u
|
|
263 clra
|
|
264 ldb ,x+
|
|
265 subb ,u+
|
|
266 bhi dist1
|
|
267 negb
|
|
268 dist1
|
|
269 pshs d
|
|
270 ldb ,x+
|
|
271 subb ,u+
|
|
272 bhi dist2
|
|
273 negb
|
|
274 dist2
|
|
275 pshs d
|
|
276 ldb ,x+
|
|
277 subb ,u+
|
|
278 bhi dist3
|
|
279 negb
|
|
280 dist3
|
|
281 addd ,s++
|
|
282 addd ,s++
|
|
283 lsra divide to get it in one byte.
|
|
284 rorb
|
|
285 lsra
|
|
286 rorb
|
|
287 puls a,x,u,pc
|
|
288
|
|
289
|
|
290 * Normalize D pals pointed to by X into a CoCo 3-byte format
|
|
291 normpals
|
|
292 pshs a,b,x
|
|
293 normloop
|
|
294 bsr normcoord
|
|
295 bsr normcoord
|
|
296 bsr normcoord
|
|
297 subd #1
|
|
298 bne normloop
|
|
299 puls a,b,x,pc
|
|
300 normcoord
|
|
301 pshs a,b
|
|
302 lda ,x
|
|
303 ldb #85
|
|
304 lbsr divAB Divide by 85.
|
|
305 lslb Round to nearest integer.
|
|
306 adca #0
|
|
307 ldb #85 Mult by 85 to get normed value.
|
|
308 mul
|
|
309 stb ,x+
|
|
310 puls a,b,pc
|
|
311
|
|
312 * X points to D many GIF palettes
|
|
313 * U points to destination for translation table.
|
|
314 *
|
|
315 * Stage 2 algorithm:
|
|
316 * For each GIF color, dither the two closest CoCo colors.
|
|
317 * Use the ratio of distances as the dithering percentage.
|
|
318 csect
|
|
319 gentpals rmb 2 Pointer to CoCo palette
|
|
320 gentcnt rmb 1 Counts down number of GIF colors
|
|
321 gentgif rmb 2 Ptr to GIF colors
|
|
322 gentred rmb 1 Holds one palette value.
|
|
323 gentgrn rmb 1
|
|
324 gentblu rmb 1
|
|
325 genttrans rmb 2 Ptr to trans table.
|
|
326 gent1dist rmb 1 Distance to primary color
|
|
327 gent2dist rmb 1 Distance to secondary color.
|
|
328 gent1pal rmb 2 Ptr to primary color
|
|
329 gent2pal rmb 2 Ptr to secondary color
|
|
330 gentvars rmb 0 Total number of local vars.
|
|
331 endsect
|
|
332
|
|
333 gentable
|
|
334 pshs a,b,x,y,u
|
|
335 leas -gentvars,s
|
|
336 stx gentgif,s
|
|
337 stb gentcnt,s
|
|
338 leay palette,y
|
|
339 sty gentpals,s
|
|
340 tfr u,y
|
|
341 * Y points to trans table address
|
|
342 * gentgif,s points to GIF palettes
|
|
343 * gentpals,s points to CoCo palettes.
|
|
344 gentloop
|
|
345
|
|
346 * First, try to get a "primary" color. Use the closest match.
|
|
347 lda numpals Number of palettes.
|
|
348 ldu gentpals,s Palette ptr.
|
|
349 ldx gentgif,s Ptr to GIF palette.
|
|
350 lbsr closest Get closest coco palette (U points to it)
|
|
351 stu gent1pal,s Save primary color ptr
|
|
352 tfr u,d Set primary color.
|
|
353 subd gentpals,s D holds offset to closest palette.
|
|
354 lbsr div3 Divide B by 3 to get a palette #.
|
|
355 stb ,y
|
|
356
|
|
357 * Now, get an "ideal" secondary color to dither with it.
|
|
358 sty genttrans,s Save Y
|
|
359 ldx gentgif,s Get ptr to GIF palette that we're trying to match
|
|
360 leay gentred,s Put result in gentred, etc.
|
|
361 bsr opp3
|
|
362 ldy genttrans,s restore Y.
|
|
363
|
|
364 * The closest to this "ideal" color will be our secondary color
|
|
365 lda numpals Number of palettes.
|
|
366 ldu gentpals,s Palette ptr.
|
|
367 * leax gentred,s Ptr to "ideal" dither match.
|
|
368 ldx gentgif,s
|
|
369 lbsr closest
|
|
370 cmpu gent1pal,s Is the closest same as the primary color?
|
|
371 bne gent2c2 No, use the closest.
|
|
372 ldu nextclose Otherwise, use the second closest.
|
|
373 gent2c2
|
|
374 tfr u,d
|
|
375 stu gent2pal,s
|
|
376 subd gentpals,s
|
|
377 bsr div3
|
|
378 stb 1,y
|
|
379
|
|
380 * Calculate distance from desired color to primary color
|
|
381 ldu gent1pal,s
|
|
382 ldx gentgif,s
|
|
383 lbsr distance
|
|
384 stb gent1dist,s
|
|
385
|
|
386 * Calculate distance from desired color to secondary color
|
|
387 ldu gent2pal,s
|
|
388 ldx gentgif,s
|
|
389 lbsr distance
|
|
390 stb gent2dist,s
|
|
391
|
|
392 * Now, use the two distances to get the dithering percentage.
|
|
393 ldb gent1dist,s Set % secondary.= (1st dist) / ( (1st dist) + (2nd dist) )
|
|
394 beq gentzero
|
|
395 tfr b,a
|
|
396 addb gent2dist,s Add distances, 9 bit result (B + Carry)
|
|
397 rorb Divide B by 2 (include carry from addition)
|
|
398 lsra Div A by 2.
|
|
399 lbsr divAB
|
|
400 gentzero
|
|
401 stb 2,y
|
|
402
|
|
403 leay 3,y Point to next trans table entry.
|
|
404
|
|
405 ldx gentgif,s
|
|
406 leax 3,x
|
|
407 stx gentgif,s Point to next GIF palette.
|
|
408
|
|
409 dec gentcnt,s Count down number.
|
|
410 bne gentloop
|
|
411
|
|
412 leas gentvars,s Clean up stack.
|
|
413 puls a,b,x,y,u,pc
|
|
414
|
|
415 * Returns in [Y], palette value on other side of [X] from [U]
|
|
416 opp3
|
|
417 pshs a,b,x,y,u
|
|
418 bsr opp31
|
|
419 bsr opp31
|
|
420 bsr opp31
|
|
421 puls a,b,x,y,u,pc
|
|
422 opp31
|
|
423 ldb ,x+
|
|
424 lda ,u+
|
|
425 bsr opposite
|
|
426 stb ,y+
|
|
427 rts
|
|
428
|
|
429 * returns in B palette value on other side of B from A.
|
|
430 * i.e. calculate 2B-A, truncating at zero and at $ff.
|
|
431 opposite
|
|
432 pshs a
|
|
433 clra
|
|
434 lslb
|
|
435 rola
|
|
436 subb ,s
|
|
437 sbca #0
|
|
438 bpl opp1
|
|
439 ldd #0 If result is negative, chop at zero.
|
|
440 opp1
|
|
441 tsta If >255, chop there.
|
|
442 beq opp2
|
|
443 ldb #$ff
|
|
444 opp2
|
|
445 puls a,pc
|
|
446
|
|
447 * Divide positive B by 3.
|
|
448 div3
|
|
449 pshs a
|
|
450 tfr b,a
|
|
451 ldb #3
|
|
452 lbsr divAB
|
|
453 tfr a,b
|
|
454 puls a,pc
|
|
455
|
|
456 endsect
|