home *** CD-ROM | disk | FTP | other *** search
/ Dream 44 / Amiga_Dream_44.iso / Linux / Apps / xanim.tgz / xanim / xanim27064 / xa_cmap.c < prev    next >
C/C++ Source or Header  |  1997-01-26  |  35KB  |  1,348 lines

  1.  
  2. /*
  3.  * xa_cmap.c
  4.  *
  5.  * Copyright (C) 1992,1993,1994,1995,1996,1997 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed without
  9.  * fee for non-commerical purposes provided that this copyright notice is
  10.  * preserved intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) 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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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
  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.  
  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.  */
  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.  
  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
  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
  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
  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
  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
  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
  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.  
  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.  
  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
  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.  
  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.  
  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.  
  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.  
  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
  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
  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.  
  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
  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
  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.  
  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.  */ 
  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.     {
  984.       size = 0x01; disp_bits = 0;
  985.       while(size <= x11_cmap_size) { 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.  
  1059. XA_CHDR *CMAP_Create_Gray(cmap,csize)
  1060. ColorReg *cmap;
  1061. xaULONG *csize;
  1062. {
  1063.   xaULONG i,size;
  1064.  
  1065.   if ( (cmap_gray_chdr == 0) || (cmap_cur_gamma != cmap_gray_gamma) )
  1066.   {
  1067.     xaULONG disp_bits;
  1068.     xaULONG g_scale;
  1069.     /* find number of bits in display or use 256 if monochrome */
  1070.     if (x11_display_type == XA_MONOCHROME) { disp_bits = 8; size = 256; }
  1071.     else
  1072.     {
  1073.       size = 0x01; disp_bits = 0;
  1074.       while(size <= x11_cmap_size) { size <<= 1; disp_bits++; }
  1075.       size >>=1; disp_bits--;
  1076.     }
  1077.     xa_gray_bits = disp_bits;
  1078.     xa_gray_shift = 16 - disp_bits;
  1079.  
  1080.     DEBUG_LEVEL3 fprintf(stderr,"Gray: bits %d shift %d\n",
  1081.                     disp_bits,xa_gray_shift);
  1082.     g_scale = cmap_scale[disp_bits];
  1083.  
  1084.     *csize = size;
  1085.     for(i=0;i<size;i++) cmap[i].red = cmap[i].green = cmap[i].blue
  1086.       = cmap[i].gray = i * g_scale;
  1087.     cmap_gray_chdr = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
  1088.     cmap_gray_gamma = cmap_cur_gamma;
  1089.   }
  1090.   else
  1091.   {
  1092.     *csize = size = cmap_gray_chdr->csize;
  1093.     for(i=0;i<size;i++) cmap[i].red = cmap[i].green = cmap[i].blue
  1094.       = cmap_gray_chdr->cmap[i].gray;
  1095.   }
  1096.   return(cmap_gray_chdr);
  1097. }
  1098.  
  1099.  
  1100. /*
  1101.  *
  1102.  *
  1103.  */
  1104. XA_CHDR *CMAP_Create_CHDR_From_True(ipic,rbits,gbits,bbits,
  1105.                         width,height,cmap,csize)
  1106. xaUBYTE *ipic;
  1107. xaULONG rbits,gbits,bbits;
  1108. xaULONG width,height;
  1109. ColorReg *cmap;
  1110. xaULONG *csize;
  1111. {
  1112.   XA_CHDR *new_chdr;
  1113.   xaULONG *clist,clist_len,wanted_csize;
  1114.   register xaULONG i,rshift,gshift,bshift;
  1115.  
  1116. /* NOTE: should make sure 2^(rbits+gbits+bbits) is < (width*height) */
  1117. /* optimize for space if so */
  1118.  
  1119.   if ( (rbits > 8) | (gbits > 8) | (bbits > 8) )
  1120.         TheEnd1("CMAP_Create_CHDR_From_True: bits > 24 err");
  1121.  
  1122.   clist_len = width * height;
  1123.   clist = (xaULONG *) malloc( clist_len * sizeof(xaULONG) );
  1124.   if (clist == 0) TheEnd1("CMAP_Create_CHDR_From_True: malloc err");
  1125.  
  1126.   rshift = 24 - rbits;
  1127.   gshift = 16 - gbits;
  1128.   bshift = 8  - bbits;
  1129.  
  1130.   for(i=0; i < clist_len; i++)
  1131.   {
  1132.     register xaULONG r,g,b;
  1133.     r = (xaULONG)(*ipic++);
  1134.     g = (xaULONG)(*ipic++);
  1135.     b = (xaULONG)(*ipic++);
  1136.     clist[i] = (r << rshift) | (g << gshift) | (b << bshift); 
  1137.   }
  1138.  
  1139.   wanted_csize = x11_cmap_size;
  1140.  
  1141.   DEBUG_LEVEL2 fprintf(stderr,"xaTRUE_CHDR: cnum = %d wanted =%d\n",
  1142.                 clist_len,wanted_csize);
  1143.   CMAP_BitMask_CList(clist,clist_len,cmap_median_bits);
  1144.   clist_len = CMAP_Compress_CList(clist,clist_len);
  1145.   DEBUG_LEVEL2 fprintf(stderr,"xaTRUE_CHDR: compress cnum = %d\n",clist_len);
  1146.  
  1147.   if (clist_len < wanted_csize) wanted_csize = clist_len;
  1148.  
  1149.   new_chdr = ACT_Get_CHDR(1,wanted_csize,0,wanted_csize,0,xaTRUE,xaTRUE);
  1150.   if (clist_len > wanted_csize)
  1151.   {
  1152.     wanted_csize = 
  1153.     CMAP_Median_Cut(new_chdr->cmap,clist,clist_len,wanted_csize);
  1154.   DEBUG_LEVEL2 fprintf(stderr,"xaTRUE_CHDR: median cnum = %d\n",wanted_csize);
  1155.   }
  1156.   else
  1157.   {
  1158.     wanted_csize = clist_len;
  1159.     CMAP_CMAP_From_Clist(new_chdr->cmap,clist,clist_len);
  1160.   }
  1161.   FREE(clist,0x204); clist=0;
  1162.   *csize = wanted_csize;
  1163.   for(i=0;i<wanted_csize;i++) cmap[i] = new_chdr->cmap[i]; 
  1164.   new_chdr->csize = wanted_csize;
  1165.   new_chdr->coff  = x11_cmap_size - wanted_csize;
  1166.   new_chdr->msize = wanted_csize;
  1167.   new_chdr->moff  = x11_cmap_size - wanted_csize;
  1168.   for(i=0; i<new_chdr->msize; i++) new_chdr->map[i] = i + new_chdr->moff;
  1169.   return(new_chdr);
  1170. }
  1171.  
  1172. void CMAP_CList_CombSort(clist,cnum)
  1173. xaULONG *clist,cnum;
  1174. { register xaULONG ShrinkFactor,gap,i,temp,finished;
  1175.   ShrinkFactor = 13; gap = cnum;
  1176.   do
  1177.   { finished = 1; gap = (gap * 10) / ShrinkFactor;
  1178.     if (gap < 1) gap = 1;
  1179.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1180.     for(i=0; i < (cnum - gap); i++)
  1181.     { if (clist[i] < clist[i+gap])
  1182.       { temp = clist[i]; clist[i] = clist[i+gap];
  1183.         clist[i+gap] = temp;
  1184.         finished = 0;
  1185.       }
  1186.     }
  1187.   } while( !finished ||  (gap > 1) );
  1188. }
  1189.  
  1190. void CMAP_CList_CombSort_Red(clist,cnum)
  1191. xaULONG *clist,cnum;
  1192. {
  1193.   register xaULONG ShrinkFactor,gap,i,temp,finished;
  1194.   ShrinkFactor = 13; gap = cnum;
  1195.   do
  1196.   { finished = 1; gap = (gap * 10) / ShrinkFactor;
  1197.     if (gap < 1) gap = 1;
  1198.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1199.     for(i=0; i < (cnum - gap); i++)
  1200.     { if ( (clist[i] & 0xff0000) < (clist[i+gap] & 0xff0000) )
  1201.       { temp = clist[i]; clist[i] = clist[i+gap];
  1202.         clist[i+gap] = temp;
  1203.         finished = 0;
  1204.       }
  1205.     }
  1206.   } while( !finished ||  (gap > 1) );
  1207. }
  1208.  
  1209. void CMAP_CList_CombSort_Green(clist,cnum)
  1210. xaULONG *clist,cnum;
  1211. {
  1212.   register xaULONG ShrinkFactor,gap,i,temp,finished;
  1213.   ShrinkFactor = 13; gap = cnum;
  1214.   do
  1215.   { finished = 1; gap = (gap * 10) / ShrinkFactor;
  1216.     if (gap < 1) gap = 1;
  1217.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1218.     for(i=0; i < (cnum - gap); i++)
  1219.     { if ( (clist[i] & 0xff00) < (clist[i+gap] & 0xff00) )
  1220.       { temp = clist[i]; clist[i] = clist[i+gap];
  1221.         clist[i+gap] = temp;
  1222.         finished = 0;
  1223.       }
  1224.     }
  1225.   } while( !finished ||  (gap > 1) );
  1226. }
  1227.  
  1228. void CMAP_CList_CombSort_Blue(clist,cnum)
  1229. xaULONG *clist,cnum;
  1230. {
  1231.   register xaULONG ShrinkFactor,gap,i,temp,finished;
  1232.   ShrinkFactor = 13; gap = cnum;
  1233.   do
  1234.   { finished = 1; gap = (gap * 10) / ShrinkFactor;
  1235.     if (gap < 1) gap = 1;
  1236.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1237.     for(i=0; i < (cnum - gap); i++)
  1238.     { if ( (clist[i] & 0xff) < (clist[i+gap] & 0xff) )
  1239.       { temp = clist[i]; clist[i] = clist[i+gap];
  1240.         clist[i+gap] = temp;
  1241.         finished = 0;
  1242.       }
  1243.     }
  1244.   } while( !finished ||  (gap > 1) );
  1245. }
  1246.  
  1247. xaULONG CMAP_Gamma_Adjust(gamma_adj,disp_gamma,anim_gamma)
  1248. xaUSHORT *gamma_adj;
  1249. double disp_gamma,anim_gamma;
  1250. {
  1251.   register xaULONG i;
  1252.   double pow(),t64k,d;
  1253.  
  1254.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Gamma_Adjust\n");
  1255.   if (disp_gamma < GAMMA_MIN) disp_gamma = 1.0;
  1256.   if (anim_gamma < GAMMA_MIN) anim_gamma = 1.0;
  1257.  
  1258.   cmap_cur_gamma = anim_gamma/disp_gamma;
  1259.   t64k = (double)(65535.0);
  1260.   for(i=0;i<256;i++)
  1261.   {
  1262.     d = (double)(i * 257)/t64k;
  1263.     gamma_adj[i] = (xaUSHORT)(0.5 + t64k * pow(d, cmap_cur_gamma));
  1264.   }
  1265.   if (disp_gamma == anim_gamma) return(xaFALSE);
  1266.   else return(xaTRUE);
  1267. }
  1268.  
  1269. /*
  1270.  *
  1271.  * affects global variables                            
  1272.  *   iff_r_shift
  1273.  *   iff_g_shift 
  1274.  *   iff_b_shift
  1275.  *   iff_r_mask 
  1276.  *   iff_g_mask 
  1277.  *   iff_b_mask
  1278.  *
  1279.  *   Creates 422 CHDR if doesn't exist.
  1280.  *   copies cmap of 422 CHDR into given cmap.
  1281.  *   sets csize to 422 CHDR size.
  1282.  *
  1283.  */ 
  1284. XA_CHDR *CMAP_Create_422(cmap,csize)
  1285. ColorReg *cmap;
  1286. xaULONG *csize;
  1287. {
  1288.   xaULONG i,size;
  1289.   xaULONG r_bits,g_bits,b_bits,last,disp_bits;
  1290.   xaULONG r_scale,g_scale,b_scale;
  1291.   XA_CHDR *chdr_422; 
  1292.  
  1293.     if (x11_display_type == XA_MONOCHROME) { size = 256; disp_bits = 8; }
  1294.     else
  1295.     {
  1296.       size = 0x01; disp_bits = 0;
  1297.       while(size <= x11_cmap_size) { size <<= 1; disp_bits++; }
  1298.       size >>=1; disp_bits--;
  1299.     }
  1300.     r_bits = 4; g_bits = 2; b_bits = 2; last = 0;
  1301.     while( (r_bits + g_bits + b_bits) > disp_bits)
  1302.     {
  1303.       switch(last)
  1304.       {
  1305.         case 0:  g_bits--; last++; break;
  1306.         case 1:  r_bits--; last++; break;
  1307.         default: b_bits--; last=0; break;
  1308.       }
  1309.     }
  1310.     xa_b_shift = 16 - b_bits;
  1311.     xa_b_mask = ((0x01 << b_bits) - 1) << (16 - b_bits);
  1312.  
  1313.     xa_g_shift = xa_b_shift - g_bits;
  1314.     xa_g_mask = ((0x01 << g_bits) - 1) << (16 - g_bits);
  1315.  
  1316.     xa_r_shift = xa_g_shift - r_bits;
  1317.     xa_r_mask = ((0x01 << r_bits) - 1) << (16 - r_bits);
  1318.  
  1319.     i = r_bits + g_bits + b_bits;
  1320.     *csize = size = 0x01 << i;
  1321.  
  1322.     r_scale = cmap_scale[r_bits];
  1323.     g_scale = cmap_scale[g_bits];
  1324.     b_scale = cmap_scale[b_bits];
  1325.  
  1326.     {
  1327.       register xaULONG rmsk,gmsk,bmsk,rshft,gshft;
  1328.  
  1329.       gshft = b_bits;     rshft = b_bits + g_bits;
  1330.       bmsk =  (0x01 << b_bits) - 1;
  1331.       gmsk = ((0x01 << g_bits) - 1) << gshft;
  1332.       rmsk = ((0x01 << r_bits) - 1) << rshft;
  1333.  
  1334.       for(i=0;i<size;i++)
  1335.       {
  1336.         xaULONG r,g,b;
  1337.         cmap[i].red   = r = ( (i & rmsk) >> rshft ) * r_scale;
  1338.         cmap[i].green = g = ( (i & gmsk) >> gshft ) * g_scale;
  1339.         cmap[i].blue  = b = (  i & bmsk           ) * b_scale;
  1340.         cmap[i].gray = ((r * 11) + (g * 16) + (b * 5)) >> 5;
  1341.       }
  1342.     }
  1343.     chdr_422 = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
  1344.   return(chdr_422);
  1345. }
  1346.  
  1347.  
  1348.