home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser 2002 January / STC_CD_01_2002.iso / GAMES / BOINKO21 / SRC / SRC / XIMGLOAD.C < prev   
C/C++ Source or Header  |  2000-09-29  |  50KB  |  1,837 lines

  1. /********************************************
  2. *        XIMGLOAD.C                            *
  3. *                                           *
  4. * Dan Ackerman - baldrick@netset.com 1999    *
  5. *                                            *
  6. * With thanks to Eero Tamien                *
  7. *                 Warwick Allison            *
  8. *                and Mario Becroft            *
  9. * All of whom over the years gave me helpful*
  10. *advice that I ignored to make this mess ;) *
  11. *                                            *
  12. * No really they were all very helpful        *
  13. ********************************************/
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18.  
  19. #include "boink.h"
  20.  
  21. #ifndef SEEK_SET
  22. #define SEEK_SET 0
  23. #endif
  24.  
  25. /* error codes */
  26. #define ERR_HEADER      1
  27. #define ERR_ALLOC       2
  28. #define ERR_FILE        3
  29. #define ERR_DEPACK      4
  30. #define ERR_TRFM        5
  31.  
  32. /* how many bytes one scanline can be */
  33. #define LINEBUF   1024
  34.  
  35. #define XIMG      0x58494D47
  36.  
  37. struct IMG_HEADER
  38. {                 /* Header of GEM Image Files   */
  39.   int version;  /* Img file format version (1) */
  40.   int length;   /* Header length in words  (8) */
  41.   int planes;   /* Number of bit-planes    (1) */
  42.   int pat_len;  /* length of Patterns      (2) */
  43.   int pix_w;    /* Pixel width in 1/1000 mmm  (372)    */
  44.   int pix_h;    /* Pixel height in 1/1000 mmm (372)    */
  45.   int img_w;    /* Pixels per line (=(x+7)/8 Bytes)    */
  46.   int img_h;    /* Total number of lines               */
  47.   long  magic;    /* Contains "XIMG" if standard color   */
  48.   int paltype;  /* palette type (0 = RGB (short each)) */
  49.   int *palette; /* palette etc.                        */
  50.   char *addr;     /* Address for the depacked bit-planes */
  51. };
  52.  
  53.  
  54. short vditodev8[] = {0,255,1,2,4,6,3,5,7,8,9,10,12,14,11,13,16,17,18,19,20,21,22,23,24,25,26
  55. ,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50
  56. ,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69
  57. ,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88
  58. ,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,
  59. 110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
  60. 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,
  61. 146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,
  62. 164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,
  63. 182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,
  64. 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,
  65. 218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,
  66. 236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,
  67. 251,252,253,254,15};
  68. short vditodev4[] = {0,15,1,2,4,6,3,5,7,8,9,10,12,14,11,13};
  69. short vditodev2[] = {0,3,1,2};
  70. short vditodev1[] = {0,1};
  71.  
  72. short id;
  73. extern int phys_handle;
  74. extern short  work_out[57];
  75.  
  76. int junk;
  77. extern MFDB screen;
  78. extern MFDB screen_fdb;
  79. int no_colors, img_handle;
  80.  
  81. int rgb_idx[256][3];
  82. RGB1000 image_colortab[256]; /* used to temp hold image pallette */
  83.  
  84. /* Function prototypes. */
  85. void    show_error( int error );
  86. int     depack_img( char *name, struct IMG_HEADER *info );
  87. int     show_img( struct IMG_HEADER *info );
  88. int     transform_img( MFDB *image, int planes, int *palette, int handle );
  89. int    dither( short **addr, long size, int width, int planes, int *palette );
  90. int     interleave( int factor, short **addr, long size, int planes );
  91. int    convert( MFDB *image, long size, int planes, int handle );
  92. int img_colors( int planes, int *palette, int handle);
  93. int truecolorimg_colors( int planes, int *palette , int col_handle);
  94. int copy_img( struct IMG_HEADER *pic, MFDB *image_buffer);
  95. int transform_truecolor( MFDB *image, long size, int planes, int handle);
  96. int mono_transform( MFDB *image, long size, int planes, int img_handle, int color, int keep_original);
  97. int c2mono( short **addr, long size, int width, int planes);
  98. int transform_remap( MFDB *image, long size, int planes, int img_handle);
  99.  
  100.  
  101.  
  102. /* Two functions used to swap the endianess */
  103. unsigned short swap_short(unsigned short in)
  104. {
  105.  unsigned short out;
  106.  out=((char)in)<<8;
  107.  out|=(in>>8);
  108.  return out;
  109. }
  110.  
  111. unsigned long swap_long(unsigned long in)
  112. {
  113.  unsigned long out;
  114.  unsigned short o1, o2;
  115.  o1=(unsigned short)(in>>16);
  116.  o2=(unsigned short)(in);
  117.  o1=swap_short(o1);
  118.  o2=swap_short(o2);
  119.  out=((unsigned long)o2)<<16;
  120.  out|=o1;
  121.  return out;
  122. }
  123.  
  124.  
  125.  
  126. /* ---------------------------------- */
  127.  
  128. void img_main(char *file )
  129. {
  130.   struct IMG_HEADER img;
  131.   int error = 1;
  132.  
  133.   img.addr = NULL;
  134.   img.palette = NULL;
  135.  
  136.   if( (error = depack_img( file, &img )) )
  137.        show_error( error );
  138.    else
  139.        show_img( &img );
  140.  
  141.   if(img.palette)  free( img.palette );
  142.   if(img.addr)  free( img.addr );
  143. }
  144.  
  145. void img_load(MFDB *image, char *file)
  146. {
  147.   struct IMG_HEADER tempimg;
  148.   int error = 1;
  149.  
  150.   tempimg.addr = NULL;
  151.   tempimg.palette = NULL;
  152.  
  153.   if( (error = depack_img( file, &tempimg )) )
  154.        show_error( error );
  155.    else
  156.        copy_img( &tempimg, image );
  157.  
  158.    if(tempimg.palette)  free( tempimg.palette );
  159.    if(tempimg.addr)  free( tempimg.addr );
  160. }
  161.  
  162.  
  163. void show_error( int error )
  164. {
  165.   char message[64];
  166.  
  167.   strcpy( message, "[1][" );
  168.  
  169.   switch( error )
  170.   {
  171.     case ERR_FILE:
  172.       strcat( message, "File error.");
  173.       break;
  174.     case ERR_HEADER:
  175.       strcat( message, "Invalid IMG-header.");
  176.       break;
  177.     case ERR_ALLOC:
  178.       strcat( message, "Not enough memory.");
  179.       break;
  180.     case ERR_DEPACK:
  181.       strcat( message, "Depacking error.");
  182.       break;
  183.   }
  184.   strcat( message, " ][  OK  ]" );
  185.  
  186.   form_alert( 1, message );
  187. }
  188.  
  189. /* Loads & depacks IMG (0 if succeded, else error). */
  190. /* Bitplanes are one after another in address IMG_HEADER.addr. */
  191. int depack_img( char *name, struct IMG_HEADER *pic )
  192. {
  193.   int   a, b, line, plane, width, word_aligned, opcode, patt_len, pal_size,
  194.         byte_repeat, patt_repeat, scan_repeat, error = FALSE;
  195.   char  buf[LINEBUF], pattern[16], *address, *to, *endline;
  196.   long  size;
  197.   FILE *fp;
  198.   short swap_endianess; /* FALSE: not swapping, TRUE: swap them */
  199.  
  200.   fp=fopen(name, "rb");
  201.   if( fp == NULL )
  202.     return( ERR_FILE );
  203.  
  204.   /* read header info (bw & ximg) into image structure */
  205.   if( fread( pic, 2, 8+3, fp ) != 8+3 )
  206.    { fclose(fp); return( ERR_FILE ); }
  207.  
  208.   swap_endianess=!(pic->planes & 0x00FF);  /* Hu, I hope this will work */
  209.   if(swap_endianess)
  210.    {
  211.     pic->version=swap_short(pic->version);
  212.     pic->length=swap_short(pic->length);
  213.     pic->planes=swap_short(pic->planes);
  214.     pic->pat_len=swap_short(pic->pat_len);
  215.     pic->pix_w=swap_short(pic->pix_w);
  216.     pic->pix_h=swap_short(pic->pix_h);
  217.     pic->img_w=swap_short(pic->img_w);
  218.     pic->img_h=swap_short(pic->img_h);
  219.     pic->magic=swap_long(pic->magic);
  220.     pic->paltype=swap_short(pic->paltype);
  221.    }
  222.  
  223.   /* if XIMG, read info */
  224. #if OS_TOS   /* Seems not yet to work right with FreeGEM :-( so I disabled it */
  225.   if( pic->magic == XIMG )
  226.   {
  227.       pal_size = (1 << pic->planes) * 3;
  228.     
  229.       /* Thothy you had modified the following line so it would not work anymore at all
  230.             I rem'd your line and replaced it with the original */
  231.       /*    pic->palette = (int *)malloc( pal_size * sizeof(int // pic->palette //) );
  232.            if(pic->palette)*/
  233.  
  234.       if( (pic->palette = (int *)malloc( pal_size * sizeof(pic->palette) )) )
  235.       {
  236.         fread( (char *)pic->palette, sizeof(int), (long)pal_size, fp );
  237.  
  238.         if(swap_endianess)
  239.          for(a=0; a<pal_size; a++)
  240.           pic->palette[a]=swap_short(pic->palette[a]);
  241.       }
  242.   }
  243.   else
  244.   {
  245.     pic->palette = NULL;
  246.   }
  247. #endif
  248. #if OS_DOS
  249.   pic->palette = NULL;
  250. #endif
  251.  
  252.   /* width in bytes word aliged */
  253.   word_aligned = (pic->img_w + 15) >> 4;
  254.   word_aligned <<= 1;
  255.  
  256.   /* width byte aligned */
  257.   width = (pic->img_w + 7) >> 3;
  258.  
  259.   /* allocate memory for the picture */
  260.   if(pic->addr) free( pic->addr );
  261.   size = (long) word_aligned * pic->img_h * pic->planes;
  262.  
  263.   /* check for header validity & malloc long... */
  264.  
  265.   if (pic->length > 7 && pic->planes < 33 && pic->img_w > 0 && pic->img_h > 0)
  266.     pic->addr = (char *) malloc( size );
  267.   else
  268.   {
  269.     error = ERR_HEADER;
  270.     goto end_depack;
  271.   }
  272.  
  273.   /* if allocation succeded, proceed with depacking */
  274.   if( pic->addr == NULL )
  275.   {
  276.     error = ERR_ALLOC;
  277.     goto end_depack;
  278.   }
  279.   else
  280.   {
  281.     patt_len = pic->pat_len;
  282.     endline = buf + width;
  283.  
  284.     /* jump over the header and possible (XIMG) info */
  285.     fseek( fp, (long) pic->length * 2, SEEK_SET );
  286.  
  287.     /* depack whole img */
  288.     for( line = 0; line < pic->img_h; line += scan_repeat )
  289.     {
  290.       scan_repeat = 1;
  291.  
  292.       /* depack one scan line */
  293.       for( plane = 0; plane < pic->planes; plane ++)
  294.       {
  295.         to = buf;
  296.  
  297.         /* depack one line in one bitplane */
  298.         do
  299.         {
  300.           opcode = fgetc( fp );
  301.           switch( opcode )
  302.           {
  303.             /* pattern or scan repeat */
  304.             case 0:
  305.  
  306.               patt_repeat = fgetc( fp );
  307.               /* repeat a pattern */
  308.               if( patt_repeat )
  309.               {
  310.                 /* read pattern */
  311.                 for( b = 0; b < patt_len; b ++ )
  312.                   pattern[b] = fgetc( fp );
  313.  
  314.                 /* copy pattern */
  315.                 for( a = 0; a < patt_repeat; a ++ )
  316.                 {
  317.                   /* in case it's odd amount... */
  318.                   for( b = 0; b < patt_len; b ++ )
  319.                    {
  320.                     *(to ++) = pattern[b];
  321.                    }
  322.                 }
  323.               }
  324.  
  325.               /* repeat a line */
  326.               else
  327.               {
  328.                 if( fgetc( fp ) == 0xFF )
  329.                   scan_repeat = fgetc( fp );
  330.                 else
  331.                 {
  332.                   error = ERR_DEPACK;
  333.                   goto end_depack;
  334.                 }
  335.               }
  336.               break;
  337.  
  338.             /* repeat 'as is' */
  339.             case 0x80:
  340.               byte_repeat = fgetc( fp );
  341.               for( ; byte_repeat > 0; byte_repeat -- )
  342.                {
  343.                 *(to ++) = fgetc( fp );
  344.                }
  345.               break;
  346.  
  347.             /* repeat black or white */
  348.             default:
  349.               byte_repeat = opcode & 0x7F;
  350.               if( opcode & 0x80 )
  351.                 opcode = 0xFF;
  352.               else
  353.                 opcode = 0x00;
  354.               for( ; byte_repeat > 0; byte_repeat -- )
  355.                {
  356.                 *(to ++) = opcode;
  357.                }
  358.           }
  359.         }
  360.         while( to < endline );
  361. for(a=0; a<width; a++)
  362.  if(swap_endianess && (a & 1))
  363.   {
  364.    char tb;
  365.    tb=buf[a-1]; buf[a-1]=buf[a]; buf[a]=tb;
  366.   }
  367.  
  368.         if( to == endline && line + scan_repeat <= pic->img_h )
  369.         {
  370.           /* calculate address of a current line in a current bitplane */
  371.           address = pic->addr  +
  372.                   (long) line  * word_aligned +
  373.                   (long) plane * word_aligned * pic->img_h;
  374.  
  375.           /* copy line to image buffer */
  376.           for( a = 0; a < scan_repeat; a ++ )
  377.           {
  378.             memcpy( address, buf, width );
  379.             address += word_aligned;
  380.           }
  381.         }
  382.         else
  383.         {
  384.           error = ERR_DEPACK;
  385.           goto end_depack;
  386.         }
  387.       }
  388.     }
  389.   }
  390.  
  391.   end_depack:
  392.   fclose( fp );
  393.  
  394.   return( error );
  395. }
  396.  
  397. /* shows img on screen */
  398. int show_img( struct IMG_HEADER *pic)
  399. {
  400.   int screen_planes, screen_w, screen_h, buttons = 0, key,
  401.         i, x1 = 0, y1 = 0, x2 = 0, y2 = 0, mx, my, xx, yy, cen_x, cen_y,
  402.         redraw = TRUE, work_in[11], work_out[57], pxyarray[8],
  403.         wg_x, wg_y, wg_w, wg_h;
  404.   MFDB image, tmpscreen;
  405.  
  406.   /* Screen and Image VDI Memory Form Definitions. */
  407.   tmpscreen.fd_addr   = 0;
  408.   image.fd_addr    = pic->addr;                 /* address      */
  409.   image.fd_w       = pic->img_w;                /* width        */
  410.   image.fd_wdwidth = (pic->img_w + 15) >> 4;    /* (words)      */
  411.   image.fd_h       = pic->img_h;                /* height       */
  412.   image.fd_stand   = 0;                         /* raster format = device */
  413.   image.fd_nplanes = pic->planes;               /* bitplanes    */
  414.  
  415.   /*** This could be as well *your* window's work area. ***/
  416.   /* Desktop work area. */
  417.   wind_get ( 0, WF_WORKXYWH, &wg_x, &wg_y, &wg_w, &wg_h );
  418.  
  419.   /* pic size on screen */
  420.   xx = min( wg_w, pic->img_w );
  421.   yy = min( wg_h, pic->img_h );
  422.  
  423.   /* for centering pic on screen */
  424.   cen_x = ((wg_w - xx) >> 1) + wg_x;
  425.   cen_y = ((wg_h - yy) >> 1) + wg_y;
  426.  
  427.   /* open virtual screen workstation (screen) */
  428.   work_in[0] = 1; work_in[10] = 2;
  429.  
  430. #if OS_TOS
  431.   if (vq_gdos() == 0)
  432.     {
  433.         work_in[0] = 2 + Getrez(); 
  434.     }
  435. #endif
  436.  
  437.   img_handle = graf_handle( &i, &i, &i, &i );
  438.  
  439.   v_opnvwk( work_in, &img_handle, work_out );
  440.   screen_w = work_out[0];
  441.   screen_h = work_out[1];
  442.  
  443.   no_colors = work_out[13];
  444.  
  445.   /* get the number of bitplanes on screen */
  446.  
  447.   vq_extnd(img_handle, 1, work_out);
  448.   screen_planes = work_out[4];
  449.  
  450.  
  451.   /* convert image to the current screen format if necessary */
  452.   if( !(transform_img( &image, screen_planes, pic->palette, img_handle)) )
  453.   {
  454.     v_clsvwk( img_handle );
  455.     return( FALSE );
  456.   }
  457.  
  458.   /* suspend other screen activity */
  459.   /*wind_update( BEG_UPDATE );
  460.   form_dial( FMD_START, wg_x, wg_y, wg_w, wg_h, wg_x, wg_y, wg_w, wg_h );
  461.  
  462.   graf_mouse( M_OFF, 0 );
  463. */
  464.  
  465.  
  466.   do
  467.   {
  468.     /* get mouse position */
  469.     graf_mkstate( &mx, &my, &buttons, &key );
  470.  
  471.     /* calculate new image place */
  472.     x1 = (long) mx * (image.fd_w - xx) / screen_w;
  473.     y1 = (long) my * (image.fd_h - yy) / screen_h;
  474.  
  475.     /* fit co-ordinates onto screen */
  476.     x1 = min( x1, pic->img_w - xx );
  477.     y1 = min( y1, pic->img_h - yy );
  478.     x1 = max( 0, x1 );
  479.     y1 = max( 0, y1 );
  480.  
  481.     /* draw image if necessary */
  482.     if ( redraw || x1 != x2 || y1 != y2 )
  483.     {
  484.       /* put values into the co-ordinate array */
  485.       pxyarray[0] = x1;
  486.       pxyarray[1] = y1;
  487.       pxyarray[2] = x1 + xx - 1;
  488.       pxyarray[3] = y1 + yy - 1;
  489.       pxyarray[4] = cen_x;
  490.       pxyarray[5] = cen_y;
  491.       pxyarray[6] = cen_x + xx - 1;
  492.       pxyarray[7] = cen_y + yy - 1;
  493.  
  494.       /* throw onto screen */
  495.       vro_cpyfm( img_handle, S_ONLY, pxyarray, &image, &tmpscreen); /* was source*/
  496.  
  497.       x2 = x1; y2 = y1;
  498.       redraw = FALSE;
  499.     }
  500.   /* exit with right button */
  501.   }
  502.   while(buttons != 1);
  503.  
  504.   /*graf_mouse( M_ON, 0 );*/
  505.  
  506.   /* enable other screen activities */
  507.   wind_update( END_UPDATE );
  508.  
  509.   /* redraw screen (really necessary with MTOS only) */
  510.   form_dial( FMD_FINISH, wg_x, wg_y, wg_w, wg_h, wg_x, wg_y, wg_w, wg_h );
  511.  
  512.   /* close virtual... */
  513.   v_clsvwk( img_handle );
  514.  
  515.   /* if image was converted to device format, free allcated memory */
  516.   if( image.fd_addr != pic->addr )
  517.     free( image.fd_addr );
  518.  
  519.   return( TRUE );
  520. }
  521.  
  522. /* copies img to MFDB */
  523. int copy_img( struct IMG_HEADER *pic, MFDB *image_buffer)
  524. {
  525.   int screen_planes, i, work_in[11], work_out[57], pxyarray[8];
  526.   MFDB image;
  527.   int curx,cury,maxx,maxy,minx,miny;
  528.  
  529.   /* Screen and Image VDI Memory Form Definitions. */
  530.   image.fd_addr    = pic->addr;                 /* address      */
  531.   image.fd_w       = pic->img_w;                /* width        */
  532.   image.fd_wdwidth = (pic->img_w + 15) >> 4;    /* (words)      */
  533.   image.fd_h       = pic->img_h;                /* height       */
  534.   image.fd_stand   = 0;                         /* raster format = device */
  535.   image.fd_nplanes = pic->planes;               /* bitplanes    */
  536.  
  537.   /* open virtual screen workstation (screen) */
  538.   work_in[0] = 1; work_in[10] = 2;
  539.  
  540.   if (vq_gdos() == 0)
  541.     {
  542.         work_in[0] = 2 + Getrez(); 
  543.     }
  544.  
  545.   img_handle = graf_handle( &i, &i, &i, &i );
  546.  
  547.   v_opnvwk( work_in, &img_handle, work_out );
  548.  
  549.   no_colors = work_out[13];
  550.  
  551.   /* get the number of bitplanes for MFDB */
  552.  
  553.   screen_planes = image_buffer->fd_nplanes;
  554.  
  555.   /* convert image to the current screen format if necessary */
  556.   if( !(transform_img( &image, screen_planes, pic->palette, img_handle)) )
  557.    {
  558.     v_clsvwk( img_handle );
  559.     return( FALSE );
  560.    }
  561.   
  562.     if (((image_buffer->fd_w - 1) <= image.fd_w)&&
  563.         ((image_buffer->fd_h - 1) <= image.fd_h))
  564.         {    
  565.             /* loaded image is larger than buffer */
  566.         
  567.             /* put values into the co-ordinate array */
  568.             pxyarray[0] = pxyarray[4] = 0;
  569.             pxyarray[1] = pxyarray[5] = 0;
  570.             pxyarray[2] = pxyarray[6] = image_buffer->fd_w - 1;
  571.             pxyarray[3] = pxyarray[7] = image_buffer->fd_h - 1;
  572.  
  573.             /* throw info buffer */
  574.             vro_cpyfm( img_handle, S_ONLY, pxyarray, &image, image_buffer);     
  575.         }
  576.     else
  577.     {
  578.         /* loaded image is smaller than buffer */
  579.     
  580.         maxx = max(image_buffer->fd_w,image.fd_w);
  581.         maxy = max(image_buffer->fd_h,image.fd_h);
  582.     
  583.         if (maxx > image_buffer->fd_w)
  584.             maxx = image_buffer->fd_w;
  585.                 
  586.         if (maxy > image_buffer->fd_h)
  587.             maxy = image_buffer->fd_h;
  588.  
  589.         minx = min(maxx,image.fd_w);
  590.         miny = min(maxy,image.fd_h);
  591.     
  592.         curx = 0; /* initialize our x and y counters */
  593.         cury = 0;
  594.             
  595.         for (curx = 0; curx <= image_buffer->fd_w;curx += image.fd_w)
  596.         {
  597.             if ((curx + image.fd_w)>image_buffer->fd_w)
  598.                 minx = image_buffer->fd_w - curx;
  599.             else
  600.                 minx = min(maxx,image.fd_w);
  601.  
  602.             if (minx < 0) minx = 0;
  603.  
  604.             for(cury = 0; cury <= image_buffer->fd_h;cury += image.fd_h)
  605.             {
  606.                 if ((cury + image.fd_h)>image_buffer->fd_h)
  607.                     miny = image_buffer->fd_h - cury;
  608.                 else
  609.                     miny = min(maxy,image.fd_h);
  610.  
  611.                 if (miny < 0) miny = 0;
  612.                 /* put values into the co-ordinate array */
  613.                                                 
  614.                 pxyarray[0] = 0;
  615.                 pxyarray[1] = 0;
  616.                 pxyarray[2] = minx - 1;
  617.                 pxyarray[3] = miny - 1;
  618.                 pxyarray[4] = curx;
  619.                 pxyarray[5] = cury;
  620.                 pxyarray[6] = curx + minx - 1;
  621.                 pxyarray[7] = cury + miny - 1;
  622.  
  623.                 /* throw onto screen  as long as it's a real block*/
  624.                 if (minx != 0 && miny != 0)
  625.                     vro_cpyfm( img_handle, S_ONLY, pxyarray, &image, image_buffer); 
  626.             }
  627.         }
  628.     }
  629.  
  630.     /* close virtual... */
  631.     v_clsvwk( img_handle );
  632.         
  633.     /* if image was converted to device format, free allcated memory */
  634.     if( image.fd_addr != pic->addr )
  635.         free( image.fd_addr );
  636.  
  637.   return( TRUE );
  638. }
  639.  
  640. /* fix_image only works for mono_chrome image files 
  641.  * color is the color you want the object to be on the screen
  642.  */
  643.  
  644. int fix_image(MFDB *image,int color)
  645. {
  646.     long size;
  647.     
  648.     size = (long)(image->fd_wdwidth * image->fd_h);
  649.  
  650.     mono_transform( image, size, planes, vdi_handle, color, 1);
  651.  
  652.   return(TRUE);
  653. }
  654.  
  655. /* return FALSE if transformation was unsuccesful */
  656. /* YOU could add dithering to these routines... */
  657. int transform_img( MFDB *image, int planes, int *palette, int img_handle)
  658. {
  659.   int factor;
  660.   long size;
  661.  
  662.   size = (long)(image->fd_wdwidth * image->fd_h);
  663.  
  664.   if( planes == 1 )
  665.   {
  666.   
  667.     if( image->fd_nplanes > 1 )
  668.     {
  669.       if( dither((short **)&(image->fd_addr), size, image->fd_wdwidth, image->fd_nplanes, palette ) == FALSE )
  670.       {
  671.         show_error( ERR_ALLOC );
  672.         return( FALSE );
  673.       }
  674.       image->fd_nplanes = 1;
  675.     }
  676. #if !ENDIANESS
  677.     else
  678.     {
  679.      vr_trnfm( img_handle, image, image);
  680.     }
  681. #endif
  682.     return( TRUE );
  683.   }
  684.   else
  685.   {
  686.     if( image->fd_nplanes != 1 )
  687.     {
  688. #if 0
  689.         if (image->fd_nplanes>planes)
  690.         {
  691.           if( dither((short **)&(image->fd_addr), size, image->fd_wdwidth, image->fd_nplanes, palette ) == FALSE )
  692.           {
  693.                 show_error( ERR_ALLOC );
  694.              return( FALSE );
  695.           }
  696.           image->fd_nplanes = 1; /* I really want this to be planes;*/
  697.         }
  698.         else
  699.         {
  700. #endif
  701.             if (planes > 8)
  702.                 truecolorimg_colors(image->fd_nplanes, palette, img_handle);
  703.             else
  704.                 img_colors(image->fd_nplanes, palette, img_handle);
  705. #if 0
  706.         }
  707. #endif
  708.     }
  709.  
  710.     /* interleaved? */
  711. /*    switch( rez )
  712.    {
  713.       case 0:
  714.         // low rez //
  715.         factor = 4;
  716.         break;
  717.       case 1:
  718.         // med rez //
  719.         factor = 2;
  720.         break;
  721.       default:
  722.         factor = 0;
  723.     }*/
  724.  
  725.     factor = 0;
  726.  
  727.     if( factor )
  728.     {
  729.       /* Interleave bitplane information. */
  730.       if( interleave( factor, (short **)&(image->fd_addr), size, image->fd_nplanes ) )
  731.       {
  732.         image->fd_nplanes = factor;
  733.         return( TRUE );
  734.       }
  735.       else
  736.         show_error( ERR_ALLOC );
  737.     }
  738.     else
  739.     {
  740.         if (planes > 8)
  741.         {
  742.             /* Non planar mode  don't use vr_trfm */
  743.             if(transform_truecolor( image, size, planes, img_handle) )
  744.                 return(TRUE);
  745.             else
  746.                 show_error(ERR_ALLOC);
  747.         }
  748.         else
  749.         {
  750. #if 0
  751.             /* Use vr_trfm(), which needs a bit more memory. */
  752.               if( convert( image, size, planes, img_handle ) )    
  753. #endif
  754.             if(transform_remap( image, size, planes, img_handle) )
  755.                 return( TRUE );
  756.               else
  757.                 show_error( ERR_ALLOC );
  758.         }
  759.     }
  760.   }
  761.   return( FALSE );
  762. }
  763.  
  764. /* dither bitplanes into an bw one */
  765. int dither( short **addr, long size, int width, int planes, int *palette )
  766. {
  767.   int i, bit, result, color, pal_size, *mat,
  768.       count = 0, row = 0, modulo = 0;
  769.   short col_max = 0, col_min = 0, intensity[256],
  770.         first_plane[32], *plane, *idx, *end, *new_addr, *new;
  771.  
  772.   /* ordered dithering matrix */
  773.   static int matrix[16][16] =
  774.    {{0x00, 0xc0, 0x30, 0xf0, 0x0c, 0xcc, 0x3c, 0xfc,
  775.      0x03, 0xc3, 0x33, 0xf3, 0x0f, 0xcf, 0x3f, 0xff},
  776.     {0x80, 0x40, 0xb0, 0x70, 0x8c, 0x4c, 0xbc, 0x7c,
  777.      0x83, 0x43, 0xb3, 0x73, 0x8f, 0x4f, 0xbf, 0x7f},
  778.     {0x20, 0xe0, 0x10, 0xd0, 0x2c, 0xec, 0x1c, 0xdc,
  779.      0x23, 0xe3, 0x13, 0xd3, 0x2f, 0xef, 0x1f, 0xdf},
  780.     {0xa0, 0x60, 0x90, 0x50, 0xac, 0x6c, 0x9c, 0x5c,
  781.      0xa3, 0x63, 0x93, 0x53, 0xaf, 0x6f, 0x9f, 0x5f},
  782.     {0x08, 0xc8, 0x38, 0xf8, 0x04, 0xc4, 0x34, 0xf4,
  783.      0x0b, 0xcb, 0x3b, 0xfb, 0x07, 0xc7, 0x37, 0xf7},
  784.     {0x88, 0x48, 0xb8, 0x78, 0x84, 0x44, 0xb4, 0x74,
  785.      0x8b, 0x4b, 0xbb, 0x7b, 0x87, 0x47, 0xb7, 0x77},
  786.     {0x28, 0xe8, 0x18, 0xd8, 0x24, 0xe4, 0x14, 0xd4,
  787.      0x2b, 0xeb, 0x1b, 0xdb, 0x27, 0xe7, 0x17, 0xd7},
  788.     {0xa8, 0x68, 0x98, 0x58, 0xa4, 0x64, 0x94, 0x54,
  789.      0xab, 0x6b, 0x9b, 0x5b, 0xa7, 0x67, 0x97, 0x57},
  790.     {0x02, 0xc2, 0x32, 0xf2, 0x0e, 0xce, 0x3e, 0xfe,
  791.      0x01, 0xc1, 0x31, 0xf1, 0x0d, 0xcd, 0x3d, 0xfd},
  792.     {0x82, 0x42, 0xb2, 0x72, 0x8e, 0x4e, 0xbe, 0x7e,
  793.      0x81, 0x41, 0xb1, 0x71, 0x8d, 0x4d, 0xbd, 0x7d},
  794.     {0x22, 0xe2, 0x12, 0xd2, 0x2e, 0xee, 0x1e, 0xde,
  795.      0x21, 0xe1, 0x11, 0xd1, 0x2d, 0xed, 0x1d, 0xdd},
  796.     {0xa2, 0x62, 0x92, 0x52, 0xae, 0x6e, 0x9e, 0x5e,
  797.      0xa1, 0x61, 0x91, 0x51, 0xad, 0x6d, 0x9d, 0x5d},
  798.     {0x0a, 0xca, 0x3a, 0xfa, 0x06, 0xc6, 0x36, 0xf6,
  799.      0x09, 0xc9, 0x39, 0xf9, 0x05, 0xc5, 0x35, 0xf5},
  800.     {0x8a, 0x4a, 0xba, 0x7a, 0x86, 0x46, 0xb6, 0x76,
  801.      0x89, 0x49, 0xb9, 0x79, 0x85, 0x45, 0xb5, 0x75},
  802.     {0x2a, 0xea, 0x1a, 0xda, 0x26, 0xe6, 0x16, 0xd6,
  803.      0x29, 0xe9, 0x19, 0xd9, 0x25, 0xe5, 0x15, 0xd5},
  804.     {0xaa, 0x6a, 0x9a, 0x5a, 0xa6, 0x66, 0x96, 0x56,
  805.      0xa9, 0x69, 0x99, 0x59, 0xa5, 0x65, 0x95, 0x55}};
  806.  
  807.   /* allocate space for the new (dithered) bitmap */
  808.   if( (new_addr = (short *) malloc( size * sizeof(**addr) )) == NULL )
  809.     return( FALSE );
  810.  
  811.   pal_size = (1 << planes);
  812.  
  813.   /* scan palette */
  814.   if( pal_size <= 256 )
  815.   {
  816.     for( i = 0; i < pal_size; i ++ )
  817.     {
  818.       intensity[i] = 0;
  819.       /* add register values together to get the grey level */
  820.       for( bit = 0; bit < 3; bit ++ )
  821.       {
  822.         intensity[i] += *(palette + 3 * i + bit);
  823.       }
  824.       col_min = min( col_min, intensity[i] );
  825.       col_max = max( col_max, intensity[i] );
  826.     }
  827.     /* scale color values to 0 - 255 range */
  828.     for( i = 0; i < pal_size; i ++ )
  829.     {
  830.       intensity[i] = (long)(intensity[i] - col_min) * 255 / (col_max - col_min);
  831.     }
  832.   }
  833.  
  834.   /* destination pointer */
  835.   new = new_addr;
  836.   /* NOTICE: *addr + size = *addr + sizeof(**addr) * size!!! */
  837.   end = *addr + size;
  838.  
  839.   /* remake first bitplane */
  840.   for( idx = *addr; idx < end; idx ++ )
  841.   {
  842.     /* go through all bitplanes */
  843.     plane = first_plane;
  844.     for( i = 0; i < planes; i ++ )
  845.     {
  846.       /* get one word from a bitplane */
  847.       *(plane ++) = *(idx + size * (long)i);
  848.     }
  849.  
  850.     /* get row's modulo into dither matrix */
  851.     if( ++ count == width )
  852.     {
  853.       count = 0;
  854.       row ++;
  855.       modulo = row % 16;
  856.     }
  857.  
  858.     result = 0;
  859.     mat = matrix[modulo];
  860.  
  861.     /* go through one word */
  862.     for( bit = 15; bit >= 0; bit -- )
  863.     {
  864.       color = 0;
  865.       plane = first_plane;
  866.  
  867.       /* OR all 'bit' bits from all bitplanes together */
  868.       for( i = 0; i < planes; i ++ )
  869.         color |= ((*(plane ++) >> bit) & 1) << i;
  870.  
  871.       /* set bit in resulting bitplane if it its' intensity demands it */
  872.       if( intensity[color] < *(mat ++) )
  873.         result |= (short) 1 << bit;
  874.         
  875.     }
  876.     
  877.     *(new ++) = result;
  878.   }
  879.   *addr = new_addr;
  880.   return( TRUE );
  881. }
  882.  
  883.  
  884. /* convert bitplanes into interleaved bitplane */
  885. int interleave( int interleave, short **addr, long size, int planes )
  886. {
  887.   short *new_addr, *new, *idx, *start, *end;
  888.   int plane, limit;
  889.  
  890.   if( (new_addr = (short *) malloc( size * interleave * sizeof(*start) )) == NULL )
  891.     return( FALSE );
  892.  
  893.   /* if enough memory */
  894.   else
  895.   {
  896.     /* NOTICE: start + size = start + sizeof(*start) * size!!! */
  897.     start = *addr - size;
  898.     end = *addr;
  899.     limit = min( interleave, planes );
  900.  
  901.     /* interleave bitmaps (max. 'interleave' bitmaps) */
  902.     for( plane = 0; plane < limit; plane ++ )
  903.     {
  904.       /* interleaved bitmap start address */
  905.       new = new_addr + plane;
  906.  
  907.       /* current bitmap address */
  908.       start += size;
  909.       end   += size;
  910.  
  911.       /* copy one bitplane interleaved */
  912.       for( idx = start; idx < end; idx ++ )
  913.       {
  914.         *new = *idx;
  915.         new += interleave;
  916.       }
  917.     }
  918.  
  919.     /* if not enough bitmaps, interleave rest with previous bitmap */
  920.     for( plane = limit; plane < interleave; plane ++ )
  921.     {
  922.       new = new_addr + plane;
  923.  
  924.       for( idx = start; idx < end; idx ++ )
  925.       {
  926.         *new = *idx;
  927.         new += interleave;
  928.       }
  929.     }
  930.  
  931.     /* new address for the image (this one in device format) */
  932.     *addr = new_addr;
  933.   }
  934.  
  935.   return( TRUE );
  936. }
  937.  
  938. /* convert image using vr_trfm() */
  939. int convert( MFDB *image, long size, int planes, int img_handle )
  940. {
  941.   char *new_addr, *tmp;
  942.   int   plane;
  943.   MFDB tempscreen;
  944.  
  945.   /* convert size from words to bytes */
  946.   size <<= 1;
  947.  
  948.   /* memory for the device raster */
  949.   if( (new_addr = (char *) malloc( size * planes )) == NULL )
  950.     return( FALSE );
  951.  
  952.   memset(new_addr,0,(size * planes));    /*    -> fill with 0-planes */
  953.  
  954.   /* do we need a temporary conversion source raster? */
  955.   if( image->fd_nplanes < planes )
  956.   {
  957.  
  958.     /* memory for the standard (bitplane) raster */
  959.     if( (tmp = (char *) malloc( size * planes )) == NULL )
  960.       return( FALSE );
  961.  
  962.     memset(tmp,0,(size * planes));
  963.  
  964.     /* copy available bitplanes to the tmp */
  965.     memcpy( tmp, image->fd_addr, size * (long)image->fd_nplanes );
  966.  
  967.     /* fill the rest with the first bitplane */
  968.     for( plane = image->fd_nplanes; plane < planes; plane ++ )
  969.       memcpy( tmp + size * (long)plane, image->fd_addr, size );
  970.     
  971.     /* free old image->fd_addr */
  972.     free(image->fd_addr);
  973.   }
  974.   else
  975.     tmp = image->fd_addr;
  976.  
  977.   /* fill in the descriptions   */
  978.   image->fd_nplanes = planes;
  979.   tempscreen = *image;        /* copy MFDB       */
  980.   image->fd_stand = 1;    /* standard format */
  981.   image->fd_addr = tmp;
  982.   tempscreen.fd_addr = new_addr;
  983.  
  984.   /* convert image to current device raster format */
  985.   vr_trnfm( img_handle, image, &tempscreen); 
  986.  
  987.   /* free temporary space */
  988.   if( tmp != image->fd_addr )
  989.     free( tmp );
  990.     
  991.  
  992.   /* change image description */
  993.   image->fd_stand = 0;        /* device format */
  994.   image->fd_addr = new_addr;
  995.  
  996.   return( TRUE );
  997. }
  998.  
  999. /*
  1000.  *  You may ask why there is a routine for truecolor palettes
  1001.  * and one for planar palettes...
  1002.  *
  1003.  *  Well one works for planar modes and the other for truecolor
  1004.  * but neither seem to work well for both.
  1005.  *
  1006.  * As I've already spent about a month longer on this than I wanted,
  1007.  * I decided to just do it the way that works.
  1008.  *
  1009.  *  Sorry for the terrible programming - Dan Ackerman 1999
  1010.  */
  1011.  
  1012.  
  1013. /*  img_colors()
  1014.  *
  1015.  *  This version now just gets the image colors to an array
  1016.  * 
  1017.  *  The reason for this is that later the program will use
  1018.  * this array to map the image to the screen colors.  So it
  1019.  * no longer modifies the screen palette at all
  1020.  *
  1021.  *  New in version 1.9  September 29, 2000 -Dan Ackerman
  1022.  */
  1023.  
  1024. int
  1025. img_colors( int planes, int *palette , int col_handle)
  1026. {
  1027.   int i, pal_size;
  1028.  
  1029.   if( palette == NULL ) return(FALSE);
  1030.  
  1031.   pal_size = (1 << planes);
  1032.  
  1033.   /* scan palette */
  1034.   if( pal_size <= 256 )
  1035.   {
  1036.     for( i = 0; i < pal_size ; i ++ )
  1037.     {
  1038.         image_colortab[i].red = *(palette + 3 * i + 0);
  1039.         image_colortab[i].green = *(palette + 3 * i + 1);
  1040.         image_colortab[i].blue = *(palette + 3 * i + 2);
  1041.     }
  1042.   }
  1043.  
  1044.   return( TRUE );
  1045. }
  1046.  
  1047. /* Set the system colors to be the palette for Truecolor modes */
  1048. int truecolorimg_colors( int planes, int *palette , int col_handle)
  1049. {
  1050.   int i, pal_size, idx;
  1051.   int rgb_in[3];
  1052.  
  1053.   pal_size = (1 << planes);
  1054.  
  1055.   /* scan palette */
  1056.   if( pal_size <= 256 )
  1057.   {
  1058.  
  1059.     for( i = 0; i < pal_size ; i ++ )
  1060.     {
  1061.         idx = i;
  1062. /*        switch(planes)
  1063.         {
  1064.             case 2:
  1065.                 idx = vditodev2[i];
  1066.                 break;
  1067.             case 4:
  1068.                 idx = vditodev4[i];
  1069.                 break;
  1070.             case 8:
  1071.                 idx = vditodev8[i];
  1072.                 break;
  1073.             default:
  1074.                 idx = i;
  1075.         }*/
  1076.  
  1077.     rgb_idx[idx][0] = *(palette + 3 * i + 0);
  1078.     rgb_idx[idx][1] = *(palette + 3 * i + 1);
  1079.     rgb_idx[idx][2] = *(palette + 3 * i + 2);
  1080.  
  1081.     rgb_in[0] = rgb_idx[idx][0];
  1082.     rgb_in[1] = rgb_idx[idx][1];
  1083.     rgb_in[2] = rgb_idx[idx][2];
  1084.     
  1085.     vs_color(col_handle,i,rgb_in);
  1086.     }
  1087.   }
  1088.  
  1089.   return( TRUE );
  1090. }
  1091.  
  1092. /*
  1093.  *  Mono Transform
  1094.  *
  1095.  *  This allows us to take a mono image up to a higher bit depth
  1096.  * and color it with a specified color.  So that mono images need
  1097.  * not remain mono.
  1098.  *
  1099.  * color flag is what color you want the foreground to be set to
  1100.  * keep_original - if true it does not free the original buffer
  1101.  */
  1102.  
  1103. int
  1104. mono_transform( MFDB *image, long size, int planes, int img_handle, int color, int keep_original)
  1105. {
  1106.   short *new_addr;
  1107.   MFDB tempscreen;
  1108.   MFDB temp;
  1109.   int pxy[8];
  1110.   int colors[2];
  1111.  
  1112.   /* convert size from words to bytes */
  1113.   size <<= 1;
  1114.  
  1115.   /* memory for the device raster */
  1116.   if( (new_addr = (char *) malloc( size * planes )) == NULL )
  1117.     return( FALSE );
  1118.  
  1119.   if (planes > 8)
  1120.       memset(new_addr,255,(size * planes));    /*    -> fill with 255-planes */
  1121.   else
  1122.       memset(new_addr,0,(size * planes));    /*    -> fill with 0-planes */
  1123.  
  1124.   /* fill in the descriptions   */
  1125.   image->fd_nplanes = planes;
  1126.   tempscreen = *image;        /* copy MFDB       */
  1127.   image->fd_stand = 0;    /* standard format */
  1128.   tempscreen.fd_addr = new_addr;
  1129.  
  1130.   temp = *image;
  1131.   temp.fd_stand = 0;
  1132.   temp.fd_nplanes = 1;
  1133.   pxy[0] = pxy[4] = 0;
  1134.   pxy[1] = pxy[5] = 0;
  1135.   pxy[2] = pxy[6] = image->fd_w - 1;
  1136.   pxy[3] = pxy[7] = image->fd_h - 1;
  1137.  
  1138.   /* If you don't do the following monochrome images are inverted */
  1139.   colors[0] = color;
  1140.   colors[1] = 1;
  1141.     
  1142.   vrt_cpyfm( img_handle,MD_TRANS,pxy,&temp,&tempscreen,colors);
  1143.  
  1144.   if (!keep_original)
  1145.       free(image->fd_addr);
  1146.  
  1147.   /* change image description */
  1148.   image->fd_stand = 0;        /* device format */
  1149.   image->fd_addr = new_addr;
  1150.  
  1151.   return( TRUE );
  1152.  
  1153. }
  1154.  
  1155.  
  1156. #ifndef OS_TOS
  1157.  
  1158. /*
  1159.  * transform_truecolor
  1160.  *
  1161.  * MFDB *image -> image of bitmap you want converted
  1162.  * long size -> size in words of necessary buffer
  1163.  * int planes -> number of planes you wish to convert bitmap to
  1164.  * int img_handle -> vdi_handle for current work
  1165.  *
  1166.  * This routine isn't the fastest thing on the planet but it works
  1167.  * and should be readily understandable.
  1168.  *
  1169.  * Mario Becroft has a routine that is much faster in a lib
  1170.  * he is working on at the moment.
  1171.  * However he's not quite ready to release it yet (august 1999)
  1172.  *  - Dan Ackerman (baldrick@netset.com) august 1999
  1173.  *
  1174.  *  KEPT IN CODE IN CASE NEW ROUTINES NOT PC GEM COMPATIBLE
  1175.  *   (Dan March 2000)
  1176.  */
  1177.  
  1178. int
  1179. transform_truecolor( MFDB *image, long size, int planes, int img_handle)
  1180. {
  1181.   char *new_addr, *monotmp;
  1182.   MFDB tempscreen;
  1183.   MFDB temp;
  1184.   MFDB monotemp;
  1185.   int pxy[8];
  1186.   int colors[2];
  1187.   int i,ccount;
  1188.   int tot_colors = (1 << image->fd_nplanes);
  1189.   int oldplanes;
  1190.   char *plane8, *plane7, *plane6, *plane5, *plane4,
  1191.           *plane3, *plane2, *plane1;
  1192.  
  1193.  
  1194.   oldplanes = image->fd_nplanes;
  1195.  
  1196.   /* convert size from words to bytes */
  1197.   size <<= 1;
  1198.  
  1199.   /* memory for the device raster */
  1200.   if( (new_addr = (char *) malloc( size * planes )) == NULL )
  1201.     return( FALSE );
  1202.  
  1203.   memset(new_addr,0,(size * planes));    /*    -> fill with 0-planes */
  1204.  
  1205.   if( (monotmp = (char *) malloc( size)) == NULL )
  1206.     return( FALSE );
  1207.  
  1208.   memset(monotmp,0,(size));
  1209.  
  1210.   /* fill in the descriptions   */
  1211.   image->fd_nplanes = planes;
  1212.   tempscreen = *image;        /* copy MFDB       */
  1213.   image->fd_stand = 1;    /* standard format */
  1214.   tempscreen.fd_addr = new_addr;
  1215.  
  1216.   monotemp = temp = *image;
  1217.   monotemp.fd_stand = temp.fd_stand = 0;
  1218.   monotemp.fd_nplanes = temp.fd_nplanes = 1;
  1219.   pxy[0] = pxy[4] = 0;
  1220.   pxy[1] = pxy[5] = 0;
  1221.   pxy[2] = pxy[6] = image->fd_w - 1;
  1222.   pxy[3] = pxy[7] = image->fd_h - 1;
  1223.  
  1224.   /* If you don't do the following monochrome images are inverted */
  1225.   colors[0] = 0;
  1226.  
  1227.   if (oldplanes == 1)
  1228.       colors[1] = 1;
  1229.   else
  1230.       colors[1] = 0;
  1231.     
  1232.   vrt_cpyfm( img_handle,MD_REPLACE,pxy,&temp,&tempscreen,colors);
  1233.  
  1234.   monotemp.fd_addr = monotmp;
  1235.  
  1236.   if(oldplanes > 1)
  1237.   {
  1238.     plane1 = (char*)image->fd_addr;
  1239.     plane2 = (char*)image->fd_addr + size;
  1240.     plane3 = (char*)image->fd_addr + (size * 2);
  1241.     plane4 = (char*)image->fd_addr + (size * 3);
  1242.  
  1243.     if (tot_colors > 16)
  1244.     {
  1245.         plane5 = (char*)image->fd_addr + (size * 4);
  1246.         plane6 = (char*)image->fd_addr + (size * 5);
  1247.         plane7 = (char*)image->fd_addr + (size * 6);
  1248.         plane8 = (char*)image->fd_addr + (size * 7);
  1249.     }
  1250.  
  1251.     for (i = 1; i < tot_colors; i++)
  1252.     {
  1253.         /* set ccount to current index */
  1254.         ccount = i;
  1255.  
  1256.         evnt_timer(1,0);
  1257.  
  1258.         memset(monotmp,255,(size));
  1259.     
  1260.         if (tot_colors > 16)
  1261.         {
  1262.             if (ccount & 0x80)
  1263.             {
  1264.                 temp.fd_addr = plane8;
  1265.                 vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1266.             }
  1267.  
  1268.             if (ccount & 0x40)
  1269.             {
  1270.                 temp.fd_addr = plane7;                                      
  1271.                 vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1272.             }
  1273.  
  1274.             if (ccount & 0x20)
  1275.             {
  1276.                 temp.fd_addr = plane6;
  1277.                 vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1278.             }
  1279.             
  1280.             if (ccount & 0x10)
  1281.             {
  1282.                 temp.fd_addr = plane5;                            
  1283.                 vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1284.             }
  1285.         }
  1286.         
  1287.         if (ccount & 0x08)
  1288.         {
  1289.             temp.fd_addr = plane4;                
  1290.             vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1291.         }
  1292.  
  1293.         if (ccount & 0x04)
  1294.         {
  1295.             temp.fd_addr = plane3;
  1296.             vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1297.         }
  1298.         
  1299.         if (ccount & 0x02)
  1300.         {
  1301.             temp.fd_addr = plane2;                            
  1302.             vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1303.         }
  1304.         
  1305.         if (ccount & 0x01)
  1306.         {
  1307.             temp.fd_addr = plane1;                        
  1308.             vro_cpyfm( img_handle,S_AND_D,pxy,&temp,&monotemp);
  1309.         }
  1310.         
  1311.         colors[0] = i;
  1312.         vrt_cpyfm(img_handle,MD_TRANS,pxy,&monotemp,&tempscreen,colors);
  1313.     }
  1314.   }
  1315.  
  1316.   free(monotmp);
  1317.   free(image->fd_addr);
  1318.  
  1319.   /* change image description */
  1320.   image->fd_stand = 0;        /* device format */
  1321.   image->fd_addr = new_addr;
  1322.  
  1323.   return( TRUE );
  1324.  
  1325. }
  1326. #else
  1327.  
  1328.  
  1329.  
  1330. /*  The new transform truecolor
  1331.  *
  1332.  *  This routine borrows heavily on two sources.
  1333.  *  1. Mario Becrofts transform function
  1334.  *  2. Eero Tammiens dither function
  1335.  *
  1336.  *  Marios routine never worked for me properly under PureC,
  1337.  * it's very possible that was my fault.  However on reflection
  1338.  * I saw that what he was doing was very similar to the dither
  1339.  * routine I was already using.  So I used Mario Becrofts strategy
  1340.  * combined with Eero Tammiens tactics and came up with the following
  1341.  * routine.
  1342.  * 
  1343.  *  I can see the possibility of a few minor tweaks that may make
  1344.  * this routine faster.  For the moment I'm happy with it.  Its significantly
  1345.  * faster than the old one I wrote (which still exists in the code for
  1346.  * anyone interested in porting this program to a non motorola platform)
  1347.  * 
  1348.  *  variables
  1349.  * MFDB *image -> MFDB of the image we want to convert to the current bit depth
  1350.  * size           -> size of buffer of the image. (could probably reconstruct, but
  1351.  *                                                we already have this value beforehand)
  1352.  * planes       -> Number of planes = current bit depth
  1353.  * img_handle  -> Our VDI_handle for vdi functions    
  1354.  *
  1355.  * Dan Ackerman ( March 7, 2000)
  1356.  */
  1357.  
  1358. int 
  1359. transform_truecolor( MFDB *image, long size, int planes, int img_handle)
  1360. {
  1361.  int i, bit, color, mask;
  1362.  short first_plane[32], *plane, *idx, *new_addr;
  1363.  short *color_table, *bit_location, *temp_addr;
  1364.  int tot_colors = (1 << image->fd_nplanes);
  1365.  char used_colors[256];
  1366.  int x, y;
  1367.  MFDB tempscreen;
  1368.  MFDB temp;
  1369.  int pxy[8], colors[2];
  1370.  long temp_size;
  1371.   
  1372.   if (image->fd_nplanes == 1)
  1373.     return(mono_transform(image, size, planes, img_handle, 1, 0));
  1374.  
  1375.   /* memory for the device raster */
  1376.   if( (new_addr = (short *) malloc( (size << 1) * planes )) == NULL )
  1377.     return( FALSE );
  1378.  
  1379.   memset(new_addr,0,((size << 1) * planes));    /*    -> fill with 0-planes */
  1380.  
  1381.   /* fill in the descriptions   */
  1382.   image->fd_nplanes = planes;
  1383.   tempscreen = *image;        /* copy MFDB       */
  1384.   image->fd_stand = 1;    /* standard format */
  1385.   tempscreen.fd_addr = new_addr;
  1386.  
  1387.   temp = *image;
  1388.   temp.fd_stand = 0;
  1389.   temp.fd_nplanes = 1;
  1390.   temp.fd_h = tot_colors;
  1391.  
  1392.   temp_size = tot_colors * temp.fd_wdwidth;
  1393.   temp_size <<= 1;
  1394.   
  1395.   if( (temp_addr = (short *) malloc(temp_size)) == NULL )
  1396.        return( FALSE );
  1397.  
  1398.   memset(temp_addr,255,(temp_size));    /*    -> fill with 0-planes */
  1399.   
  1400.   temp.fd_addr = temp_addr;
  1401.   
  1402.   pxy[0] = pxy[4] = 0;
  1403.   pxy[1] = pxy[5] = 0;
  1404.   pxy[2] = pxy[6] = image->fd_w-1;
  1405.   pxy[3] = pxy[7] = image->fd_h-1;
  1406.  
  1407.   /* If you don't do the following monochrome images are inverted */
  1408.   colors[1] = 0;
  1409.  
  1410.   mask = tot_colors - 1;
  1411.  
  1412.   idx = (short *)image->fd_addr;
  1413.   
  1414.   bit_location = color_table = (short *)temp_addr;
  1415.   
  1416.   for (y = 0; y < image->fd_h; y++)
  1417.     {
  1418.         memset(temp_addr,0,temp_size);
  1419.         memset( used_colors, 0, sizeof( used_colors ) );
  1420.     
  1421.         for (x = 0; x < image->fd_wdwidth; x++)
  1422.         {
  1423.             /* go through all bitplanes */
  1424.             plane = first_plane;
  1425.  
  1426.             for( i = 0; i < image->fd_nplanes; i ++ )
  1427.             {
  1428.               /* get one word from a bitplane */
  1429.               *(plane ++) = *(idx + size * (long)i);
  1430.             }
  1431.  
  1432.             /* go through one word */
  1433.             for( bit = 15; bit >= 0; bit -- )
  1434.             {
  1435.               color = 0;
  1436.               plane = first_plane;
  1437.  
  1438.               /* OR all 'bit' bits from all bitplanes together */
  1439.               for( i = 0; i < image->fd_nplanes; i ++ )
  1440.                 color |= ((*(plane ++) >> bit) & 1) << i;
  1441.       
  1442.               color &= mask;
  1443.  
  1444.               used_colors[color] = 1;
  1445.  
  1446.               bit_location =  (short *)(color_table + (temp.fd_wdwidth * (long)color) + x);
  1447.     
  1448.               *bit_location |= 1 << bit;
  1449.             }
  1450.  
  1451.             idx++; /* increment idx */
  1452.         }
  1453.  
  1454.         /* if we've gone to the end of a row update now */
  1455.  
  1456.         pxy[5] = pxy[7] = y;
  1457.  
  1458.         for (i=0;i<tot_colors;i++)
  1459.         {
  1460.               if(used_colors[i])
  1461.               {
  1462.                 colors[0] = i;
  1463.                   pxy[1] = pxy[3] = i;
  1464.                     vrt_cpyfm( img_handle, MD_TRANS, pxy, &temp, &tempscreen, colors );
  1465.             }
  1466.  
  1467.         }
  1468.  
  1469.     }
  1470.  
  1471.   free(temp_addr);
  1472.   free(image->fd_addr);
  1473.   image->fd_stand = 0;    /* standard format */
  1474.  
  1475.   image->fd_addr = new_addr;
  1476.   return( TRUE );
  1477. }
  1478. #endif
  1479.  
  1480. /* Tests a color, default set for large screens 
  1481.  *  Simply away for showing a big block of color on 
  1482.  * the screen while debugging these routines
  1483.  */
  1484. int test_color( int color, int img_handle )
  1485. {
  1486.   int pxy[4];
  1487.  
  1488.     pxy[0] = 0;
  1489.       pxy[1] = 0;/*+(50*color);*/
  1490.       pxy[2] = 50;
  1491.       pxy[3] = 50;/*+(50*color);*/
  1492.  
  1493.     vsm_type(img_handle, 1);
  1494.  
  1495.     vsf_interior(img_handle,1);
  1496.     vsf_color(img_handle, color);
  1497.     v_bar(img_handle, pxy);
  1498.     
  1499.   return( TRUE );
  1500. }
  1501.  
  1502. /* Color Square
  1503.  * Used for drawing a solid square of a single
  1504.  * color to the screen.
  1505.  *
  1506.  * img_handle is the vdi handle we are working with
  1507.  * color is the color you want to display
  1508.  * x is x location
  1509.  * y is y location
  1510.  * w is width and height (remember this is just a square )
  1511.  */
  1512. int
  1513. color_square( int img_handle, int color, int x, int y, int w )
  1514. {
  1515.   int pxy[4];
  1516.  
  1517.     pxy[0] = x;
  1518.       pxy[1] = y;
  1519.       pxy[2] = x + w;
  1520.       pxy[3] = y + w;
  1521.  
  1522.     vsm_type(img_handle, 1);
  1523.  
  1524.     vsf_interior(img_handle,1);
  1525.     vsf_color(img_handle, color);
  1526.     v_bar(img_handle, pxy);
  1527.     
  1528.   return( TRUE );
  1529. }
  1530.  
  1531. /*  The transform with remapping
  1532.  *
  1533.  *  This is a rework of transform_truecolor to handle
  1534.  * remapping to the system pallete on planar modes
  1535.  * 
  1536.  *  variables
  1537.  * MFDB *image -> MFDB of the image we want to convert to the current bit depth
  1538.  * size           -> size of buffer of the image. (could probably reconstruct, but
  1539.  *                                                we already have this value beforehand)
  1540.  * planes       -> Number of planes = current bit depth
  1541.  * img_handle  -> Our VDI_handle for vdi functions    
  1542.  *
  1543.  * Dan Ackerman ( March 7, 2000)
  1544.  */
  1545.  
  1546. int 
  1547. transform_remap( MFDB *image, long size, int planes, int img_handle)
  1548. {
  1549.  int i, ii, bit, color, mask;
  1550.  short first_plane[32], *plane, *idx, *new_addr;
  1551.  short *color_table, *bit_location, *temp_addr;
  1552.  int tot_colors = (1 << image->fd_nplanes);
  1553.  char used_colors[256];
  1554.  int remap_colors[256];
  1555.  int x, y;
  1556.  MFDB tempscreen;
  1557.  MFDB temp;
  1558.  int pxy[8], colors[2];
  1559.  long temp_size;
  1560.   int hit_color = 0;
  1561.   RGB1000 best; /* used to temp hold the difference best color match */
  1562.   int bestno;   /* color index for best match */
  1563.   int res_colors = (1 << planes); /* Doesn't work in truecolor modes, only planar */
  1564.   
  1565.   if (image->fd_nplanes == 1)
  1566.     return(mono_transform(image, size, planes, img_handle, 1, 0));
  1567.  
  1568.   /* memory for the device raster */
  1569.   if( (new_addr = (short *) malloc( (size << 1) * planes )) == NULL )
  1570.     return( FALSE );
  1571.  
  1572.   memset(new_addr,0,((size << 1) * planes));    /*    -> fill with 0-planes */
  1573.  
  1574.   /* fill in the descriptions   */
  1575.   image->fd_nplanes = planes;
  1576.   tempscreen = *image;        /* copy MFDB       */
  1577.   image->fd_stand = 1;    /* standard format */
  1578.   tempscreen.fd_addr = new_addr;
  1579.  
  1580.   temp = *image;
  1581.   temp.fd_stand = 0;
  1582.   temp.fd_nplanes = 1;
  1583.   temp.fd_h = tot_colors;
  1584.  
  1585.   temp_size = tot_colors * temp.fd_wdwidth;
  1586.   temp_size <<= 1;
  1587.   
  1588.   if( (temp_addr = (short *) malloc(temp_size)) == NULL )
  1589.        return( FALSE );
  1590.  
  1591.   memset(temp_addr,255,(temp_size));    /*    -> fill with 0-planes */
  1592.   
  1593.   temp.fd_addr = temp_addr;
  1594.   
  1595.   /* remap the color pallete of image */
  1596.   
  1597.   for (i = 0; i < tot_colors; i++)
  1598.   {
  1599.       ii = 0;
  1600.       hit_color = 0;
  1601.  
  1602.     do
  1603.       {
  1604.  
  1605.           if ((image_colortab[i].red == screen_colortab[ii].red)&&
  1606.             (image_colortab[i].green == screen_colortab[ii].green)&&
  1607.             (image_colortab[i].blue == screen_colortab[ii].blue))
  1608.             {
  1609.                 remap_colors[i] = ii;
  1610.                 hit_color = 1;
  1611.                 break;
  1612.             }
  1613.                 
  1614.         ii++;
  1615.       }while(ii < res_colors);
  1616.     
  1617.     /* We didn't get an exact match, so approximate */
  1618.       if(hit_color == 0)
  1619.       {
  1620.         /* set best color match to 0*/
  1621.         bestno = 0;
  1622.  
  1623.         /* set initial differences to 1000, ensures that initial value is worst possible */
  1624.         best.red = 1000;
  1625.         best.green = 1000;
  1626.         best.blue = 1000;
  1627.  
  1628.         ii = 0;
  1629.  
  1630.         do
  1631.           {
  1632.  
  1633.             if (image_colortab[i].red > screen_colortab[ii].red)
  1634.             {
  1635.                 if((image_colortab[i].red - screen_colortab[ii].red) <= best.red)
  1636.                 {
  1637.                     if (image_colortab[i].green > screen_colortab[ii].green)
  1638.                     {
  1639.                         if((image_colortab[i].green - screen_colortab[ii].green) <= best.green)
  1640.                         {
  1641.                             if (image_colortab[i].blue > screen_colortab[ii].blue)
  1642.                             {
  1643.                                 if((image_colortab[i].blue - screen_colortab[ii].blue) <= best.blue)
  1644.                                 {
  1645.                                     bestno = ii;
  1646.                                     best.red = (image_colortab[i].red - screen_colortab[ii].red);
  1647.                                     best.green = (image_colortab[i].green - screen_colortab[ii].green);
  1648.                                     best.blue = (image_colortab[i].blue - screen_colortab[ii].blue);
  1649.                                 }
  1650.                             }
  1651.                             else
  1652.                             {
  1653.                                 if((screen_colortab[ii].blue - image_colortab[i].blue) <= best.blue)
  1654.                                 {
  1655.                                     bestno = ii;
  1656.                                     best.red = (image_colortab[i].red - screen_colortab[ii].red);
  1657.                                     best.green = (image_colortab[i].green - screen_colortab[ii].green);
  1658.                                     best.blue = (screen_colortab[ii].blue - image_colortab[i].blue);
  1659.                                 }                            
  1660.                             }
  1661.                         }
  1662.                     }
  1663.                     else
  1664.                     {
  1665.                         if((screen_colortab[ii].green - image_colortab[i].green) <= best.green)
  1666.                         {
  1667.                             if (image_colortab[i].blue > screen_colortab[ii].blue)
  1668.                             {
  1669.                                 if((image_colortab[i].blue - screen_colortab[ii].blue) <= best.blue)
  1670.                                 {
  1671.                                     bestno = ii;
  1672.                                     best.red = (image_colortab[i].red - screen_colortab[ii].red);
  1673.                                     best.green = (screen_colortab[ii].green - image_colortab[i].green);
  1674.                                     best.blue = (image_colortab[i].blue - screen_colortab[ii].blue);
  1675.                                 }
  1676.                             }
  1677.                             else
  1678.                             {
  1679.                                 if((screen_colortab[ii].blue - image_colortab[i].blue) <= best.blue)
  1680.                                 {
  1681.                                     bestno = ii;
  1682.                                     best.red = (image_colortab[i].red - screen_colortab[ii].red);
  1683.                                     best.green = (screen_colortab[ii].green - image_colortab[i].green);
  1684.                                     best.blue = (screen_colortab[ii].blue - image_colortab[i].blue);
  1685.                                 }                            
  1686.                             }
  1687.                         }
  1688.                     }
  1689.                 }
  1690.  
  1691.             }
  1692.             else
  1693.             {
  1694.                 if((screen_colortab[ii].red - image_colortab[i].red) <= best.red)
  1695.                 {
  1696.                     if (image_colortab[i].green > screen_colortab[ii].green)
  1697.                     {
  1698.                         if((image_colortab[i].green - screen_colortab[ii].green) <= best.green)
  1699.                         {
  1700.                             if (image_colortab[i].blue > screen_colortab[ii].blue)
  1701.                             {
  1702.                                 if((image_colortab[i].blue - screen_colortab[ii].blue) <= best.blue)
  1703.                                 {
  1704.                                     bestno = ii;
  1705.                                     best.red = (screen_colortab[ii].red - image_colortab[i].red);
  1706.                                     best.green = (image_colortab[i].green - screen_colortab[ii].green);
  1707.                                     best.blue = (image_colortab[i].blue - screen_colortab[ii].blue);
  1708.                                 }
  1709.                             }
  1710.                             else
  1711.                             {
  1712.                                 if((screen_colortab[ii].blue - image_colortab[i].blue) <= best.blue)
  1713.                                 {
  1714.                                     bestno = ii;
  1715.                                     best.red = (screen_colortab[ii].red - image_colortab[i].red);
  1716.                                     best.green = (image_colortab[i].green - screen_colortab[ii].green);
  1717.                                     best.blue = (screen_colortab[ii].blue - image_colortab[i].blue);
  1718.                                 }                            
  1719.                             }
  1720.                         }
  1721.                     }
  1722.                     else
  1723.                     {
  1724.                         if((screen_colortab[ii].green - image_colortab[i].green) <= best.green)
  1725.                         {
  1726.                             if (image_colortab[i].blue > screen_colortab[ii].blue)
  1727.                             {
  1728.                                 if((image_colortab[i].blue - screen_colortab[ii].blue) <= best.blue)
  1729.                                 {
  1730.                                     bestno = ii;
  1731.                                     best.red = (screen_colortab[ii].red - image_colortab[i].red);
  1732.                                     best.green = (screen_colortab[ii].green - image_colortab[i].green);
  1733.                                     best.blue = (image_colortab[i].blue - screen_colortab[ii].blue);
  1734.                                 }
  1735.                             }
  1736.                             else
  1737.                             {
  1738.                                 if((screen_colortab[ii].blue - image_colortab[i].blue) <= best.blue)
  1739.                                 {
  1740.                                     bestno = ii;
  1741.                                     best.red = (screen_colortab[ii].red - image_colortab[i].red);
  1742.                                     best.green = (screen_colortab[ii].green - image_colortab[i].green);
  1743.                                     best.blue = (screen_colortab[ii].blue - image_colortab[i].blue);
  1744.                                 }                            
  1745.                             }
  1746.                         }
  1747.                     }
  1748.                 }
  1749.             }
  1750.  
  1751.             ii++;
  1752.           }while(ii < res_colors);
  1753.  
  1754. /*        printf("best no = %d\r\n",bestno);*/
  1755.           
  1756.         remap_colors[i] = bestno;
  1757.       }
  1758.   }
  1759.   
  1760.   /* setup copy array */
  1761.   pxy[0] = pxy[4] = 0;
  1762.   pxy[1] = pxy[5] = 0;
  1763.   pxy[2] = pxy[6] = image->fd_w-1;
  1764.   pxy[3] = pxy[7] = image->fd_h-1;
  1765.  
  1766.   /* If you don't do the following monochrome images are inverted */
  1767.   colors[1] = 0;
  1768.  
  1769.   mask = tot_colors - 1;
  1770.  
  1771.   idx = (short *)image->fd_addr;
  1772.   
  1773.   bit_location = color_table = (short *)temp_addr;
  1774.   
  1775.   for (y = 0; y < image->fd_h; y++)
  1776.     {
  1777.         memset(temp_addr,0,temp_size);
  1778.         memset( used_colors, 0, sizeof( used_colors ) );
  1779.     
  1780.         for (x = 0; x < image->fd_wdwidth; x++)
  1781.         {
  1782.             /* go through all bitplanes */
  1783.             plane = first_plane;
  1784.  
  1785.             for( i = 0; i < image->fd_nplanes; i ++ )
  1786.             {
  1787.               /* get one word from a bitplane */
  1788.               *(plane ++) = *(idx + size * (long)i);
  1789.             }
  1790.  
  1791.             /* go through one word */
  1792.             for( bit = 15; bit >= 0; bit -- )
  1793.             {
  1794.               color = 0;
  1795.               plane = first_plane;
  1796.  
  1797.               /* OR all 'bit' bits from all bitplanes together */
  1798.               for( i = 0; i < image->fd_nplanes; i ++ )
  1799.                 color |= ((*(plane ++) >> bit) & 1) << i;
  1800.       
  1801.               color &= mask;
  1802.  
  1803.               used_colors[color] = 1;
  1804.  
  1805.               bit_location =  (short *)(color_table + (temp.fd_wdwidth * (long)color) + x);
  1806.     
  1807.               *bit_location |= 1 << bit;
  1808.             }
  1809.  
  1810.             idx++; /* increment idx */
  1811.         }
  1812.  
  1813.         /* if we've gone to the end of a row update now */
  1814.  
  1815.         pxy[5] = pxy[7] = y;
  1816.  
  1817.         for (i=0;i<tot_colors;i++)
  1818.         {
  1819.               if(used_colors[i])
  1820.               {
  1821.                 colors[0] = remap_colors[i];
  1822.                   pxy[1] = pxy[3] = i;
  1823.                     vrt_cpyfm( img_handle, MD_TRANS, pxy, &temp, &tempscreen, colors );
  1824.             }
  1825.  
  1826.         }
  1827.  
  1828.     }
  1829.  
  1830.   free(temp_addr);
  1831.   free(image->fd_addr);
  1832.   image->fd_stand = 0;    /* standard format */
  1833.  
  1834.   image->fd_addr = new_addr;
  1835.   return( TRUE );
  1836. }
  1837.