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

  1.  
  2. /*
  3.  * xa_utils.c
  4.  *
  5.  * Copyright (C) 1991,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. /* revhist
  19.  * 12dec94  +bCdm caused core on Alpha OSF/1 v3.0. 
  20.  *           found and fixed by David Mosberger-Tang.
  21.  *
  22.  */ 
  23. #include "xanim.h"
  24.  
  25. void UTIL_Sub_Image();
  26. void UTIL_Create_Clip();
  27. void UTIL_Mapped_To_Mapped();
  28. void UTIL_Mapped_To_Bitmap();
  29. xaULONG UTIL_Get_Buffer_Scale();
  30. void UTIL_Scale_Buffer_Pos();
  31. void UTIL_Scale_Pos_Size();
  32. xaUBYTE *UTIL_Alloc_Scaled();
  33. xaUBYTE *UTIL_Scale_Mapped();
  34. xaUBYTE *UTIL_Scale_Bitmap();
  35. void UTIL_Pack_Image();
  36. void UTIL_FPS_2_Time();
  37.  
  38. xaULONG UTIL_Get_LSB_Long();
  39. xaULONG UTIL_Get_LSB_Short();
  40. xaULONG UTIL_Get_MSB_Long();
  41. xaULONG UTIL_Get_MSB_UShort();
  42. xaLONG UTIL_Get_MSB_Short();
  43. void UTIL_Mapped_To_Floyd();
  44. xaULONG CMAP_Find_Closest();
  45. void CMAP_Cache_Init();
  46. void CMAP_Cache_Clear();
  47.  
  48. extern xaULONG *xa_scale_row_buff;
  49. extern xaULONG xa_scale_row_size;
  50. extern char *xa_scale_buff;
  51. extern xaULONG xa_scale_buff_size;
  52. extern xaLONG xa_dither_flag;
  53. extern xaULONG xa_buff_x,xa_buff_y;
  54. extern float xa_bscalex,xa_bscaley;
  55.  
  56.  
  57. void
  58. UTIL_Sub_Image(out,in,xosize,yosize,xipos,yipos,xisize,pix_size)
  59. xaUBYTE *out,*in;
  60. xaULONG xosize,yosize,xipos,yipos,xisize,pix_size;
  61. {
  62.   xaULONG y,x;
  63.   xaUBYTE *in_ptr;
  64.   xosize *= pix_size;
  65.   xisize *= pix_size;
  66.   xipos  *= pix_size;
  67.   for(y=yipos; y < (yipos + yosize); y++)
  68.   {
  69.     in_ptr = (xaUBYTE *)(in + (y * xisize + xipos));
  70.     x = xosize;
  71.     while(x--) *out++ = *in_ptr++;
  72.   } 
  73. }
  74.  
  75. void
  76. UTIL_Mapped_To_Mapped(out,in,chdr,xipos,yipos,xosize,yosize,xisize,yisize)
  77. xaUBYTE *out;        /* output image - maybe the same as input image */
  78. xaUBYTE *in;        /* input image */
  79. XA_CHDR *chdr;        /* color header to remap to */
  80. xaULONG xipos,yipos;    /* pos of section in input buffer */
  81. xaULONG xosize,yosize;    /* size of section in input buffer */
  82. xaULONG xisize,yisize;    /* size of input buffer */
  83. {
  84.   xaULONG *map,moff;
  85.   xaULONG y,x;
  86.   xaUBYTE *in_ptr;
  87.  
  88.   map = chdr->map;
  89.   moff = chdr->moff;
  90.   switch(x11_bytes_pixel)
  91.   {
  92.    case 4: /* start from backside to allow for when out = in */
  93.     {
  94.       xaULONG *ulp;
  95.       for(y=yosize; y > 0; y--)
  96.       {
  97.         in_ptr = (xaUBYTE *)(in + (y + yipos - 1) * xisize 
  98.                         + xipos + xosize - 1 );
  99.         ulp =    (xaULONG *)(out + ((4 * y * xosize) - 4));
  100.         x = xosize;
  101.         if (moff) while(x--) *ulp-- = map[(*in_ptr--)-moff];
  102.         else while(x--) *ulp-- = map[*in_ptr--];
  103.       }
  104.     }
  105.     break;
  106.    case 2: /* start from backside to allow for when out = in */
  107.     {
  108.       xaUSHORT *usp;
  109.       for(y=yosize; y > 0; y--)
  110.       {
  111.         in_ptr = (xaUBYTE *)(in + (y + yipos - 1) * xisize 
  112.                         + xipos + xosize - 1 );
  113.         usp =    (xaUSHORT *)(out + ((2 * y * xosize) - 2));
  114.         x = xosize;
  115.         if (moff) while(x--) *usp-- = (xaUSHORT)map[(*in_ptr--)-moff];
  116.         else while(x--) *usp-- = (xaUSHORT)map[*in_ptr--];
  117.       }
  118.     }
  119.     break;
  120.    case 1:
  121.     {
  122.       for(y=yipos; y < (yipos + yosize); y++)
  123.       {
  124.         in_ptr = (xaUBYTE *)(in + y * xisize + xipos);
  125.         x = xosize;
  126.         if (moff) while(x--) *out++ = (xaUBYTE)(map[(*in_ptr++)-moff]);
  127.         else while(x--) *out++ = (xaUBYTE)(map[*in_ptr++]);
  128.       }
  129.     }
  130.     break;
  131.   } /* end switch */ 
  132. }
  133.  
  134. void
  135. UTIL_Create_Clip(out,in,pix_mask,xsize,ysize,pix_size,xosize,bit_order)
  136. xaUBYTE *out,*in;
  137. xaULONG pix_mask,xsize,ysize,pix_size,xosize,bit_order;
  138. {
  139.   register xaULONG data_in,bit_mask,x,y,mask_start,mask_end;
  140.   register xaUBYTE data_out;
  141.  
  142.   if (bit_order == X11_MSB) { mask_start = 0x80; mask_end = 0x01; }
  143.   else { mask_start = 0x01; mask_end = 0x80; }
  144.  
  145.   for(y=0; y<ysize; y++)
  146.   {
  147.     bit_mask = mask_start;
  148.     data_out = 0;
  149.     for(x=0; x < xosize; x++)
  150.     {
  151.       if (x < xsize)
  152.       {
  153.         if (pix_size == 4) 
  154.       { xaULONG *ulp = (xaULONG *)in;    data_in = *ulp; }
  155.         else if (pix_size == 2)
  156.       { xaUSHORT *usp = (xaUSHORT *)in;    data_in = (xaULONG)(*usp); }
  157.         else                data_in = (xaULONG)(*in);
  158.         in += pix_size;
  159.         if (data_in != pix_mask) data_out |= bit_mask;
  160.       }
  161.  
  162.       if (bit_mask == mask_end)
  163.       {
  164.         *out++ = data_out;
  165.         bit_mask = mask_start;
  166.     data_out = 0;
  167.       }
  168.       else if (mask_start == 0x01) bit_mask <<= 1;
  169.            else bit_mask >>= 1;
  170.     } /* end of for x */
  171.     if (bit_mask != mask_start) *out++ = data_out;
  172.   } /* end of for y */
  173. }
  174.  
  175. void
  176. UTIL_Mapped_To_Bitmap(out,in,chdr,xpos,ypos,xsize,ysize,width,height,line_size)
  177. xaUBYTE *out;        /* output buffer */
  178. xaUBYTE *in;        /* input buffer */
  179. XA_CHDR *chdr;        /* Color Hdr to use */
  180. xaULONG xpos,ypos;    /* pos of section in input buffer */
  181. xaULONG xsize, ysize;    /* size of section in input buffer */
  182. xaULONG width, height;    /* size of buffer */
  183. xaULONG line_size;    /* size if bytes of input buffer */
  184. {
  185.   xaULONG y,flag,csize;
  186.   ColorReg *cmap;
  187.   register xaULONG mask,invert,x,mask_start,mask_end;
  188.   xaSHORT *imap,*c_ptr,*n_ptr,*err_buff,err,threshold;
  189.   xaUBYTE data,*o_ptr;
  190.   
  191.   csize = chdr->csize;
  192.   cmap = chdr->cmap;
  193.  
  194.   err_buff = (xaSHORT *)malloc(xsize * 2 * sizeof(xaSHORT));
  195.   imap     = (xaSHORT *)malloc(csize * sizeof(xaSHORT));
  196.  
  197.    /* shift gray down to 8 bits */
  198.   for(x=0; x<csize; x++) imap[x] = cmap[x].gray >> 8;
  199.  
  200.   for(x = 0; x < xsize; x++) err_buff[x] = (xaUSHORT)imap[ *in++ ];
  201.   flag = 0;
  202.  
  203.   /* used to invert image */
  204.   if (x11_white & 0x01) invert = 0x00;
  205.   else invert = ~0x00;
  206.   threshold = 128;
  207.  
  208.   if (x11_bit_order == X11_MSB) { mask_start = 0x80; mask_end = 0x01; }
  209.   else { mask_start = 0x01; mask_end = 0x80; }
  210.  
  211.   for(y = 0; y < ysize; y++)
  212.   {
  213.     o_ptr = (xaUBYTE *)(out + (line_size * y));
  214.     /* double buffer error arrays */
  215.     n_ptr = c_ptr = err_buff;
  216.     if (flag == 0) { n_ptr += xsize; flag = 1; }
  217.     else { c_ptr += xsize; flag = 0;
  218.     }
  219.     data = 0x00;
  220.     mask = mask_start;
  221.     if (y < (ysize - 1) )  n_ptr[0] = (xaUSHORT)imap[ *in++ ];
  222.  
  223.     for(x=0; x<xsize; x++)
  224.     {
  225.       if (*c_ptr >= threshold) { err = *c_ptr - 255; data |= mask; } 
  226.       else  err = *c_ptr;
  227.  
  228.       if (mask == mask_end) 
  229.     { *o_ptr++ = data^invert; data = 0x00; mask = mask_start; }
  230.       else if (mask_start == 0x80) mask >>= 1;
  231.            else mask <<= 1;
  232.       c_ptr++;
  233.  
  234.       if (xa_dither_flag == xaFALSE)
  235.       {
  236.         if (x < (xsize - 1) ) *n_ptr++ = imap[ *in++ ];
  237.       }
  238.       else
  239.       {
  240.         if (x < (xsize - 1) )  *c_ptr += (7 * err)/16;
  241.         if (y < (ysize - 1) )
  242.         {
  243.           if (x > 0) *n_ptr++ += (3 * err)/16;
  244.           *n_ptr++ += (5 * err)/16;
  245.           if (x < (xsize - 1) ) 
  246.           { *n_ptr = (xaUSHORT)(imap[*in++]) + (xaSHORT)(err/16); n_ptr--; }
  247.         }
  248.       }
  249.     }
  250.     if (mask != mask_start) *o_ptr++ = data^invert; /* send out partial */
  251.  
  252.   }
  253.   FREE(err_buff,0x300); err_buff=0;
  254.   FREE(imap,0x301); imap=0;
  255. }
  256.  
  257. /* Routine to read a little endian long word.
  258.  */
  259. xaULONG UTIL_Get_LSB_Long(fp)
  260. FILE *fp;
  261. {
  262.  xaULONG ret;
  263.  
  264.  ret =  fgetc(fp);
  265.  ret |= fgetc(fp) << 8;
  266.  ret |= fgetc(fp) << 16;
  267.  ret |= fgetc(fp) << 24;
  268.  return ret;
  269. }
  270.  
  271. /* Routine to read a little endian half word.
  272.  */
  273. xaULONG UTIL_Get_LSB_Short(fp)
  274. FILE *fp;
  275. {
  276.  xaULONG ret;
  277.  
  278.  ret =  fgetc(fp);
  279.  ret |= fgetc(fp) << 8;
  280.  return ret;
  281. }
  282.  
  283. /* Routine to read a big endian long word.
  284.  */
  285. xaULONG UTIL_Get_MSB_Long(fp)
  286. FILE *fp;
  287. {
  288.  xaULONG ret;
  289.  
  290.  ret  = fgetc(fp) << 24;
  291.  ret |= fgetc(fp) << 16;
  292.  ret |= fgetc(fp) << 8;
  293.  ret |=  fgetc(fp);
  294.  return ret;
  295. }
  296.  
  297. /* Routine to read a big endian half word.
  298.  */
  299. xaLONG UTIL_Get_MSB_Short(fp)
  300. FILE *fp;
  301. {
  302.  xaLONG ret;
  303.  xaSHORT tmp;
  304.  
  305.  tmp  =  fgetc(fp) << 8;
  306.  tmp |=  fgetc(fp);
  307.  ret = tmp;
  308.  return ret;
  309. }
  310.  
  311. /* 
  312.  * Routine to read a big endian half word.
  313.  */
  314. xaULONG UTIL_Get_MSB_UShort(fp)
  315. FILE *fp;
  316. {
  317.  xaULONG ret;
  318.  
  319.  ret  =  fgetc(fp) << 8;
  320.  ret |=  fgetc(fp);
  321.  return ret;
  322. }
  323.  
  324. /*
  325.  *
  326.  */
  327. void UTIL_Mapped_To_Floyd(out,in,chdr_out,chdr_in,
  328.         xipos,yipos,xosize,yosize,xisize,yisize)
  329. xaUBYTE *out;        /* output (size of section) */
  330. xaUBYTE *in;        /* input image */
  331. XA_CHDR *chdr_out;    /* chdr to map to */
  332. XA_CHDR *chdr_in;    /* input images chdr */
  333. xaULONG xipos,yipos;    /* section position within input buffer */
  334. xaULONG xosize, yosize;    /* section size */
  335. xaULONG xisize, yisize;    /* input buffer size */
  336. {
  337.   xaULONG flag,csize_out,cflag;
  338.   ColorReg *cmap_in,*cmap_out;
  339.   register xaULONG x,y;
  340.   xaULONG shift_r,shift_g,shift_b,coff_out;
  341.   xaSHORT *err_buff0, *err_buff1, *e_ptr, *ne_ptr;
  342.   xaSHORT r_err,g_err,b_err;
  343.   xaUBYTE *o_ptr;
  344.  
  345.   cflag = (x11_display_type & XA_X11_COLOR)?xaTRUE:xaFALSE;
  346.  
  347.   if (!(x11_display_type & XA_X11_TRUE))
  348.   {
  349.     if (cmap_cache == 0) CMAP_Cache_Init(0);
  350.     if (chdr_out != cmap_cache_chdr)
  351.     {
  352.       DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %x\n",(xaULONG)chdr_out);
  353.       CMAP_Cache_Clear();
  354.       cmap_cache_chdr = chdr_out;
  355.     }
  356.     shift_r = 3 * cmap_cache_bits;
  357.     shift_g = 2 * cmap_cache_bits;
  358.     shift_b = cmap_cache_bits;
  359.   }
  360.   
  361.   csize_out = chdr_out->csize;
  362.   cmap_out = chdr_out->cmap;
  363.   coff_out = chdr_out->coff;
  364.  
  365.   /* allocate error buffer and set up pointers */
  366.   e_ptr = err_buff1 = err_buff0 = (xaSHORT *)malloc(6 * xosize * sizeof(xaSHORT));
  367.   if (err_buff0 == 0) TheEnd1("UTIL_Mapped_To_Floyd: malloc err");
  368.   err_buff1 = &err_buff0[(3 * xosize)]; /* POD verify */
  369.   flag = 0;
  370.  
  371.   { /* POD NOTE: only do this with different cmaps */
  372.     register xaULONG i,moff,msize,mcoff;
  373.     moff = chdr_in->moff;
  374.     mcoff = moff - chdr_in->coff;
  375.     msize = chdr_in->msize;
  376.     cmap_in = (ColorReg *)malloc((moff + msize) * sizeof(ColorReg));
  377.     for(i=0; i<msize; i++)
  378.     {
  379.       cmap_in[i + moff].red   = chdr_in->cmap[i + mcoff].red >> 8;
  380.       cmap_in[i + moff].green = chdr_in->cmap[i + mcoff].green >> 8;
  381.       cmap_in[i + moff].blue  = chdr_in->cmap[i + mcoff].blue >> 8;
  382.       cmap_in[i + moff].gray  = chdr_in->cmap[i + mcoff].gray >> 8;
  383.     }
  384.   }
  385.   {
  386.     register xaUBYTE *i_ptr = (xaUBYTE *)(in + (xisize * (yosize-1+yipos) + xipos));
  387.     x = xosize; while(x--)
  388.     {
  389.       register xaULONG p = *i_ptr++;
  390.       *e_ptr++ = (xaUSHORT)cmap_in[ p ].red   << 4;
  391.       *e_ptr++ = (xaUSHORT)cmap_in[ p ].green << 4;
  392.       *e_ptr++ = (xaUSHORT)cmap_in[ p ].blue  << 4;
  393.     }
  394.   }
  395.  
  396.   y = yosize; while(y--)
  397.   {
  398.     o_ptr = (xaUBYTE *)(out + (xosize * y * x11_bytes_pixel));
  399.     if (flag) { e_ptr = err_buff1; ne_ptr = err_buff0; flag = 0; }
  400.     else      { e_ptr = err_buff0; ne_ptr = err_buff1; flag = 1; }
  401.     if (y > 0)
  402.     {
  403.       register xaSHORT *tptr = ne_ptr;
  404.       register xaUBYTE *i_ptr = (xaUBYTE *)(in + (xisize * (y-1+yipos) + xipos));
  405.       x = xosize; while(x--)
  406.       {
  407.     register xaULONG p = *i_ptr++;
  408.     *tptr++ = (xaUSHORT)cmap_in[ p ].red   << 4;
  409.     *tptr++ = (xaUSHORT)cmap_in[ p ].green << 4;
  410.     *tptr++ = (xaUSHORT)cmap_in[ p ].blue  << 4;
  411.       }
  412.     }
  413.  
  414.     x = xosize; while(x--)
  415.     {
  416.       xaULONG color_out,pix_out;
  417.       register xaSHORT r,g,b;
  418.  
  419.       r = (*e_ptr++)/16; if (r<0) r = 0; else if (r>255) r = 255;
  420.       g = (*e_ptr++)/16; if (g<0) g = 0; else if (g>255) g = 255;
  421.       b = (*e_ptr++)/16; if (b<0) b = 0; else if (b>255) b = 255;
  422.      
  423.       if (x11_display_type & XA_X11_TRUE)
  424.       {
  425.     xaULONG tr,tg,tb;
  426.     pix_out = X11_Get_True_Color(r,g,b,8);
  427.     tr = ((pix_out & x11_red_mask)   >> x11_red_shift);
  428.     tg = ((pix_out & x11_green_mask) >> x11_green_shift);
  429.     tb = ((pix_out & x11_blue_mask)  >> x11_blue_shift);
  430.     r_err = r - (xaSHORT)(cmap_out[tr].red >> 8);
  431.     g_err = g - (xaSHORT)(cmap_out[tg].green >> 8);
  432.     b_err = b - (xaSHORT)(cmap_out[tb].blue >> 8);
  433.       }
  434.       else
  435.       {
  436.         register xaULONG cache_i;
  437.         cache_i = (  ( (r << shift_r) & cmap_cache_rmask)
  438.                    | ( (g << shift_g) & cmap_cache_gmask)
  439.                    | ( (b << shift_b) & cmap_cache_bmask) ) >> 8;
  440.     if (cmap_cache[cache_i] == 0xffff)
  441.     {
  442.       color_out = CMAP_Find_Closest(cmap_out,csize_out,r,g,b,8,8,8,cflag);
  443.       cmap_cache[cache_i] = (xaSHORT)color_out;
  444.     }
  445.     else color_out = (xaULONG)cmap_cache[cache_i];
  446.     pix_out = color_out + coff_out;
  447.         r_err = r - (xaSHORT)(cmap_out[color_out].red >> 8);
  448.         g_err = g - (xaSHORT)(cmap_out[color_out].green >> 8);
  449.         b_err = b - (xaSHORT)(cmap_out[color_out].blue >> 8);
  450.       }
  451.  
  452.       if (x11_bytes_pixel == 1) *o_ptr++ = (xaUBYTE)pix_out;
  453.       else if (x11_bytes_pixel == 2)
  454.       { xaUSHORT *so_ptr = (xaUSHORT *)(o_ptr);
  455.         *so_ptr = (xaUSHORT)pix_out; o_ptr +=2; }
  456.       else { xaULONG *lo_ptr = (xaULONG *)(o_ptr);
  457.              *lo_ptr = (xaULONG)pix_out; o_ptr +=4; }
  458.  
  459.       if (x)
  460.       {
  461.     *e_ptr   += 7 * r_err;
  462.     e_ptr[1] += 7 * g_err;
  463.     e_ptr[2] += 7 * b_err;
  464.       }
  465.       if (y)
  466.       {
  467.         if (x < (xosize-1) ) /* not 1st of line */
  468.     {
  469.       *ne_ptr++ += 3 * r_err;
  470.       *ne_ptr++ += 3 * g_err;
  471.       *ne_ptr++ += 3 * b_err;
  472.     }
  473.         *ne_ptr   += 5 * r_err;
  474.         ne_ptr[1] += 5 * g_err;
  475.         ne_ptr[2] += 5 * b_err;
  476.         if (x)
  477.         {
  478.       ne_ptr[3] += r_err;
  479.       ne_ptr[4] += g_err;
  480.       ne_ptr[5] += b_err;
  481.     }
  482.       }
  483.     } /* end of x */
  484.   } /* end of y */
  485.   if (err_buff0) FREE(err_buff0,0x302);
  486.   if (cmap_in) FREE(cmap_in,0x303);
  487.   err_buff0 = 0; cmap_in = 0;
  488. }
  489.  
  490. /*
  491.  * Function to Scale <x,y> positions and sizes
  492.  *
  493.  */
  494.  
  495. void
  496. UTIL_Scale_Pos_Size(xpos,ypos,xsize,ysize,xi_scale,yi_scale,
  497.                     xo_scale,yo_scale)
  498. xaLONG *xpos,*ypos;     /* input/output positions */
  499. xaLONG *xsize,*ysize;     /* input/output sizes */
  500. xaLONG xi_scale,yi_scale; /* input scale/image size */
  501. xaLONG xo_scale,yo_scale; /* output scale/image size */
  502. {
  503.   xaLONG ixp,iyp,oxp,oyp;
  504.   xaLONG ixsize,iysize,oxsize,oysize;
  505.  
  506.   ixp = *xpos;      iyp = *ypos;
  507.   ixsize = *xsize;  iysize = *ysize;
  508.  
  509.   oxp = (ixp * xo_scale) / xi_scale;
  510.   if ( ((oxp * xi_scale) / xo_scale) < ixp ) oxp++;
  511.   oxsize = (((ixp + ixsize) * xo_scale) / xi_scale) + 1 - oxp;
  512.   if ( (((oxp+oxsize-1) * xi_scale) / xo_scale) >= (ixp+ixsize) ) oxsize--;
  513.  
  514.   oyp = (iyp * yo_scale) / yi_scale;
  515.   if ( ((oyp * yi_scale) / yo_scale) < iyp ) oyp++;
  516.   oysize = (((iyp + iysize) * yo_scale) / yi_scale) + 1 - oyp;
  517.   if ( (((oyp+oysize-1) * yi_scale) / yo_scale) >= (iyp+iysize) ) oysize--;
  518.  
  519.   *xpos = oxp;        *ypos = oyp;
  520.   *xsize = oxsize;    *ysize = oysize;
  521. }
  522.  
  523.  
  524. /*
  525.  * Function to Scale <x,y> positions
  526.  *
  527.  *  new <x,y> positions returned in xopos,yopos;
  528.  */
  529.  
  530. void
  531. UTIL_Scale_Buffer_Pos(xpos,ypos,xi_scale,yi_scale,
  532.                     xo_scale,yo_scale)
  533. xaLONG *xpos,*ypos;     /* input/output positions */
  534. xaLONG xi_scale,yi_scale; /* input scale/image size */
  535. xaLONG xo_scale,yo_scale; /* output scale/image size */
  536. {
  537.   xaLONG ixp,iyp,oxp,oyp;
  538.  
  539.   ixp = *xpos; iyp = *ypos;
  540.  
  541.   oxp = (ixp * xo_scale) / xi_scale;
  542.   if ( ((oxp * xi_scale) / xo_scale) < ixp ) oxp++;
  543.  
  544.   oyp = (iyp * yo_scale) / yi_scale;
  545.   if ( ((oyp * yi_scale) / yo_scale) < iyp ) oyp++;
  546.  
  547.   *xpos = oxp;        *ypos = oyp;
  548. }
  549.  
  550.  
  551. /*
  552.  * Function to get Scaling Buffer Coordinates.
  553.  *     returns xaTRUE if need to scale while buffering
  554.  *    returns xaFALSE if you don't 
  555.  *
  556.  * NOTE: This should only be called within XXX_Read_File or else
  557.  *       scale isn't guaranteed to be valid.
  558.  * ACT_Setup_Mapped is okay since it has the same limitations.
  559.  */
  560. xaULONG UTIL_Get_Buffer_Scale(width,height,buffx_o,buffy_o)
  561. xaULONG width,height;     /* width, height of anim */
  562. xaULONG *buffx_o,*buffy_o; /* scaled width, height of anim */
  563. {
  564.  xaULONG need_to_scale;
  565.  xaULONG buff_x,buff_y;
  566.  
  567.   /* Figure out buffer scaling */
  568.   if ( (xa_buff_x != 0) && (xa_buff_y != 0) )
  569.         { buff_x = xa_buff_x; buff_y = xa_buff_y; }
  570.   else if (xa_buff_x != 0) /* if just x, then adjust y */
  571.         { buff_x = xa_buff_x; buff_y = (height * xa_buff_x) / width; }
  572.   else if (xa_buff_y != 0) /* if just y, then adjust x */
  573.         { buff_y = xa_buff_y; buff_x = (width * xa_buff_y) / height; }
  574.   else
  575.   {
  576.      /* handle any scaling */
  577.     buff_x = (xaULONG)((float)(width) * xa_bscalex);
  578.     if (buff_x == 0) buff_x = width;
  579.     buff_y = (xaULONG)((float)(height) * xa_bscaley);
  580.     if (buff_y == 0) buff_y = height;
  581.   }
  582.   if ((buff_x != width) || (buff_y != height)) need_to_scale = xaTRUE;
  583.   else need_to_scale = xaFALSE;
  584.   *buffx_o = buff_x; *buffy_o = buff_y;
  585.   return(need_to_scale);
  586. }
  587.  
  588. /*
  589.  * Function to allocate buffer for Scaling
  590.  *
  591.  */
  592. xaUBYTE *UTIL_Alloc_Scaled(xi_size,yi_size,xi_scale,yi_scale,
  593.     xo_scale,yo_scale,pix_size,xo_pos,yo_pos,bitmap_flag)
  594. xaULONG xi_size,yi_size;   /* size of section */
  595. xaULONG xi_scale,yi_scale; /* size of full input image */
  596. xaULONG xo_scale,yo_scale; /* size of full output image */
  597. xaULONG pix_size;          /* pixel size */
  598. xaULONG xo_pos,yo_pos;     /* pos of section in input buffer */
  599. xaULONG bitmap_flag;     /* if true, then alloc for a bitmap */
  600.  
  601. {
  602.   xaULONG sx,sy,xsize,ysize;
  603.   xaUBYTE *out;
  604.  
  605.   sx = (xo_pos * xo_scale) / xi_scale;
  606.   if ( ((sx * xi_scale) / xo_scale) < xo_pos ) sx++;
  607.   xsize = (((xo_pos + xi_size) * xo_scale) / xi_scale) + 1 - sx;
  608.   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xo_pos+xi_size) ) xsize--;
  609.  
  610.   sy = (yo_pos * yo_scale) / yi_scale;
  611.   if ( ((sy * yi_scale) / yo_scale) < yo_pos ) sy++;
  612.   ysize = (((yo_pos + yi_size) * yo_scale) / yi_scale) + 1 - sy;
  613.   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yo_pos+yi_size) ) ysize--;
  614.  
  615.   if ( (xsize==0) || (ysize==0) )
  616.   {
  617.     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %d %d\n",xsize,ysize);
  618.     return(0);
  619.   }
  620.  
  621. DEBUG_LEVEL1 fprintf(stderr,"AllocScaled: xy %d %d  t %d\n",
  622.   xsize,ysize,(xsize * ysize * pix_size));
  623.  
  624.   if (bitmap_flag==xaTRUE)
  625.   {
  626.     xaULONG line_size;
  627.     line_size = X11_Get_Bitmap_Width(xsize) / 8;
  628.     out = (xaUBYTE *)malloc(line_size * ysize);
  629.   }
  630.   else out = (xaUBYTE *)malloc(xsize * ysize * pix_size);
  631.   if (out==0) TheEnd1("UTIL_Alloc_Scaled: malloc err");
  632.   return(out);
  633. }
  634.  
  635. /*
  636.  * Function to Scale a Mapped Image 
  637.  *
  638.  */
  639. xaUBYTE *UTIL_Scale_Mapped(out,in,xi_pos,yi_pos,xi_size,yi_size,
  640.     xi_buff_size,xi_scale,yi_scale,xo_scale,yo_scale,pix_size,
  641.     xo_pos,yo_pos,xo_size,yo_size,chdr)
  642. xaUBYTE *out;         /* output buffer, if 0 then one is created */
  643. xaUBYTE *in;         /* input image buffer */
  644. xaULONG xi_pos,yi_pos;     /* pos of section in input buffer */
  645. xaULONG xi_size,yi_size;   /* size of section */
  646. xaULONG xi_buff_size;      /* row size of input buffer in bytes */
  647. xaULONG xi_scale,yi_scale; /* size of full input image */
  648. xaULONG xo_scale,yo_scale; /* size of full output image */
  649. xaULONG pix_size;         /* pixel size */
  650. xaULONG *xo_pos,*yo_pos;   /* I screen pos/O pos of section in output buffer */
  651. xaULONG *xo_size,*yo_size; /* O size of outgoing section */
  652. XA_CHDR *chdr;
  653. /* note: pos of section in output buffer is always 0,0 */
  654. {
  655.   xaULONG i,y,sx,sy,xvp,yvp,xsize,ysize,xoff;
  656.  
  657.  
  658.   xvp = *xo_pos; yvp = *yo_pos;
  659.   sx = (xvp * xo_scale) / xi_scale;
  660.   if ( ((sx * xi_scale) / xo_scale) < xvp ) sx++;
  661.   xsize = (((xvp + xi_size) * xo_scale) / xi_scale) + 1 - sx;
  662.   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xvp+xi_size) ) xsize--;
  663.  
  664.   sy = (yvp * yo_scale) / yi_scale;
  665.   if ( ((sy * yi_scale) / yo_scale) < yvp ) sy++;
  666.   ysize = (((yvp + yi_size) * yo_scale) / yi_scale) + 1 - sy;
  667.   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yvp+yi_size) ) ysize--;
  668.  
  669.   xoff = xvp - xi_pos;
  670.   if ( (xsize==0) || (ysize==0) ) 
  671.   {
  672.     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %d %d\n",xsize,ysize);
  673.     *xo_pos = *yo_pos = *xo_size = *yo_size = 0;
  674.     return(0);
  675.   }
  676.  
  677.   /* use scale buffer if necessary */
  678.   if (out == 0)
  679.   {
  680.     xaULONG tsize = xsize * ysize * pix_size;
  681.     XA_REALLOC(xa_scale_buff,xa_scale_buff_size,tsize);
  682.     out = (xaUBYTE *)xa_scale_buff;
  683.   }
  684.  
  685.   /* readjust row cache buffer if necessary */
  686.   if (xsize > xa_scale_row_size)
  687.   {
  688.     xaULONG *tmp;
  689.     if (xa_scale_row_buff == 0) tmp = (xaULONG *) malloc(xsize * sizeof(xaULONG) );
  690.     else tmp = (xaULONG *) realloc(xa_scale_row_buff, xsize * sizeof(xaULONG) );
  691.     if (tmp == 0) TheEnd1("UTIL_Scale_Mapped: row malloc err\n");
  692.     xa_scale_row_buff = tmp;    xa_scale_row_size = xsize;
  693.   }
  694.  
  695.   y = sx; for(i = 0; i < xsize; i++,y++)
  696.     xa_scale_row_buff[i] = ((y * xi_scale) / xo_scale ) - xoff;
  697.  
  698.   if (chdr==0) /* no mapping */
  699.   {
  700.     register xaULONG x,yoff;
  701.     yoff = yvp - yi_pos;
  702.     if (pix_size == 4)
  703.     {
  704.       register xaULONG *optr = (xaULONG *)out;
  705.       for(y=sy; y< (sy + ysize); y++)
  706.       { register xaULONG *in_r_ptr = 
  707.         (xaULONG *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  708.         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
  709.       }
  710.     }
  711.     else if (pix_size == 2)
  712.     {
  713.       register xaUSHORT *optr = (xaUSHORT *)out;
  714.       for(y=sy; y< (sy + ysize); y++)
  715.       { register xaUSHORT *in_r_ptr = 
  716.         (xaUSHORT *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  717.         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
  718.       }
  719.     }
  720.     else
  721.     {
  722.       register xaUBYTE *optr = (xaUBYTE *)out;
  723.       for(y=sy; y< (sy + ysize); y++)
  724.       { register xaUBYTE *in_r_ptr = 
  725.         (xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  726.         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
  727.       }
  728.     }
  729.   }
  730.   else /* remap as we scale */
  731.   {
  732.     register xaULONG x,yoff,moff,*map;
  733.     map  = chdr->map; moff = chdr->moff; yoff = yvp - yi_pos;
  734.     if (pix_size == 4)
  735.     {
  736.       register xaULONG *optr = (xaULONG *)out;
  737.       for(y=sy; y< (sy + ysize); y++)
  738.       { register xaUBYTE *in_r_ptr = 
  739.         (xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  740.     if (moff) for(x = 0; x < xsize; x++) 
  741.         *optr++ = (xaULONG)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
  742.     else for(x = 0; x < xsize; x++) 
  743.         *optr++ = (xaULONG)map[in_r_ptr[ xa_scale_row_buff[x]]];
  744.       }
  745.     }
  746.     else if (pix_size == 2)
  747.     {
  748.       register xaUSHORT *optr = (xaUSHORT *)out;
  749.       for(y=sy; y< (sy + ysize); y++)
  750.       { register xaUBYTE *in_r_ptr = 
  751.         (xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  752.     if (moff) for(x = 0; x < xsize; x++) 
  753.         *optr++ = (xaUSHORT)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
  754.     else for(x = 0; x < xsize; x++) 
  755.         *optr++ = (xaUSHORT)map[in_r_ptr[ xa_scale_row_buff[x]]];
  756.       }
  757.     }
  758.     else
  759.     {
  760.       register xaUBYTE *optr = (xaUBYTE *)out;
  761.       for(y=sy; y< (sy + ysize); y++)
  762.       { register xaUBYTE *in_r_ptr = 
  763.         (xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
  764.     if (moff) for(x = 0; x < xsize; x++) 
  765.         *optr++ = (xaUBYTE)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
  766.     else for(x = 0; x < xsize; x++) 
  767.         *optr++ = (xaUBYTE)map[in_r_ptr[ xa_scale_row_buff[x]]];
  768.       }
  769.     }
  770.   }
  771.   *yo_pos = sy; *yo_size = ysize;
  772.   *xo_pos = sx; *xo_size = xsize;
  773.   return(out);
  774. }
  775.  
  776.  
  777. /*
  778.  * for now assum xi_pos=yi_pos=0 and size are multiple of 8s 
  779.  *
  780.  */
  781. xaUBYTE *UTIL_Scale_Bitmap(out,in,xi_size,yi_size,
  782.     xi_line_size,xi_scale,yi_scale,xo_scale,yo_scale,
  783.     xo_pos,yo_pos,xo_size,yo_size,ibit_order,obit_order)
  784. xaUBYTE *out,*in;
  785. xaULONG xi_size,yi_size;   /* size of section */
  786. xaULONG xi_line_size;      /* row size of input buffer in bytes*/
  787. xaULONG xi_scale,yi_scale; /* size of full input image */
  788. xaULONG xo_scale,yo_scale; /* size of full output image */
  789. xaULONG *xo_pos,*yo_pos;   /* pos of section in input/output buffer */
  790. xaULONG *xo_size,*yo_size; /* size of outgoing section */
  791. xaULONG ibit_order;     /* input bit_order */
  792. xaULONG obit_order;     /* output bit_order */
  793. {
  794.   xaULONG xo_line_size;
  795.   xaULONG i,y,sx,sy,xvp,yvp,xsize,ysize;
  796.   xaULONG *row_b_ptr;
  797.   xaUBYTE *row_msk_ptr,mask_start,mask_end;
  798.  
  799.   xvp = *xo_pos; yvp = *yo_pos;
  800.   sx = (xvp * xo_scale) / xi_scale;
  801.   if ( ((sx * xi_scale) / xo_scale) < xvp ) sx++;
  802.   xsize = (((xvp + xi_size) * xo_scale) / xi_scale) + 1 - sx;
  803.   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xvp+xi_size) ) xsize--;
  804.  
  805.   sy = (yvp * yo_scale) / yi_scale;
  806.   if ( ((sy * yi_scale) / yo_scale) < yvp ) sy++;
  807.   ysize = (((yvp + yi_size) * yo_scale) / yi_scale) + 1 - sy;
  808.   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yvp+yi_size) ) ysize--;
  809.  
  810. DEBUG_LEVEL1 fprintf(stderr,"SCALE BITMAP: siz %dx%d -> %dx%d\n",
  811.     xi_size,yi_size,xsize,ysize);
  812. DEBUG_LEVEL1 fprintf(stderr,"SCALE BITMAP: pos %dx%d -> %dx%d\n",
  813.     xvp,yvp,sx,sy);
  814.  
  815.   if ( (xsize==0) || (ysize==0) ) 
  816.   {
  817.     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %d %d\n",xsize,ysize);
  818.     *xo_size = *yo_size = 0;
  819.     return(0);
  820.   }
  821.   xo_line_size = X11_Get_Bitmap_Width(xsize) / 8;
  822.   /* use scale buffer if necessary */
  823.   if (out == 0)
  824.   {
  825.     xaULONG tsize = ysize * xo_line_size;
  826.     XA_REALLOC(xa_scale_buff,xa_scale_buff_size,tsize);
  827.     out = (xaUBYTE *)xa_scale_buff;
  828.   }
  829.  
  830.   /* readjust row cache buffer if necessary */
  831.   if ( (xsize<<1) > xa_scale_row_size)
  832.   {
  833.     xaULONG *tmp;
  834.     if (xa_scale_row_buff == 0) tmp = (xaULONG *) malloc(xsize * sizeof(xaULONG) );
  835.     else tmp = (xaULONG *) realloc(xa_scale_row_buff,(xsize<<1)*sizeof(xaULONG));
  836.     if (tmp == 0) TheEnd1("UTIL_Scale_Mapped: row malloc err\n");
  837.     xa_scale_row_buff = tmp;    xa_scale_row_size = (xsize<<1);
  838.   }
  839.   row_b_ptr = xa_scale_row_buff;
  840.   row_msk_ptr = (xaUBYTE *)&xa_scale_row_buff[xsize];
  841.  
  842.   y = sx;
  843.   for(i = 0; i < xsize; i++,y++)
  844.   {
  845.     register xaULONG x = ((y * xi_scale) / xo_scale) - xvp;
  846.     row_b_ptr[i] = x/8;
  847.     if (ibit_order == X11_LSB) row_msk_ptr[i] = 0x01 << (x%8);
  848.     else row_msk_ptr[i] = 0x01 << (7 - (x%8));
  849.   }
  850.   if (obit_order == X11_MSB) { mask_start = 0x80; mask_end = 0x01; }
  851.   else { mask_start = 0x01; mask_end = 0x80; }
  852.   for(y=sy; y < (sy+ysize);y++)
  853.   {
  854.     register xaULONG x;
  855.     register xaUBYTE omsk,odat;
  856.     register xaUBYTE *iptr,*optr;
  857.     iptr = (xaUBYTE *)(in + (((y * yi_scale) / yo_scale)-yvp) * xi_line_size);
  858.     optr = (xaUBYTE *)(out + ((y - sy) * xo_line_size));
  859.     omsk = mask_start; odat = 0;
  860.     for(x=0; x<xsize; x++)
  861.     {
  862.       if ( iptr[ row_b_ptr[x] ] & row_msk_ptr[x] ) odat |= omsk;
  863.       if (omsk == mask_end) { *optr++ = odat; omsk = mask_start; odat = 0; }
  864.       else if (mask_start == 0x01) omsk <<= 1; else omsk >>= 1;
  865.     }
  866.     if (omsk) *optr++ = odat;
  867.   }
  868.   *xo_pos = sx;     *yo_pos = sy;
  869.   *xo_size = xsize; *yo_size = ysize;
  870.   return(out);
  871. }
  872.  
  873. /**********************
  874.  * UTIL_RGB_To_Map
  875.  *
  876.  **********************/
  877. xaUBYTE *UTIL_RGB_To_Map(out,in,chdr,xsize,ysize,free_in_flag)
  878. xaUBYTE *out,*in;
  879. XA_CHDR *chdr;
  880. xaULONG xsize,ysize;
  881. xaULONG free_in_flag;
  882. {
  883.   xaULONG i,shift_r,shift_g,shift_b,pic_size;
  884.   xaUBYTE *t_pic,*iptr,*optr;
  885.   xaULONG csize,coff;
  886.  
  887.   DEBUG_LEVEL1 fprintf(stderr,"UTIL_RGB_To_Map\n");
  888.   pic_size = xsize * ysize;
  889.   if (out == 0)
  890.   {
  891.     t_pic = (xaUBYTE *)malloc( XA_PIC_SIZE(pic_size) );
  892.     if (t_pic == 0) TheEnd1("RGB: t_pic malloc err");
  893.   } else t_pic = out;
  894.  
  895.   if (cmap_cache == 0) CMAP_Cache_Init(0);
  896.   if (chdr != cmap_cache_chdr)
  897.   {
  898.     DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %x\n",
  899.                                                         (xaULONG)chdr);
  900.     CMAP_Cache_Clear();
  901.     cmap_cache_chdr = chdr;
  902.   }
  903.   shift_r = 3 * cmap_cache_bits;
  904.   shift_g = 2 * cmap_cache_bits;
  905.   shift_b = cmap_cache_bits;
  906.  
  907.  
  908.   csize = chdr->csize;
  909.   coff = chdr->coff;
  910.   iptr = in;
  911.   optr = t_pic;
  912.   for(i=0; i < pic_size; i++)
  913.   {
  914.     register xaULONG color_out,r,g,b;
  915.     register xaULONG cache_i;
  916.  
  917.     r = (xaULONG)(*iptr++); g = (xaULONG)(*iptr++); b = (xaULONG)(*iptr++);
  918.     cache_i  = (xaULONG)(  (  ( (r << shift_r) & cmap_cache_rmask)
  919.                           | ( (g << shift_g) & cmap_cache_gmask)
  920.                           | ( (b << shift_b) & cmap_cache_bmask)
  921.                          ) >> 8);
  922.     if (cmap_cache[cache_i] == 0xffff)
  923.     {
  924.       color_out = coff +
  925.                 CMAP_Find_Closest(chdr->cmap,csize,r,g,b,8,8,8,xaTRUE);
  926.       cmap_cache[cache_i] = (xaUSHORT)color_out;
  927.     }
  928.     else color_out = (xaULONG)cmap_cache[cache_i];
  929.  
  930.     *optr++ = (xaUBYTE)(color_out);
  931.  
  932.   }
  933.   if (free_in_flag == xaTRUE) FREE(in,0x304); in=0;
  934.   return(t_pic);
  935. }
  936.  
  937. /**********************
  938.  *
  939.  **********************/
  940. xaUBYTE *UTIL_RGB_To_FS_Map(out,in,chdr,xsize,ysize,free_in_flag)
  941. xaUBYTE *out,*in;
  942. XA_CHDR *chdr;
  943. xaULONG xsize,ysize;
  944. xaULONG free_in_flag;
  945. {
  946.   xaULONG flag,csize,xsize3;
  947.   ColorReg *cmap;
  948.   register xaULONG x,y;
  949.   xaULONG shift_r,shift_g,shift_b,coff;
  950.   xaSHORT *err_buff0, *err_buff1, *e_ptr, *ne_ptr;
  951.   xaSHORT r_err,g_err,b_err;
  952.   xaUBYTE *o_ptr,*tpic;
  953.  
  954.   DEBUG_LEVEL1 fprintf(stderr,"UTIL_RGB_To_FS_Map\n");
  955.  
  956.   if (out == 0)
  957.   {
  958.     tpic = (xaUBYTE *)malloc( XA_PIC_SIZE(xsize * ysize) );
  959.     if (tpic == 0) TheEnd1("UTIL_RGB_To_FS_Map: malloc err");
  960.   } else tpic = out;
  961.  
  962.   if (cmap_cache == 0) CMAP_Cache_Init(0);
  963.  
  964.   if (chdr != cmap_cache_chdr)
  965.   {
  966.     DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %x\n",(xaULONG)chdr);
  967.     CMAP_Cache_Clear();
  968.     cmap_cache_chdr = chdr;
  969.   }
  970.   shift_r = 3 * cmap_cache_bits;
  971.   shift_g = 2 * cmap_cache_bits;
  972.   shift_b = cmap_cache_bits;
  973.   
  974.   csize = chdr->csize;
  975.   cmap = chdr->cmap;
  976.   coff = chdr->coff;
  977.  
  978.   /* allocate error buffer and set up pointers */
  979.   xsize3 = xsize * 3;
  980.   e_ptr = err_buff0 = (xaSHORT *)malloc(6 * xsize * sizeof(xaSHORT) );
  981.   if (err_buff0 == 0) TheEnd1("UTIL_Mapped_To_Floyd: malloc err");
  982.   err_buff1 = &err_buff0[xsize3];
  983.   flag = 0;
  984.  
  985.   {
  986.     register xaUBYTE *i_ptr = (xaUBYTE *)( in + (xsize3 * (ysize-1)));
  987.     x = xsize; while(x--)
  988.     {
  989.       *e_ptr++ = (xaUSHORT)(*i_ptr++) << 4;
  990.       *e_ptr++ = (xaUSHORT)(*i_ptr++) << 4;
  991.       *e_ptr++ = (xaUSHORT)(*i_ptr++) << 4;
  992.     }
  993.   }
  994.  
  995.   y = ysize; while(y--)
  996.   {
  997.     o_ptr = (xaUBYTE *)(tpic + (xsize * y));
  998.     if (flag) { e_ptr = err_buff1; ne_ptr = err_buff0; flag = 0; }
  999.     else      { e_ptr = err_buff0; ne_ptr = err_buff1; flag = 1; }
  1000.     if (y > 0)
  1001.     {
  1002.       register xaSHORT *tptr = ne_ptr;
  1003.       register xaUBYTE *i_ptr = (xaUBYTE *)(in + (xsize3 * (y-1)));
  1004.       x = xsize; while(x--)
  1005.       {
  1006.     *tptr++ = (xaUSHORT)(*i_ptr++) << 4;
  1007.     *tptr++ = (xaUSHORT)(*i_ptr++) << 4;
  1008.     *tptr++ = (xaUSHORT)(*i_ptr++) << 4;
  1009.       }
  1010.     }
  1011.  
  1012.     x = xsize; while(x--)
  1013.     {
  1014.       xaULONG color_out;
  1015.       register xaSHORT r,g,b;
  1016.       register xaULONG cache_i;
  1017.  
  1018.       r = (*e_ptr++)/16; if (r<0) r = 0; else if (r>255) r = 255;
  1019.       g = (*e_ptr++)/16; if (g<0) g = 0; else if (g>255) g = 255;
  1020.       b = (*e_ptr++)/16; if (b<0) b = 0; else if (b>255) b = 255;
  1021.      
  1022.       cache_i = (  ( (r << shift_r) & cmap_cache_rmask)
  1023.                  | ( (g << shift_g) & cmap_cache_gmask)
  1024.                  | ( (b << shift_b) & cmap_cache_bmask) ) >> 8;
  1025.  
  1026.       if (cmap_cache[cache_i] == 0xffff)
  1027.       {
  1028.         color_out = CMAP_Find_Closest(cmap,csize,r,g,b,8,8,8,xaTRUE);
  1029.         cmap_cache[cache_i] = (xaSHORT)color_out;
  1030.       }
  1031.       else color_out = (xaULONG)cmap_cache[cache_i];
  1032.       
  1033.       *o_ptr++ = (xaUBYTE)(color_out + coff);
  1034.  
  1035.       r_err = r - (xaSHORT)(cmap[color_out].red >> 8);
  1036.       g_err = g - (xaSHORT)(cmap[color_out].green >> 8);
  1037.       b_err = b - (xaSHORT)(cmap[color_out].blue >> 8);
  1038.  
  1039.       if (x)
  1040.       {
  1041.     *e_ptr   += 7 * r_err;
  1042.     e_ptr[1] += 7 * g_err;
  1043.     e_ptr[2] += 7 * b_err;
  1044.       }
  1045.       if (y)
  1046.       {
  1047.         if (x < (xsize-1) ) /* not 1st of line */
  1048.     {
  1049.       *ne_ptr++ += 3 * r_err;
  1050.       *ne_ptr++ += 3 * g_err;
  1051.       *ne_ptr++ += 3 * b_err;
  1052.     }
  1053.         *ne_ptr   += 5 * r_err;
  1054.         ne_ptr[1] += 5 * g_err;
  1055.         ne_ptr[2] += 5 * b_err;
  1056.         if (x)
  1057.         {
  1058.       ne_ptr[3] += r_err;
  1059.       ne_ptr[4] += g_err;
  1060.       ne_ptr[5] += b_err;
  1061.     }
  1062.       }
  1063.     } /* end of x */
  1064.   } /* end of y */
  1065.   if (err_buff0) { FREE(err_buff0,0x305); err_buff0=0; }
  1066.   if (free_in_flag == xaTRUE) FREE(in,0x306);
  1067.   return(tpic);
  1068. }
  1069.  
  1070. void
  1071. UTIL_Pack_Image(out,in,xsize,ysize)
  1072. xaUBYTE *out;
  1073. xaUBYTE *in;
  1074. xaULONG xsize,ysize;
  1075. {
  1076.   xaUBYTE *o_ptr;
  1077.   xaULONG x,y,shft_msk;
  1078.   xaLONG shft_start,shft_end,shft_inc;
  1079.  
  1080.   if (x11_bits_per_pixel == 4)
  1081.   { shft_msk = 0x0f;
  1082.     if (x11_byte_order == X11_MSB) {shft_start=4; shft_end=0; shft_inc= -4;}
  1083.     else               {shft_start=0; shft_end=4; shft_inc=  4;}
  1084.   }
  1085.   else if (x11_bits_per_pixel == 2)
  1086.   { shft_msk = 0x03;
  1087.     if (x11_byte_order == X11_MSB) {shft_start=6; shft_end=0; shft_inc= -2;}
  1088.     else               {shft_start=0; shft_end=6; shft_inc=  2;}
  1089.   }
  1090.   else /* unsupported depth */
  1091.   {
  1092.     fprintf(stderr,"X11 Packing of bits %d to depth %d not yet supported\n",
  1093.     x11_bits_per_pixel,x11_depth);
  1094.     return;
  1095.   }
  1096.  
  1097.   o_ptr = out;
  1098.   for(y=0;y<ysize;y++)
  1099.   { register xaULONG data = 0;
  1100.     register xaLONG shft  = shft_start;
  1101.     for(x=0; x<xsize; x++)
  1102.     {
  1103.     if (shft != shft_end) /* still creating byte */
  1104.     { data |= ((*in++) & shft_msk) << shft; 
  1105.       shft += shft_inc;
  1106.     }
  1107.     else /* at the end */
  1108.     {
  1109.       *o_ptr++ = data | (((*in++) & shft_msk) << shft);
  1110.       shft = shft_start;
  1111.       data = 0;
  1112.     } 
  1113.     }
  1114.     if (shft != shft_start) *o_ptr++ = data; /* partial byte */
  1115.   } /* end of y loop */
  1116. }
  1117.  
  1118. /**************************
  1119.  *
  1120.  * Convert frames per second into vid_time(ms) 
  1121.  * and vid_timelo(fractional ms).
  1122.  *
  1123.  * Global Variable: xa_jiffy_flag   non-zero then IS ms to use.
  1124.  ***********************/
  1125. void UTIL_FPS_2_Time(anim,fps)
  1126. XA_ANIM_SETUP *anim;
  1127. double fps;
  1128. {
  1129.   if (xa_jiffy_flag) { anim->vid_time = xa_jiffy_flag; anim->vid_timelo = 0; }
  1130.   { double ptime = (double)(1000.0) / fps;
  1131.     anim->vid_time = (xaULONG)(ptime);
  1132.     ptime -= (double)(anim->vid_time);
  1133.     anim->vid_timelo = (xaULONG)(ptime * (double)(1<<24));
  1134.   }
  1135. }
  1136.  
  1137. /**************************
  1138.  * Index
  1139.  * Searches string "s" for character "c" starting at the
  1140.  * beginning of the string.
  1141.  **************************/
  1142. char *XA_index(s,c)
  1143. char *s,c;
  1144. { int len;
  1145.   char *p = s;
  1146.  
  1147.   if (s == (char *)(NULL)) return((char *)(NULL));
  1148.   len = strlen(s);
  1149.   while(len >= 0)
  1150.   { if (*p == c) return(p);
  1151.     else {p++; len--;}
  1152.   }
  1153.   return( (char *)(NULL) );
  1154. }
  1155.  
  1156. /**************************
  1157.  * Reverse Index
  1158.  * Searches string "s" for character "c" starting at the 
  1159.  * end of the string.
  1160.  **************************/
  1161. char *XA_rindex(s,c)
  1162. char *s,c;
  1163. { int len;
  1164.   char *p = s;
  1165.  
  1166.   if (c == 0) return((char *)(NULL));
  1167.   if (s == (char *)(NULL)) return((char *)(NULL));
  1168.   len = strlen(s);
  1169.   p += len;
  1170.   while(len >= 0)
  1171.   { if (*p == c) return(p);
  1172.     else {p--; len--;}
  1173.   }
  1174.   return( (char *)(NULL) );
  1175. }
  1176.  
  1177. /**************************
  1178.  * Return xaTRUE is key is inside s, else return xaFALSE
  1179.  **************************/
  1180. xaULONG XA_find_str(s,key)
  1181. char *s, *key;
  1182. { xaULONG key_len;
  1183.   char first = *key;
  1184.   char *tmp_s = s;
  1185.  
  1186.   if (key == 0) return(xaFALSE);
  1187.   key_len = strlen(key);
  1188.   while(s)
  1189.   { tmp_s = XA_index(s,first);
  1190.     if (tmp_s) 
  1191.     { 
  1192.       if (strncmp(tmp_s,key,key_len) == 0) return(xaTRUE); 
  1193.       s = tmp_s; s++;
  1194.     }
  1195.     else break;
  1196.   }
  1197.   return(xaFALSE);
  1198. }
  1199.  
  1200.