1
2 /*
3 * xa_cmap.c
4 *
5 * Copyright (C) 1992-1998,1999 by Mark Podlipec.
6 * All rights reserved.
7 *
8 * This software may be freely used, copied and redistributed without
9 * fee for non-commerical purposes provided that this copyright
10 * notice is preserved intact on all copies.
11 *
12 * There is no warranty or other guarantee of fitness of this software.
13 * It is provided solely "as is". The author disclaims all
14 * responsibility and liability with respect to this software's usage
15 * or its effect upon hardware or computer systems.
16 *
17 */
18
19 #include "xanim.h"
20
21 extern XA_CHDR *xa_chdr_first;
22 extern XColor defs[256];
23 extern Display *theDisp;
24 extern Colormap theCmap;
25
26 extern xaULONG cmap_use_combsort;
27
28 static XA_CHDR *cmap_332_chdr = 0;
29 static XA_CHDR *cmap_gray_chdr = 0;
30 static double cmap_332_gamma = 0.0;
31 static double cmap_gray_gamma = 0.0;
32 static double cmap_cur_gamma = 0.0;
33
34 /* TBD move to xanim.h */
35 #define GAMMA_MIN 0.0001
36
37 #define CMAP_ABS(x) (((x)<0)?(-(x)):(x))
38 #define CMAP_SQR(x) ((x) * (x))
39
40 xaULONG cmap_scale[17] = { 65535, 65535, 21845, 9362,
41 4369, 2114, 1040, 516,
42 257, 128, 64, 32,
43 16, 8, 4, 2, 1};
44
45 ColorReg find_cmap[256];
46 ColorReg *cur_find_cmap = 0;
47 xaULONG find_red[256],find_green[256],find_blue[256];
48
49 /* Box structure for Median Cut algorithm */
50 typedef struct CMAP_Box_Struct
51 {
52 struct CMAP_Box_Struct *next;
53 xaLONG rmin,rmax,gmin,gmax,bmin,bmax;
54 xaULONG last_sort;
55 xaULONG *clist;
56 xaULONG clist_len;
57 } CMAP_Box;
58
59 #define CMAP_MEDIAN_NONE 0
60 #define CMAP_MEDIAN_RED 1
61 #define CMAP_MEDIAN_GREEN 2
62 #define CMAP_MEDIAN_BLUE 3
63
64 int ColorComp();
65 int CMAP_CList_Compare();
66 xaULONG CMAP_Find_Closest();
67 xaLONG CMAP_Find_Exact();
68 xaLONG CMAP_CHDR_Match();
69 void CMAP_Remap_CHDRs();
70 void CMAP_Remap_CHDR();
71 void CMAP_Compact_Box();
72 xaLONG CMAP_Split_Box();
73 void CMAP_Histogram_CHDR();
74 void CMAP_CMAP_From_Clist();
75 void CMAP_CList_CombSort();
76 void CMAP_CList_CombSort_Red();
77 void CMAP_CList_CombSort_Green();
78 void CMAP_CList_CombSort_Blue();
79 xaULONG CMAP_Gamma_Adjust();
80 void CMAP_Shrink_CHDR();
81 void CMAP_Map_To_One();
82
83
84 xaLONG CMAP_Median_Cut();
85 CMAP_Box *CMAP_Get_Box();
86 void CMAP_Find_Box_Color();
87 int CMAP_Median_Compare_Red();
88 int CMAP_Median_Compare_Green();
89 int CMAP_Median_Compare_Blue();
90 xaLONG CMAP_Split_Box();
91
92 XA_CHDR *ACT_Get_CHDR();
93 XA_CHDR *ACT_Get_CMAP();
94 XA_CHDR *CMAP_Create_CHDR_From_True();
95
96 void X11_Get_Colormap();
97 void X11_Make_Nice_CHDR();
98
99 /*
100 *
101 */
ColorComp(c1,c2)102 int ColorComp(c1,c2)
103 ColorReg *c1,*c2;
104 {
105 long val1,val2;
106
107 val1 = (3 * c1->red) + (4 * c1->green) + (2 * c1->blue);
108 val2 = (3 * c2->red) + (4 * c2->green) + (2 * c2->blue);
109 if (val1 != val2) return( val2 - val1 );
110 else if (c1->green != c2->green) return( c2->green - c1->green );
111 else if (c1->red != c2->red ) return( c2->red - c1->red );
112 else return( c2->blue - c1->blue );
113 }
114
115 /*
116 *
117 */
CMAP_Find_Closest(t_cmap,csize,r,g,b,rbits,gbits,bbits,color_flag)118 xaULONG CMAP_Find_Closest(t_cmap,csize,r,g,b,rbits,gbits,bbits,color_flag)
119 ColorReg *t_cmap;
120 xaULONG csize;
121 xaLONG r,g,b;
122 xaULONG rbits,gbits,bbits;
123 xaULONG color_flag;
124 { register xaULONG i,min_diff;
125 register xaULONG cmap_entry;
126
127 if (color_flag == xaFALSE)
128 {
129 register xaLONG gray;
130
131 gray = 11 * (r * cmap_scale[rbits]);
132 gray += 16 * (g * cmap_scale[gbits]);
133 gray += 5 * (b * cmap_scale[bbits]);
134 gray >>= 5;
135 cmap_entry = 0;
136 for(i=0; i<csize; i++)
137 {
138 register xaULONG diff;
139 diff = CMAP_ABS(gray - (xaLONG)(t_cmap[i].gray));
140 if (i == 0) min_diff = diff;
141
142 if (diff == 0) return(i);
143 if (diff < min_diff) {min_diff = diff; cmap_entry = i;}
144 }
145 return(cmap_entry);
146 }
147 else
148 {
149 if (cur_find_cmap != t_cmap)
150 {
151 if (cur_find_cmap == 0)
152 {
153 for(i=0;i<256;i++)
154 {
155 find_red[i] = 11 * i * i;
156 find_green[i] = 16 * i * i;
157 find_blue[i] = 5 * i * i;
158 }
159 }
160 for(i=0;i<csize;i++)
161 {
162 find_cmap[i].red = t_cmap[i].red >> 8;
163 find_cmap[i].green = t_cmap[i].green >> 8;
164 find_cmap[i].blue = t_cmap[i].blue >> 8;
165 }
166 cur_find_cmap = t_cmap;
167 }
168 if (rbits < 16) r *= cmap_scale[rbits];
169 if (gbits < 16) g *= cmap_scale[gbits];
170 if (bbits < 16) b *= cmap_scale[bbits];
171 r >>= 8; g >>= 8; b >>= 8;
172 cmap_entry = 0;
173 for(i=0; i<csize; i++)
174 {
175 register xaULONG diff;
176 diff = find_red[ CMAP_ABS(r - (xaLONG)(find_cmap[i].red)) ];
177 diff += find_green[ CMAP_ABS(g - (xaLONG)(find_cmap[i].green))];
178 diff += find_blue[ CMAP_ABS(b - (xaLONG)(find_cmap[i].blue)) ];
179 if (i == 0) min_diff = diff;
180
181 if (diff == 0) return(i);
182 if (diff < min_diff) {min_diff = diff; cmap_entry = i;}
183 }
184 return(cmap_entry);
185 }
186 }
187
188 /*
189 * return index of exact match.
190 * return -1 if no match found.
191 */
CMAP_Find_Exact(cmap,coff,csize,r,g,b,gray)192 xaLONG CMAP_Find_Exact(cmap,coff,csize,r,g,b,gray)
193 ColorReg *cmap;
194 xaULONG coff,csize;
195 xaUSHORT r,g,b,gray;
196 {
197 register xaLONG i,match;
198
199 match = -1;
200 i = csize;
201 if (x11_display_type & XA_X11_GRAY)
202 {
203 while( (i > coff) && (match < 0) )
204 { i--; if (gray == cmap[i].gray) match = i; }
205 }
206 else
207 {
208 while( (i > coff) && (match < 0) )
209 { i--;
210 if ( (r == cmap[i].red)
211 && (g == cmap[i].green)
212 && (b == cmap[i].blue) ) match = i;
213 }
214 }
215 return(match);
216 }
217
218 /*
219 *
220 */
CMAP_CHDR_Match(chdr1,chdr2)221 xaLONG CMAP_CHDR_Match(chdr1,chdr2)
222 XA_CHDR *chdr1,*chdr2;
223 {
224 ColorReg *cmap1,*cmap2;
225 xaULONG i;
226
227 if (chdr1 == chdr2) return(xaTRUE);
228 if ( (chdr1->csize != chdr2->csize)
229 || (chdr1->coff != chdr2->coff ) ) return(xaFALSE);
230
231 cmap1 = chdr1->cmap;
232 cmap2 = chdr2->cmap;
233 for(i=0; i < chdr1->csize; i++)
234 {
235 if ( (cmap1[i].red != cmap2[i].red)
236 || (cmap1[i].green != cmap2[i].green)
237 || (cmap1[i].blue != cmap2[i].blue) ) return(xaFALSE);
238 }
239 return(xaTRUE);
240 }
241
242 /*
243 *
244 */
CMAP_CList_Compare(pc1,pc2)245 int CMAP_CList_Compare(pc1,pc2)
246 void *pc1,*pc2;
247 { int *c1 = (int *)pc1;
248 int *c2 = (int *)pc2;
249 return( (*c1) - (*c2) );
250 }
251
252 void
CMAP_BitMask_CList(clist,cnum,bits)253 CMAP_BitMask_CList(clist,cnum,bits)
254 xaULONG *clist,cnum,bits;
255 {
256 xaULONG i,r_mask;
257 if ( (bits==0) || (bits>=9) ) TheEnd1("CMAP_BitMask_CList: bad bits");
258 r_mask = ((0x01 << bits) - 1);
259 r_mask <<= 8 - bits;
260 r_mask = (r_mask << 16) | (r_mask << 8) | r_mask;
261 for(i=0;i<cnum;i++) *clist++ &= r_mask;
262 }
263
CMAP_Compress_CList(clist,cnum)264 xaULONG CMAP_Compress_CList(clist,cnum)
265 xaULONG *clist,cnum;
266 {
267 register xaULONG i,j,data;
268
269 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Compress_CList: start %d c %d\n",
270 cnum,cmap_use_combsort);
271 if (cnum == 1) return(cnum);
272 /* sort color list */
273 if (cmap_use_combsort == xaTRUE) CMAP_CList_CombSort(clist,cnum);
274 else qsort(clist,cnum,sizeof(xaULONG),CMAP_CList_Compare);
275 /* eliminate identical entries */
276 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Compress_CList: sort done %d\n",cnum);
277 data = clist[0]; j = 1;
278 for(i=1; i<cnum; i++)
279 { if (data != clist[i])
280 { data = clist[i];
281 clist[j] = data; j++;
282 }
283 }
284 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Compress_CList: done %d\n",j);
285 return(j);
286 }
287
288 /*
289 * return the total number of colors in all of the current chdr's
290 * also return the largest csize in max_csize if not NULL.
291 */
CMAP_Color_Count(chdr,max_csize)292 xaULONG CMAP_Color_Count(chdr,max_csize)
293 XA_CHDR *chdr;
294 xaULONG *max_csize;
295 {
296 xaULONG cnt,max_size;
297 cnt = max_size = 0;
298 while(chdr)
299 {
300 if (chdr->csize > max_size) max_size = chdr->csize;
301 cnt += chdr->csize;
302 chdr = chdr->next; }
303 if (max_csize != 0) *max_csize = max_size;
304 return(cnt);
305 }
306
307
CMAP_Make_Clist(chdr,clist)308 xaULONG CMAP_Make_Clist(chdr,clist)
309 XA_CHDR *chdr;
310 xaULONG **clist;
311 {
312 xaULONG *clst,clist_len,c_i;
313
314 /* count colors in chdr's */
315 clist_len = CMAP_Color_Count(chdr,(xaULONG *)(0));
316 /* allocate room for list of all colors */
317 clst = (xaULONG *)malloc(clist_len * sizeof(xaULONG));
318 if (clst == 0) TheEnd1("CMAP_Make_Clist: malloc err\n");
319
320 c_i = 0;
321 while(chdr)
322 {
323 ColorReg *cmap;
324 xaULONG i,csize,*hist,stat_size;
325
326 csize = chdr->csize;
327 cmap = chdr->cmap;
328 if (cmap_hist_flag == xaTRUE)
329 {
330 hist = (xaULONG *)malloc(csize * sizeof(xaULONG));
331 if (hist == 0) TheEnd1("CMAP_Manipulate_CHDRS: hist malloc err\n");
332 for(i=0;i<csize;i++) hist[i] = 0;
333 CMAP_Histogram_CHDR(chdr,hist,csize,chdr->moff);
334 stat_size = c_i;
335 } else hist = 0;
336 for(i=0; i<chdr->csize; i++)
337 {
338 if ( (cmap_hist_flag == xaFALSE)
339 || ((cmap_hist_flag == xaTRUE) && hist[i]) )
340 {
341 /* note: cmap's are full 16 bits and clist is 0 r g b, 8 bits each*/
342 clst[c_i] = (xaULONG)(cmap[i].red & 0xff00) << 8;
343 clst[c_i] |= (xaULONG)(cmap[i].green & 0xff00);
344 clst[c_i] |= (xaULONG)(cmap[i].blue & 0xff00) >> 8;
345 c_i++;
346 }
347 }
348 if (hist) { FREE(hist,0x201); hist=0;}
349 if (cmap_hist_flag == xaTRUE)
350 {
351 DEBUG_LEVEL2
352 fprintf(stderr," csize %x afta hist %d\n",
353 chdr->csize,(c_i - stat_size) );
354 }
355 chdr = chdr->next;
356 }
357 *clist = clst;
358 return(c_i);
359 }
360
361 void
CMAP_Map_To_One()362 CMAP_Map_To_One()
363 {
364 XA_CHDR *new_chdr;
365 xaULONG *clist,clist_len,i,wanted_csize;
366 xaULONG actual_csize;
367
368 /* NOTE: clist is malloc'd in CMAP_Make_Clist */
369 clist_len = CMAP_Make_Clist(xa_chdr_start,&clist);
370 DEBUG_LEVEL2
371 fprintf(stderr,"CMAP_Map_To_One: start csize = %d\n",clist_len);
372
373 wanted_csize = x11_cmap_size;
374
375 {
376 xaULONG bits;
377
378 bits = 7;
379 while ( (clist_len >= wanted_csize) && (bits >= cmap_median_bits) )
380 {
381 CMAP_BitMask_CList(clist,clist_len,bits);
382 clist_len = CMAP_Compress_CList(clist,clist_len);
383 DEBUG_LEVEL2
384 fprintf(stderr,"CMAP_Map_To_One: bit %d csize = %d\n",bits,clist_len);
385 bits--;
386 }
387 if (clist_len < wanted_csize) wanted_csize = clist_len;
388 }
389
390 new_chdr = ACT_Get_CHDR(1,wanted_csize,0,wanted_csize,0,xaTRUE,xaTRUE);
391 if (clist_len > wanted_csize)
392 {
393 actual_csize = CMAP_Median_Cut(new_chdr->cmap,
394 clist,clist_len,wanted_csize);
395 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: csize %d\n",actual_csize);
396 }
397 else
398 {
399 CMAP_CMAP_From_Clist(new_chdr->cmap,clist,clist_len);
400 actual_csize = clist_len;
401 DEBUG_LEVEL2 fprintf(stderr,"CMAP_CList: csize %d\n",actual_csize);
402 }
403 FREE(clist,0x202); clist=0;
404 new_chdr->csize = actual_csize;
405 new_chdr->coff = x11_cmap_size - actual_csize;
406 new_chdr->msize = actual_csize;
407 new_chdr->moff = x11_cmap_size - actual_csize;
408 for(i=0; i<new_chdr->msize; i++) new_chdr->map[i] = i + new_chdr->moff;
409 if (cmap_play_nice == xaTRUE) X11_Make_Nice_CHDR(new_chdr);
410 CMAP_Remap_CHDRs(new_chdr);
411 xa_chdr_first = new_chdr;
412 }
413
414 void
CMAP_Shrink_CHDR(old_chdr,new_csize)415 CMAP_Shrink_CHDR(old_chdr,new_csize)
416 XA_CHDR *old_chdr;
417 xaULONG new_csize;
418 {
419 XA_CHDR *new_chdr;
420 xaULONG *clist,clist_len,i,wanted_csize;
421 xaULONG actual_csize;
422
423 /* NOTE: clist is malloc'd in CMAP_Make_Clist */
424 clist_len = CMAP_Make_Clist(xa_chdr_start,&clist);
425 DEBUG_LEVEL2
426 fprintf(stderr,"CMAP_Shrink_CHDR: start csize = %d\n",clist_len);
427 wanted_csize = new_csize;
428
429 {
430 xaULONG bits;
431
432 bits = 7;
433 while ( (clist_len >= wanted_csize) && (bits >= cmap_median_bits) )
434 {
435 CMAP_BitMask_CList(clist,clist_len,bits);
436 clist_len = CMAP_Compress_CList(clist,clist_len);
437 DEBUG_LEVEL2
438 fprintf(stderr,"CMAP_Map_To_One: bit %d csize = %d\n",bits,clist_len);
439 bits--;
440 }
441 if (clist_len < wanted_csize) wanted_csize = clist_len;
442 }
443
444 new_chdr = ACT_Get_CHDR(1,wanted_csize,0,wanted_csize,0,xaTRUE,xaTRUE);
445 if (clist_len > wanted_csize)
446 {
447 actual_csize = CMAP_Median_Cut(new_chdr->cmap,
448 clist,clist_len,wanted_csize);
449 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: csize %d\n",actual_csize);
450 }
451 else
452 {
453 CMAP_CMAP_From_Clist(new_chdr->cmap,clist,clist_len);
454 actual_csize = clist_len;
455 DEBUG_LEVEL2 fprintf(stderr,"CMAP_CList: csize %d\n",actual_csize);
456 }
457 FREE(clist,0x202); clist=0;
458 new_chdr->csize = actual_csize;
459 new_chdr->coff = x11_cmap_size - actual_csize;
460 new_chdr->msize = actual_csize;
461 new_chdr->moff = x11_cmap_size - actual_csize;
462 for(i=0; i<new_chdr->msize; i++) new_chdr->map[i] = i + new_chdr->moff;
463 CMAP_Remap_CHDRs(new_chdr);
464 }
465
466 void
CMAP_Manipulate_CHDRS()467 CMAP_Manipulate_CHDRS()
468 {
469 xa_chdr_first = xa_chdr_start;
470
471 if (x11_display_type == XA_MONOCHROME) return;
472 if ( (x11_display_type & XA_X11_STATIC)
473 || (x11_display_type & XA_X11_TRUE) )
474 {
475 XA_CHDR *fixed_chdr;
476
477 fixed_chdr = ACT_Get_CHDR(1,x11_cmap_size,0,x11_cmap_size,0,xaTRUE,xaTRUE);
478 X11_Get_Colormap(fixed_chdr);
479 xa_chdr_first = fixed_chdr;
480 CMAP_Remap_CHDRs(fixed_chdr);
481 return;
482 }
483 else if ( (cmap_play_nice == xaTRUE) || (cmap_map_to_one_flag == xaTRUE)
484 || (cmap_color_func == 4) )
485 {
486 CMAP_Map_To_One();
487 return;
488 }
489 else if (cmap_map_to_1st_flag == xaTRUE)
490 {
491 CMAP_Remap_CHDRs(xa_chdr_start);
492 return;
493 }
494 else if (x11_display_type != XA_MONOCHROME)
495 { /* Check for CMAPs > x11_cmap_size */
496 xaULONG flag;
497 XA_CHDR *tmp_chdr;
498
499 flag = 0;
500 tmp_chdr = xa_chdr_start;
501 while(tmp_chdr != 0)
502 {
503 if (tmp_chdr->csize > x11_cmap_size)
504 {
505 CMAP_Shrink_CHDR(tmp_chdr,x11_cmap_size);
506 if (flag == 0) xa_chdr_first = tmp_chdr->new_chdr;
507 }
508 tmp_chdr = tmp_chdr->next;
509 flag = 1;
510 }
511 }
512 }
513
514 void
CMAP_Remap_CHDR(new_chdr,old_chdr)515 CMAP_Remap_CHDR(new_chdr,old_chdr)
516 XA_CHDR *new_chdr,*old_chdr;
517 {
518 ColorReg *new_cmap,*old_cmap;
519 xaULONG *tmp_map,*old_map;
520 xaULONG new_csize,new_coff,old_csize,old_coff;
521 xaULONG new_moff,old_msize,old_moff;
522 xaULONG i,cflag;
523
524 old_cmap = old_chdr->cmap;
525 old_csize = old_chdr->csize;
526 old_coff = old_chdr->coff;
527 old_map = old_chdr->map;
528 old_msize = old_chdr->msize;
529 old_moff = old_chdr->moff;
530
531 new_csize = new_chdr->csize;
532 new_coff = new_chdr->coff;
533 new_cmap = new_chdr->cmap;
534 new_moff = new_chdr->moff;
535
536 tmp_map = (xaULONG *)malloc(old_msize * sizeof(xaULONG));
537 if (tmp_map == 0) TheEnd1("CMAP_Remap_CHDR: map malloc err\n");
538
539 cflag = (x11_display_type & XA_X11_COLOR)?xaTRUE:xaFALSE;
540 for(i=0; i < old_msize; i++)
541 {
542 xaULONG j,match;
543 j = i + old_moff - old_coff; /* get cmap entry for this pixel */
544 if (x11_display_type & XA_X11_TRUE)
545 {
546 tmp_map[i] = X11_Get_True_Color(
547 old_cmap[j].red,old_cmap[j].green,old_cmap[j].blue,16);
548 }
549 else
550 {
551 match = CMAP_Find_Closest( new_cmap,new_csize,
552 old_cmap[j].red, old_cmap[j].green, old_cmap[j].blue,16,16,16,cflag);
553 tmp_map[i] = match + new_coff; /* new pixel value */
554 }
555 }
556 old_chdr->new_chdr = new_chdr;
557 FREE(old_chdr->map,0x203);
558 old_chdr->map = tmp_map;
559 }
560
561 void
CMAP_Remap_CHDRs(the_chdr)562 CMAP_Remap_CHDRs(the_chdr)
563 XA_CHDR *the_chdr;
564 {
565 XA_CHDR *tmp_chdr;
566
567 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Remap_CHDRs to %x\n",(xaULONG)the_chdr);
568
569 tmp_chdr = xa_chdr_start;
570 while(tmp_chdr)
571 {
572 if (CMAP_CHDR_Match(the_chdr,tmp_chdr) == xaFALSE)
573 CMAP_Remap_CHDR(the_chdr,tmp_chdr);
574 tmp_chdr = tmp_chdr->next;
575 }
576 }
577
578 void
CMAP_CMAP_From_Clist(cmap_out,clist,clist_len)579 CMAP_CMAP_From_Clist(cmap_out,clist,clist_len)
580 ColorReg *cmap_out;
581 xaULONG *clist,clist_len;
582 {
583 register xaULONG i,r,g,b;
584
585 for(i=0;i<clist_len;i++)
586 {
587 r = (clist[i] >> 16) & 0xff;
588 g = (clist[i] >> 8) & 0xff;
589 b = clist[i] & 0xff;
590 cmap_out[i].red = (xaUSHORT)( r | (r << 8) );
591 cmap_out[i].green = (xaUSHORT)( g | (g << 8) );
592 cmap_out[i].blue = (xaUSHORT)( b | (b << 8) );
593 cmap_out[i].gray =
594 (xaUSHORT)( (((r * 11) + (g * 16) + (b * 5) ) >> 5) * 257 );
595 }
596 }
597
CMAP_Get_Box()598 CMAP_Box *CMAP_Get_Box()
599 {
600 CMAP_Box *tmp;
601 tmp = (CMAP_Box *)malloc(sizeof(CMAP_Box));
602 if (tmp == 0) TheEnd1("CMAP_Get_Box: malloc err\n");
603 return(tmp);
604 }
605
CMAP_Median_Cut(cmap_out,clist,clist_len,wanted_clen)606 xaLONG CMAP_Median_Cut(cmap_out,clist,clist_len,wanted_clen)
607 ColorReg *cmap_out;
608 xaULONG *clist,clist_len,wanted_clen;
609 {
610 CMAP_Box *start_box,*box;
611 xaULONG i,cur_box_num;
612
613 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: starting\n");
614 /* make first box */
615 start_box = CMAP_Get_Box();
616 start_box->clist = clist;
617 start_box->clist_len = clist_len;
618 start_box->next = 0;
619 CMAP_Compact_Box(start_box);
620
621 cur_box_num = 1;
622 while(cur_box_num < wanted_clen)
623 {
624 xaULONG box_i,box_num;
625
626 /* loop through current boxes and split in half */
627 box_i = 0;
628 box_num = cur_box_num;
629 box = start_box;
630 while( box && (cur_box_num < wanted_clen) && (box_i < box_num) )
631 {
632 if ( CMAP_Split_Box(box) == xaTRUE )
633 {
634 cur_box_num++;
635 box = box->next; /* move past new box */
636 }
637 box_i++;
638 box = box->next;
639 }
640 if (box_num == cur_box_num) break; /* no boxes split */
641 }
642
643 box = start_box;
644 for(i=0; i<cur_box_num; i++)
645 {
646 if (box)
647 {
648 CMAP_Find_Box_Color(&cmap_out[i],box);
649 start_box = box;
650 box = box->next;
651 FREE(start_box,0x205);
652 }
653 else fprintf(stderr,"CMAP_Median_Cut: box/box_num mismatch\n");
654 }
655 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: done\n");
656 return(cur_box_num);
657 }
658
659
660 void
CMAP_Compact_Box(box)661 CMAP_Compact_Box(box)
662 CMAP_Box *box;
663 {
664 xaLONG i;
665
666 DEBUG_LEVEL3 fprintf(stderr,"Compacting Box %x\n",(xaULONG)box);
667 /* 256 is max+1 in 8 bit r,g,b */
668 box->rmin = box->gmin = box->bmin = 256;
669 box->rmax = box->gmax = box->bmax = -1;
670 for(i=0; i<box->clist_len; i++)
671 {
672 register xaLONG r,g,b;
673
674 b = box->clist[i];
675 r = (b >> 16) & 0xff;
676 g = (b >> 8) & 0xff;
677 b &= 0xff;
678
679 if (r < box->rmin) box->rmin = r;
680 if (g < box->gmin) box->gmin = g;
681 if (b < box->bmin) box->bmin = b;
682 if (r > box->rmax) box->rmax = r;
683 if (g > box->gmax) box->gmax = g;
684 if (b > box->bmax) box->bmax = b;
685 }
686 }
687
CMAP_Median_Compare_Red(pc1,pc2)688 int CMAP_Median_Compare_Red(pc1,pc2)
689 void *pc1,*pc2;
690 { int *c1 = (int *)pc1;
691 int *c2 = (int *)pc2;
692 return( ((*c1) & 0xff0000) - ((*c2) & 0xff0000) );
693 }
694
CMAP_Median_Compare_Green(pc1,pc2)695 int CMAP_Median_Compare_Green(pc1,pc2)
696 void *pc1,*pc2;
697 { int *c1 = (int *)pc1;
698 int *c2 = (int *)pc2;
699 return( ((*c1) & 0xff00) - ((*c2) & 0xff00) );
700 }
701
CMAP_Median_Compare_Blue(pc1,pc2)702 int CMAP_Median_Compare_Blue(pc1,pc2)
703 void *pc1,*pc2;
704 { int *c1 = (int *)pc1;
705 int *c2 = (int *)pc2;
706 return( ((*c1) & 0xff) - ((*c2) & 0xff) );
707 }
708
709
710
CMAP_Split_Box(box)711 xaLONG CMAP_Split_Box(box)
712 CMAP_Box *box;
713 {
714 CMAP_Box *newbox;
715 register xaLONG sort_type,rdif,gdif,bdif;
716
717 rdif = box->rmax - box->rmin;
718 gdif = box->gmax - box->gmin;
719 bdif = box->bmax - box->bmin;
720 if (box->clist_len <= 1) return(xaFALSE);
721
722 if ((rdif >= gdif) && (rdif >= bdif)) sort_type = CMAP_MEDIAN_RED;
723 else if ((gdif >= rdif) && (gdif >= bdif)) sort_type = CMAP_MEDIAN_GREEN;
724 else sort_type = CMAP_MEDIAN_BLUE;
725
726 if (box->last_sort != sort_type)
727 {
728 if (cmap_use_combsort == xaTRUE)
729 switch(sort_type)
730 {
731 case CMAP_MEDIAN_RED:
732 CMAP_CList_CombSort_Red(box->clist,box->clist_len); break;
733 case CMAP_MEDIAN_GREEN:
734 CMAP_CList_CombSort_Green(box->clist,box->clist_len); break;
735 default:
736 CMAP_CList_CombSort_Blue(box->clist,box->clist_len); break;
737 }
738 else
739 switch(sort_type)
740 {
741 case CMAP_MEDIAN_RED: qsort(box->clist,box->clist_len,
742 sizeof(xaLONG),CMAP_Median_Compare_Red); break;
743 case CMAP_MEDIAN_GREEN: qsort(box->clist,box->clist_len,
744 sizeof(xaLONG),CMAP_Median_Compare_Green); break;
745 default: qsort(box->clist,box->clist_len,
746 sizeof(xaLONG),CMAP_Median_Compare_Blue); break;
747 }
748 box->last_sort = sort_type;
749 }
750 newbox = CMAP_Get_Box();
751 newbox->next = box->next;
752 box->next = newbox;
753 /* split color list */
754 newbox->clist_len = box->clist_len / 2;
755 box->clist_len -= newbox->clist_len;
756 newbox->clist = &box->clist[box->clist_len];
757 newbox->last_sort = sort_type;
758 CMAP_Compact_Box(box);
759 CMAP_Compact_Box(newbox);
760 return(xaTRUE);
761 }
762
763 /*
764 * Assumes 8 bits per color component
765 */
766 void
CMAP_Find_Box_Color(creg,box)767 CMAP_Find_Box_Color(creg,box)
768 ColorReg *creg;
769 CMAP_Box *box;
770 {
771 register xaLONG i;
772 register xaULONG r,g,b,sum;
773
774 DEBUG_LEVEL3 fprintf(stderr," box has %d\n",box->clist_len);
775 if (cmap_median_type == CMAP_MEDIAN_SUM)
776 {
777 r=0; g=0; b=0; sum=0;
778 for(i=0; i<box->clist_len; i++)
779 {
780 register xaULONG tcol;
781 tcol = box->clist[i];
782 r += (tcol >> 16) & 0xff;
783 g += (tcol >> 8) & 0xff;
784 b += tcol & 0xff;
785 }
786 sum = box->clist_len;
787 r /= sum; g /= sum; b /= sum;
788 }
789 else
790 {
791 r = (box->rmin + box->rmax) >> 1;
792 g = (box->gmin + box->gmax) >> 1;
793 b = (box->bmin + box->bmax) >> 1;
794 }
795 creg->red = r * 257;
796 creg->green = g * 257;
797 creg->blue = b * 257;
798 creg->gray = (((r * 11) + (g * 16) + (b * 5) ) >> 5) * 257;
799 }
800
801
802 void
CMAP_Histogram_CHDR(chdr,hist,csize,moff)803 CMAP_Histogram_CHDR(chdr,hist,csize,moff)
804 XA_CHDR *chdr;
805 xaULONG *hist,csize,moff;
806 {
807 XA_ACTION *act;
808
809 DEBUG_LEVEL2 fprintf(stderr,"Histogram for %x\n",(xaULONG)chdr);
810 act = chdr->acts;
811 while(act)
812 {
813 switch(act->type)
814 {
815 case ACT_DISP:
816 case ACT_MAPPED:
817 {
818 register xaUBYTE *p;
819 register xaULONG psize;
820 ACT_MAPPED_HDR *map_hdr;
821
822 DEBUG_LEVEL2 fprintf(stderr," hist'ing act %x\n",(xaULONG)act);
823 map_hdr = (ACT_MAPPED_HDR *)act->data;
824 psize = map_hdr->xsize * map_hdr->ysize;
825 p = map_hdr->data;
826 if (p)
827 {
828 if (moff) while(psize--) hist[ (*p++)-moff ]++;
829 else while(psize--) hist[ *p++ ]++;
830 }
831 }
832 break;
833 /*
834 case ACT_SETTER:
835 {
836 register xaUBYTE *p;
837 register xaULONG psize;
838 ACT_MAPPED_HDR *map_hdr;
839 ACT_SETTER_HDR *setter_hdr;
840 XA_ACTION *back_act;
841
842 DEBUG_LEVEL2 fprintf(stderr," hist'ing setter act %x\n",act);
843
844 setter_hdr = (ACT_SETTER_HDR *)act->data;
845 back_act = setter_hdr->back;
846 if (back_act)
847 {
848 map_hdr = (ACT_MAPPED_HDR *)back_act->data;
849 psize = map_hdr->xsize * map_hdr->ysize;
850 DEBUG_LEVEL2 fprintf(stderr,"psize = %d\n",psize);
851 p = map_hdr->data;
852 if (p)
853 {
854 if (moff) while(psize--) hist[ (*p++)-moff ]++;
855 else while(psize--) hist[ *p++ ]++;
856 }
857 }
858 }
859 break;
860 */
861 } /* end of switch */
862 act = act->next_same_chdr;
863 } /* end of while */
864
865 }
866
CMAP_Expand_Maps()867 void CMAP_Expand_Maps()
868 {
869 XA_CHDR *tmp_chdr;
870
871 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Expand_Maps\n");
872
873 tmp_chdr = xa_chdr_start;
874 while(tmp_chdr)
875 {
876 register xaULONG i,msize,d,*map;
877
878 msize = tmp_chdr->msize;
879 map = tmp_chdr->map;
880 if (map)
881 for(i=0;i<msize;i++)
882 {
883 d = map[i] & 0xff;
884 map[i] = (d<<24) | (d<<16) | (d<<8) | d;
885 }
886 tmp_chdr = tmp_chdr->next;
887 }
888 }
889
890 void
CMAP_Cache_Init(flag)891 CMAP_Cache_Init(flag)
892 xaULONG flag;
893 {
894 cmap_cache_bits = cmap_median_bits;
895 if (cmap_cache_bits > CMAP_CACHE_MAX_BITS)
896 cmap_cache_bits = CMAP_CACHE_MAX_BITS;
897 cmap_cache_size = 0x01 << (cmap_cache_bits * 3);
898 cmap_cache = (xaUSHORT *)malloc(cmap_cache_size * sizeof(xaUSHORT));
899 cmap_cache_bmask = ( (0x01 << cmap_cache_bits) - 1) << 8;
900 cmap_cache_gmask = cmap_cache_bmask << cmap_cache_bits;
901 cmap_cache_rmask = cmap_cache_gmask << cmap_cache_bits;
902 if (cmap_cache == 0) TheEnd1("CMAP_CACHE: malloc err");
903 cmap_cache_chdr = 0;
904 if (flag == 1)
905 {
906 cmap_cache2 = (xaUSHORT *)malloc(cmap_cache_size * sizeof(xaUSHORT));
907 if (cmap_cache2 == 0) TheEnd1("CMAP_CACHE: malloc err2");
908 }
909 DEBUG_LEVEL3 fprintf(stderr,"cache mask's %x %x %x\n",
910 cmap_cache_rmask,cmap_cache_gmask,cmap_cache_bmask);
911 }
912 /*
913 * Set CMAP cache to all 0xffff's. Since CMAP's are currently limited
914 * to 256 in size, this is a non-valid value.
915 */
916 void
CMAP_Cache_Clear()917 CMAP_Cache_Clear()
918 {
919 register xaUSHORT *tp;
920 register xaULONG i;
921 tp = cmap_cache; i = cmap_cache_size;
922 while(i--) *tp++ = 0xffff;
923 }
924
925
CMAP_Get_Or_Mask(cmap_size)926 xaULONG CMAP_Get_Or_Mask(cmap_size)
927 xaULONG cmap_size; /* number of colors in anim cmap */
928 {
929 xaULONG or_mask,imagec;
930
931 /* if image is getting remapped then this doesn't matter */
932 if ( (cmap_play_nice == xaTRUE)
933 || (x11_display_type & XA_X11_TRUE)
934 || (x11_display_type & XA_X11_STATIC)
935 || (x11_display_type == XA_MONOCHROME) ) return(0);
936
937
938 if (cmap_size >= x11_cmap_size) return(0); /* needs to be quant'd */
939
940 /* find largest power of 2 <= display's cmap size */
941 or_mask = 0x01;
942 while(or_mask <= x11_cmap_size) or_mask <<= 1;
943 or_mask >>=1;
944
945 /* round cmap_size up to nearest power of two */
946 imagec = 0x01;
947 while(imagec <= cmap_size) imagec <<= 1;
948 imagec >>=1;
949
950 if (imagec >= or_mask) return(0);
951 return(or_mask - imagec);
952 }
953
954
955 /*
956 *
957 * affects global variables
958 * iff_r_shift
959 * iff_g_shift
960 * iff_b_shift
961 * iff_r_mask
962 * iff_g_mask
963 * iff_b_mask
964 *
965 * Creates 332 CHDR if doesn't exist.
966 * copies cmap of 332 CHDR into given cmap.
967 * sets csize to 332 CHDR size.
968 *
969 */
CMAP_Create_332(cmap,csize)970 XA_CHDR *CMAP_Create_332(cmap,csize)
971 ColorReg *cmap;
972 xaULONG *csize;
973 {
974 xaULONG i,size;
975
976 if ( (cmap_332_chdr == 0) || (cmap_cur_gamma != cmap_332_gamma) )
977 {
978 xaULONG r_bits,g_bits,b_bits,last,disp_bits;
979 xaULONG r_scale,g_scale,b_scale;
980
981 if (x11_display_type == XA_MONOCHROME) { size = 256; disp_bits = 8; }
982 else
983 { int xsize = (x11_cmap_size > 256)?(256):(x11_cmap_size);
984 size = 0x01; disp_bits = 0;
985 while(size <= xsize) { size <<= 1; disp_bits++; }
986 size >>=1; disp_bits--;
987 }
988 r_bits = 3; g_bits = 3; b_bits = 3; last = 2;
989 while( (r_bits + g_bits + b_bits) > disp_bits)
990 {
991 switch(last)
992 {
993 case 0: g_bits--; last++; break;
994 case 1: r_bits--; last++; break;
995 default: b_bits--; last=0; break;
996 }
997 }
998 xa_b_shift = 16 - b_bits;
999 xa_b_mask = ((0x01 << b_bits) - 1) << (16 - b_bits);
1000
1001 xa_g_shift = xa_b_shift - g_bits;
1002 xa_g_mask = ((0x01 << g_bits) - 1) << (16 - g_bits);
1003
1004 xa_r_shift = xa_g_shift - r_bits;
1005 xa_r_mask = ((0x01 << r_bits) - 1) << (16 - r_bits);
1006
1007 DEBUG_LEVEL3
1008 {
1009 fprintf(stderr,"CMAP_Create_332: %d: %d %d %d\n",
1010 disp_bits,r_bits,g_bits,b_bits);
1011 fprintf(stderr,"CMAP_Create_332: masks: %x %x %x\n",
1012 xa_r_mask,xa_g_mask,xa_b_mask);
1013 fprintf(stderr,"CMAP_Create_332: shifts: %x %x %x\n",
1014 xa_r_shift,xa_g_shift,xa_b_shift);
1015 }
1016 i = r_bits + g_bits + b_bits;
1017 *csize = size = 0x01 << i;
1018
1019 r_scale = cmap_scale[r_bits];
1020 g_scale = cmap_scale[g_bits];
1021 b_scale = cmap_scale[b_bits];
1022
1023 {
1024 register xaULONG rmsk,gmsk,bmsk,rshft,gshft;
1025
1026 gshft = b_bits; rshft = b_bits + g_bits;
1027 bmsk = (0x01 << b_bits) - 1;
1028 gmsk = ((0x01 << g_bits) - 1) << gshft;
1029 rmsk = ((0x01 << r_bits) - 1) << rshft;
1030
1031 for(i=0;i<size;i++)
1032 {
1033 xaULONG r,g,b;
1034 cmap[i].red = r = ( (i & rmsk) >> rshft ) * r_scale;
1035 cmap[i].green = g = ( (i & gmsk) >> gshft ) * g_scale;
1036 cmap[i].blue = b = ( i & bmsk ) * b_scale;
1037 cmap[i].gray = ((r * 11) + (g * 16) + (b * 5)) >> 5;
1038 }
1039 }
1040 cmap_332_chdr = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
1041 cmap_332_gamma = cmap_cur_gamma;
1042 } /* end of create cmap_332_chdr */
1043 else
1044 {
1045 ColorReg *cmap332;
1046 *csize = size = cmap_332_chdr->csize;
1047 cmap332 = cmap_332_chdr->cmap;
1048 for(i=0;i<size;i++)
1049 {
1050 cmap[i].red = cmap332[i].red;
1051 cmap[i].green = cmap332[i].green;
1052 cmap[i].blue = cmap332[i].blue;
1053 cmap[i].gray = cmap332[i].gray;
1054 }
1055 }
1056 return(cmap_332_chdr);
1057 }
1058
CMAP_Create_Gray(cmap,csize)1059 XA_CHDR *CMAP_Create_Gray(cmap,csize)
1060 ColorReg *cmap;
1061 xaULONG *csize;
1062 {
1063 xaULONG i,size;
1064
1065
1066 if ( (cmap_gray_chdr == 0) || (cmap_cur_gamma != cmap_gray_gamma) )
1067 {
1068 xaULONG disp_bits;
1069 xaULONG g_scale;
1070 /* find number of bits in display or use 256 if monochrome */
1071 if (x11_display_type == XA_MONOCHROME) { disp_bits = 8; size = 256; }
1072 else
1073 { int xsize = (x11_cmap_size > 256)?(256):(x11_cmap_size);
1074 size = 0x01; disp_bits = 0;
1075 while(size <= xsize) { size <<= 1; disp_bits++; }
1076 size >>=1; disp_bits--;
1077 }
1078 xa_gray_bits = disp_bits;
1079 xa_gray_shift = 16 - disp_bits;
1080
1081 DEBUG_LEVEL3 fprintf(stderr,"Gray: bits %d shift %d\n",
1082 disp_bits,xa_gray_shift);
1083 g_scale = cmap_scale[disp_bits];
1084
1085 *csize = size;
1086 for(i=0;i<size;i++) cmap[i].red = cmap[i].green = cmap[i].blue
1087 = cmap[i].gray = i * g_scale;
1088 cmap_gray_chdr = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
1089 cmap_gray_gamma = cmap_cur_gamma;
1090 }
1091 else
1092 {
1093 *csize = size = cmap_gray_chdr->csize;
1094 for(i=0;i<size;i++) cmap[i].red = cmap[i].green = cmap[i].blue
1095 = cmap_gray_chdr->cmap[i].gray;
1096 }
1097 return(cmap_gray_chdr);
1098 }
1099
1100
1101 /*
1102 *
1103 *
1104 */
CMAP_Create_CHDR_From_True(ipic,rbits,gbits,bbits,width,height,cmap,csize)1105 XA_CHDR *CMAP_Create_CHDR_From_True(ipic,rbits,gbits,bbits,
1106 width,height,cmap,csize)
1107 xaUBYTE *ipic;
1108 xaULONG rbits,gbits,bbits;
1109 xaULONG width,height;
1110 ColorReg *cmap;
1111 xaULONG *csize;
1112 {
1113 XA_CHDR *new_chdr;
1114 xaULONG *clist,clist_len,wanted_csize;
1115 register xaULONG i,rshift,gshift,bshift;
1116
1117 /* NOTE: should make sure 2^(rbits+gbits+bbits) is < (width*height) */
1118 /* optimize for space if so */
1119
1120 if ( (rbits > 8) | (gbits > 8) | (bbits > 8) )
1121 TheEnd1("CMAP_Create_CHDR_From_True: bits > 24 err");
1122
1123 clist_len = width * height;
1124 clist = (xaULONG *) malloc( clist_len * sizeof(xaULONG) );
1125 if (clist == 0) TheEnd1("CMAP_Create_CHDR_From_True: malloc err");
1126
1127 rshift = 24 - rbits;
1128 gshift = 16 - gbits;
1129 bshift = 8 - bbits;
1130
1131 for(i=0; i < clist_len; i++)
1132 {
1133 register xaULONG r,g,b;
1134 r = (xaULONG)(*ipic++);
1135 g = (xaULONG)(*ipic++);
1136 b = (xaULONG)(*ipic++);
1137 clist[i] = (r << rshift) | (g << gshift) | (b << bshift);
1138 }
1139
1140 wanted_csize = x11_cmap_size;
1141
1142 DEBUG_LEVEL2 fprintf(stderr,"xaTRUE_CHDR: cnum = %d wanted =%d\n",
1143 clist_len,wanted_csize);
1144 CMAP_BitMask_CList(clist,clist_len,cmap_median_bits);
1145 clist_len = CMAP_Compress_CList(clist,clist_len);
1146 DEBUG_LEVEL2 fprintf(stderr,"xaTRUE_CHDR: compress cnum = %d\n",clist_len);
1147
1148 if (clist_len < wanted_csize) wanted_csize = clist_len;
1149
1150 new_chdr = ACT_Get_CHDR(1,wanted_csize,0,wanted_csize,0,xaTRUE,xaTRUE);
1151 if (clist_len > wanted_csize)
1152 {
1153 wanted_csize =
1154 CMAP_Median_Cut(new_chdr->cmap,clist,clist_len,wanted_csize);
1155 DEBUG_LEVEL2 fprintf(stderr,"xaTRUE_CHDR: median cnum = %d\n",wanted_csize);
1156 }
1157 else
1158 {
1159 wanted_csize = clist_len;
1160 CMAP_CMAP_From_Clist(new_chdr->cmap,clist,clist_len);
1161 }
1162 FREE(clist,0x204); clist=0;
1163 *csize = wanted_csize;
1164 for(i=0;i<wanted_csize;i++) cmap[i] = new_chdr->cmap[i];
1165 new_chdr->csize = wanted_csize;
1166 new_chdr->coff = x11_cmap_size - wanted_csize;
1167 new_chdr->msize = wanted_csize;
1168 new_chdr->moff = x11_cmap_size - wanted_csize;
1169 for(i=0; i<new_chdr->msize; i++) new_chdr->map[i] = i + new_chdr->moff;
1170 return(new_chdr);
1171 }
1172
CMAP_CList_CombSort(clist,cnum)1173 void CMAP_CList_CombSort(clist,cnum)
1174 xaULONG *clist,cnum;
1175 { register xaULONG ShrinkFactor,gap,i,temp,finished;
1176 ShrinkFactor = 13; gap = cnum;
1177 do
1178 { finished = 1; gap = (gap * 10) / ShrinkFactor;
1179 if (gap < 1) gap = 1;
1180 if ( (gap==9) | (gap == 10) ) gap = 11;
1181 for(i=0; i < (cnum - gap); i++)
1182 { if (clist[i] < clist[i+gap])
1183 { temp = clist[i]; clist[i] = clist[i+gap];
1184 clist[i+gap] = temp;
1185 finished = 0;
1186 }
1187 }
1188 } while( !finished || (gap > 1) );
1189 }
1190
CMAP_CList_CombSort_Red(clist,cnum)1191 void CMAP_CList_CombSort_Red(clist,cnum)
1192 xaULONG *clist,cnum;
1193 {
1194 register xaULONG ShrinkFactor,gap,i,temp,finished;
1195 ShrinkFactor = 13; gap = cnum;
1196 do
1197 { finished = 1; gap = (gap * 10) / ShrinkFactor;
1198 if (gap < 1) gap = 1;
1199 if ( (gap==9) | (gap == 10) ) gap = 11;
1200 for(i=0; i < (cnum - gap); i++)
1201 { if ( (clist[i] & 0xff0000) < (clist[i+gap] & 0xff0000) )
1202 { temp = clist[i]; clist[i] = clist[i+gap];
1203 clist[i+gap] = temp;
1204 finished = 0;
1205 }
1206 }
1207 } while( !finished || (gap > 1) );
1208 }
1209
CMAP_CList_CombSort_Green(clist,cnum)1210 void CMAP_CList_CombSort_Green(clist,cnum)
1211 xaULONG *clist,cnum;
1212 {
1213 register xaULONG ShrinkFactor,gap,i,temp,finished;
1214 ShrinkFactor = 13; gap = cnum;
1215 do
1216 { finished = 1; gap = (gap * 10) / ShrinkFactor;
1217 if (gap < 1) gap = 1;
1218 if ( (gap==9) | (gap == 10) ) gap = 11;
1219 for(i=0; i < (cnum - gap); i++)
1220 { if ( (clist[i] & 0xff00) < (clist[i+gap] & 0xff00) )
1221 { temp = clist[i]; clist[i] = clist[i+gap];
1222 clist[i+gap] = temp;
1223 finished = 0;
1224 }
1225 }
1226 } while( !finished || (gap > 1) );
1227 }
1228
CMAP_CList_CombSort_Blue(clist,cnum)1229 void CMAP_CList_CombSort_Blue(clist,cnum)
1230 xaULONG *clist,cnum;
1231 {
1232 register xaULONG ShrinkFactor,gap,i,temp,finished;
1233 ShrinkFactor = 13; gap = cnum;
1234 do
1235 { finished = 1; gap = (gap * 10) / ShrinkFactor;
1236 if (gap < 1) gap = 1;
1237 if ( (gap==9) | (gap == 10) ) gap = 11;
1238 for(i=0; i < (cnum - gap); i++)
1239 { if ( (clist[i] & 0xff) < (clist[i+gap] & 0xff) )
1240 { temp = clist[i]; clist[i] = clist[i+gap];
1241 clist[i+gap] = temp;
1242 finished = 0;
1243 }
1244 }
1245 } while( !finished || (gap > 1) );
1246 }
1247
CMAP_Gamma_Adjust(gamma_adj,disp_gamma,anim_gamma)1248 xaULONG CMAP_Gamma_Adjust(gamma_adj,disp_gamma,anim_gamma)
1249 xaUSHORT *gamma_adj;
1250 double disp_gamma,anim_gamma;
1251 {
1252 register xaULONG i;
1253 double pow(),t64k,d;
1254
1255 DEBUG_LEVEL2 fprintf(stderr,"CMAP_Gamma_Adjust\n");
1256 if (disp_gamma < GAMMA_MIN) disp_gamma = 1.0;
1257 if (anim_gamma < GAMMA_MIN) anim_gamma = 1.0;
1258
1259 cmap_cur_gamma = anim_gamma/disp_gamma;
1260 t64k = (double)(65535.0);
1261 for(i=0;i<256;i++)
1262 {
1263 d = (double)(i * 257)/t64k;
1264 gamma_adj[i] = (xaUSHORT)(0.5 + t64k * pow(d, cmap_cur_gamma));
1265 }
1266 if (disp_gamma == anim_gamma) return(xaFALSE);
1267 else return(xaTRUE);
1268 }
1269
1270 /*
1271 *
1272 * affects global variables
1273 * iff_r_shift
1274 * iff_g_shift
1275 * iff_b_shift
1276 * iff_r_mask
1277 * iff_g_mask
1278 * iff_b_mask
1279 *
1280 * Creates 422 CHDR if doesn't exist.
1281 * copies cmap of 422 CHDR into given cmap.
1282 * sets csize to 422 CHDR size.
1283 *
1284 */
CMAP_Create_422(cmap,csize)1285 XA_CHDR *CMAP_Create_422(cmap,csize)
1286 ColorReg *cmap;
1287 xaULONG *csize;
1288 {
1289 xaULONG i,size;
1290 xaULONG r_bits,g_bits,b_bits,last,disp_bits;
1291 xaULONG r_scale,g_scale,b_scale;
1292 XA_CHDR *chdr_422;
1293
1294 if (x11_display_type == XA_MONOCHROME) { size = 256; disp_bits = 8; }
1295 else
1296 {
1297 size = 0x01; disp_bits = 0;
1298 while(size <= x11_cmap_size) { size <<= 1; disp_bits++; }
1299 size >>=1; disp_bits--;
1300 }
1301 r_bits = 4; g_bits = 2; b_bits = 2; last = 0;
1302 while( (r_bits + g_bits + b_bits) > disp_bits)
1303 {
1304 switch(last)
1305 {
1306 case 0: g_bits--; last++; break;
1307 case 1: r_bits--; last++; break;
1308 default: b_bits--; last=0; break;
1309 }
1310 }
1311 xa_b_shift = 16 - b_bits;
1312 xa_b_mask = ((0x01 << b_bits) - 1) << (16 - b_bits);
1313
1314 xa_g_shift = xa_b_shift - g_bits;
1315 xa_g_mask = ((0x01 << g_bits) - 1) << (16 - g_bits);
1316
1317 xa_r_shift = xa_g_shift - r_bits;
1318 xa_r_mask = ((0x01 << r_bits) - 1) << (16 - r_bits);
1319
1320 i = r_bits + g_bits + b_bits;
1321 *csize = size = 0x01 << i;
1322
1323 r_scale = cmap_scale[r_bits];
1324 g_scale = cmap_scale[g_bits];
1325 b_scale = cmap_scale[b_bits];
1326
1327 {
1328 register xaULONG rmsk,gmsk,bmsk,rshft,gshft;
1329
1330 gshft = b_bits; rshft = b_bits + g_bits;
1331 bmsk = (0x01 << b_bits) - 1;
1332 gmsk = ((0x01 << g_bits) - 1) << gshft;
1333 rmsk = ((0x01 << r_bits) - 1) << rshft;
1334
1335 for(i=0;i<size;i++)
1336 {
1337 xaULONG r,g,b;
1338 cmap[i].red = r = ( (i & rmsk) >> rshft ) * r_scale;
1339 cmap[i].green = g = ( (i & gmsk) >> gshft ) * g_scale;
1340 cmap[i].blue = b = ( i & bmsk ) * b_scale;
1341 cmap[i].gray = ((r * 11) + (g * 16) + (b * 5)) >> 5;
1342 }
1343 }
1344 chdr_422 = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
1345 return(chdr_422);
1346 }
1347
1348
1349