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