home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / pal / testp.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  24KB  |  1,133 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <conio.h>
  16. #include <math.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <fcntl.h>
  21. #include <io.h>
  22. #include <dos.h>
  23. #include <malloc.h>
  24. #include <ctype.h>
  25.  
  26. #include "gr.h"
  27. #include "ui.h"
  28. #include "key.h"
  29.  
  30.  
  31. extern void gr_pal_setblock(int start, int stop, void * colors );
  32.  
  33. typedef unsigned char   BYTE;
  34. typedef unsigned short  WORD;
  35. typedef unsigned int    DWORD;
  36.  
  37. #define GAMMA  1.3
  38.  
  39. #define CUBE(x) ((x)*(x)*(x))
  40. #define SQUARE(x) ((x)*(x))
  41.  
  42. #define BM_LINEAR   0
  43. #define BM_MODEX    1
  44. #define BM_SVGA     2
  45. #define BM_RGB15    3   //5 bits each r,g,b stored at 16 bits
  46.  
  47. typedef struct  {
  48.     WORD        X, Y;
  49.     WORD        Width;
  50.     WORD        Height;
  51.     WORD        Type;
  52.     WORD        Rowsize;
  53.     DWORD       DataPtr;
  54.     WORD        Data[1];
  55. } BITMAP15;
  56.  
  57. typedef struct  {
  58.     WORD        X, Y;
  59.     WORD        Width;
  60.     WORD        Height;
  61.     WORD        Type;
  62.     WORD        Rowsize;
  63.     DWORD       DataPtr;
  64.     BYTE        Data[1];
  65. } BITMAP8;
  66.  
  67. extern BITMAP15 * IFF_To_15BPP(char * ifilename);
  68.  
  69. typedef struct  {
  70.     BYTE        Red;
  71.     BYTE        Green;
  72.     BYTE        Blue;
  73. } RGB;
  74.  
  75. typedef struct
  76. {
  77.     int Lo[3];
  78.     int Hi[3];
  79.     int NumElements;
  80. } BOX;
  81.  
  82.  
  83. BOX Boxes[256];             // The color boxes that we want to fill
  84. RGB ColRegs[256];           // The palette entries that we fill
  85. int * RGBCube = NULL;         // Used to count the color frequencies in the original image.
  86.  
  87. void *bmd_fade_table;
  88.  
  89. BYTE * AverageTable;
  90. BYTE ColorTable[16][256];
  91. BYTE * LookupTable;
  92.  
  93. int Usage[256];
  94. int NumBoxes;
  95. int TotalPixels;
  96. int TotalPixels1;
  97. int AllowedColors = 256;
  98. BYTE Gamma32[32];
  99. BYTE Gamma64[32];
  100.  
  101. int WorstError;
  102. BYTE WorstRed, WorstGreen, WorstBlue;
  103.  
  104. char * Filename[25];
  105. BITMAP15 * Image15[25];
  106. BITMAP8 * Image8[25];
  107. int NumImages = 0;
  108.  
  109. char temp[200];
  110.  
  111. int RequestedColors;
  112.  
  113. void * ReadFile( char * filename, int * length )
  114. {
  115.     void * FileData;
  116.     int handle;
  117.  
  118.     handle = open( filename, O_RDONLY | O_BINARY );
  119.     if (handle == -1 ) {
  120.         printf( "Unable to open '%s'\n", filename );
  121.         exit(1);
  122.     }
  123.  
  124.     *length = filelength( handle );
  125.  
  126.     FileData = (void * )malloc( *length );
  127.  
  128.     if (FileData == NULL )  {
  129.         close( handle );
  130.         printf( "Not enough memory to read in file '%s'\n", filename );
  131.         exit(1);
  132.     }
  133.  
  134.     if (read( handle, FileData, *length ) != *length )    {
  135.         printf( "Error reading in '%s' data.\n", filename );
  136.         free( FileData );
  137.         close( handle );
  138.         exit(1);
  139.     }
  140.     close( handle );
  141.  
  142.     return FileData;
  143.  
  144. }
  145.  
  146. void WriteFile( char * filename, void * data, int length )
  147. {
  148.     int handle;
  149.  
  150.     handle = open( filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
  151.     if (handle == -1 ) {
  152.         printf( "Error opening output file '%s'\n", filename );
  153.         exit(1);
  154.     }
  155.     if (write( handle, data, length )!=length)  {
  156.         printf( "Error writing output file '%s'\n", filename );
  157.         close( handle );
  158.         exit(1);
  159.     }
  160.  
  161.     close( handle );
  162. }
  163.  
  164.  
  165.  
  166. void InitializeMixer()
  167. {
  168.     int i;
  169.  
  170.     printf( "Initializing mixer...\n" );
  171.  
  172.     TotalPixels = 0;
  173.  
  174.  
  175.     if (RGBCube==NULL )
  176.     {
  177.         RGBCube = (int *)malloc(32*32*32*sizeof(int));
  178.         if (RGBCube==NULL) exit(1);
  179.     }
  180.  
  181.     for (i=0; i<32768; i++ )
  182.     {
  183.         RGBCube[i] = 0;
  184.     }
  185.  
  186.     for (i=0; i<256; i++ )
  187.         Usage[i] = 0;
  188. }
  189.  
  190.  
  191. void FillGamma() {
  192.     double intensity;
  193.     int i;
  194.     int sellevels, pallevels;
  195.  
  196.     sellevels = 31;
  197.     pallevels = 63;
  198.  
  199.     Gamma64[0] = 0;
  200.     for (i=1; i<=sellevels; i++) {
  201.         intensity = (double)i/(double)sellevels;
  202.         Gamma64[i] = (BYTE)((pow(intensity, 1.0/GAMMA)*pallevels) + 0.5);
  203.     }
  204.  
  205.     sellevels = 31;
  206.     pallevels = 31;
  207.  
  208.     Gamma32[0] = 0;
  209.     for (i=1; i<=sellevels; i++) {
  210.         intensity = (double)i/(double)sellevels;
  211.         Gamma32[i] = (BYTE)((pow(intensity, 1.0/GAMMA)*pallevels) + 0.5);
  212.     }
  213. }
  214.  
  215.  
  216.  
  217. void ScanColorFrequencies( BITMAP15 * buf, char * filename )
  218. {
  219.     int i;
  220.     int r, g, b, max;
  221.  
  222.     printf( "Factoring in %s's colors...\n", filename );
  223.  
  224.     for (i=0; i< (buf->Width*buf->Height); i++ )
  225.     {
  226.  
  227.         r = ((buf->Data[i] >> 10) & 31);
  228.         g = ((buf->Data[i] >> 5) & 31);
  229.         b = (buf->Data[i] & 31);
  230.  
  231.  
  232.  
  233.         max = 0;
  234.         if ( r > max) max = r;
  235.         if ( g > max) max = g;
  236.         if ( b > max) max = b;
  237.  
  238.         if (max > 0) {
  239.             RGBCube[ (r<<10)+(g<<5)+b ]++;
  240.             TotalPixels++;
  241.         }
  242.     }
  243. }
  244.  
  245. void Shrink( int BoxIndex ) {
  246.   int axis, aax1, aax2;
  247.   int ind[3], flag;
  248.  
  249.   for (axis=0; axis<3; axis++ ) {
  250.       switch(axis)    {
  251.           case 0:
  252.               aax1=1; aax2=2; break;
  253.           case 1:
  254.               aax1=0; aax2=2; break;
  255.           case 2:
  256.               aax1=0; aax2=1;
  257.       }
  258.  
  259.       flag=0;
  260.       for (ind[axis]=Boxes[BoxIndex].Lo[axis]; ind[axis]<=Boxes[BoxIndex].Hi[axis]; ind[axis]++ )    {
  261.           for (ind[aax1]=Boxes[BoxIndex].Lo[aax1]; ind[aax1]<=Boxes[BoxIndex].Hi[aax1]; ind[aax1]++ )    {
  262.               for (ind[aax2]=Boxes[BoxIndex].Lo[aax2]; ind[aax2]<=Boxes[BoxIndex].Hi[aax2]; ind[aax2]++ )
  263.                   if (RGBCube[ (ind[0]<<10)+(ind[2]<<5)+ind[1] ] )    {
  264.                       flag = 1;
  265.                       break;
  266.                   }
  267.               if (flag) break;
  268.           }
  269.           if (flag) break;
  270.       }
  271.  
  272.       Boxes[BoxIndex].Lo[axis] = ind[axis];
  273.       flag=0;
  274.       for (ind[axis]=Boxes[BoxIndex].Hi[axis]; ind[axis]+1>=Boxes[BoxIndex].Lo[axis]+1; ind[axis]-- )    {
  275.           for (ind[aax1]=Boxes[BoxIndex].Hi[aax1]; ind[aax1]+1>=Boxes[BoxIndex].Lo[aax1]+1; ind[aax1]-- )    {
  276.               for (ind[aax2]=Boxes[BoxIndex].Hi[aax2]; ind[aax2]+1>=Boxes[BoxIndex].Lo[aax2]+1; ind[aax2]-- )
  277.                   if (RGBCube[ (ind[0]<<10)+(ind[2]<<5)+ind[1] ] )    {
  278.                       flag = 1;
  279.                       break;
  280.                   }
  281.               if (flag) break;
  282.           }
  283.           if (flag) break;
  284.       }
  285.       Boxes[BoxIndex].Hi[axis] = ind[axis];
  286.   }
  287. }
  288.  
  289.  
  290. int GetGrey( RGB * reg )
  291. {
  292.     BYTE r, b, g;
  293.  
  294.     r = reg->Red/2;
  295.     g = reg->Green/2;
  296.     b = reg->Blue/2;
  297.     return (r+g+b)/3;
  298.  
  299. }
  300.  
  301. void SortPalette()
  302. {
  303.     BYTE t;
  304.     int i, j, incr, grey1, grey2, t1;
  305.  
  306.     incr = AllowedColors / 2;
  307.     while( incr > 0 )
  308.     {
  309.         for (i=incr; i<AllowedColors; i++ )
  310.         {
  311.             j = i - incr;
  312.             while (j>=0 )
  313.             {
  314.                 grey1 = GetGrey( &(ColRegs[j]) );
  315.                 grey2 = GetGrey( &(ColRegs[j+incr]) );
  316.  
  317.                 if (grey1 > grey2 ) {
  318.                     t = ColRegs[j+incr].Red;
  319.                     ColRegs[j+incr].Red=ColRegs[j].Red;
  320.                     ColRegs[j].Red=t;
  321.                     t = ColRegs[j+incr].Green;
  322.                     ColRegs[j+incr].Green=ColRegs[j].Green;
  323.                     ColRegs[j].Green=t;
  324.                     t = ColRegs[j+incr].Blue;
  325.                     ColRegs[j+incr].Blue=ColRegs[j].Blue;
  326.                     ColRegs[j].Blue=t;
  327.                     t1 = Usage[j+incr];
  328.                     Usage[j+incr]=Usage[j];
  329.                     Usage[j]=t1;
  330.                     j -= incr;
  331.                 }
  332.                 else
  333.                     break;
  334.             }
  335.         }
  336.         incr = incr / 2;
  337.     }
  338.  
  339.     t = ColRegs[254].Red;
  340.     ColRegs[254].Red=ColRegs[7].Red;
  341.     ColRegs[7].Red=t;
  342.     t = ColRegs[254].Green;
  343.     ColRegs[254].Green=ColRegs[7].Green;
  344.     ColRegs[7].Green=t;
  345.     t = ColRegs[254].Blue;
  346.     ColRegs[254].Blue=ColRegs[7].Blue;
  347.     ColRegs[7].Blue=t;
  348.     t1 = Usage[254];
  349.     Usage[254]=Usage[7];
  350.     Usage[7]=t1;
  351. }
  352.  
  353.  
  354. void CombinePalettes() {
  355.   int SelectedBox, c, ind[3], Max, axis, TargetBox, k, aax1, aax2;
  356.   int LongMax, PlaneSum, ElementSum;
  357.   int Index,r,b,g;
  358.   int rsum,bsum,gsum,tmp, i;
  359.  
  360.   printf( "Creating a master palette...\n"  );
  361.  
  362.   Boxes[0].Lo[0] = 0;
  363.   Boxes[0].Hi[0] = 31;
  364.   Boxes[0].Lo[1] = 0;
  365.   Boxes[0].Hi[1] = 31;
  366.   Boxes[0].Lo[2] = 0;
  367.   Boxes[0].Hi[2] = 31;
  368.  
  369.   Boxes[0].NumElements = TotalPixels;
  370.   NumBoxes = 1;
  371.   Shrink(0);
  372.  
  373.   while(NumBoxes < AllowedColors )    {
  374.       LongMax = 0;
  375.       SelectedBox = 1000;
  376.       for (c=0; c<NumBoxes; c++ )    {
  377.           if ((Boxes[c].NumElements > LongMax) && ((Boxes[c].Lo[0] != Boxes[c].Hi[0]) || (Boxes[c].Lo[1] != Boxes[c].Hi[1]) || (Boxes[c].Lo[2] != Boxes[c].Hi[2])) )    {
  378.               LongMax = Boxes[c].NumElements;
  379.               SelectedBox = c;
  380.           }
  381.       }
  382.       if (SelectedBox == 1000) break;
  383.       axis = 0;
  384.       Max = Boxes[SelectedBox].Hi[axis] - Boxes[SelectedBox].Lo[axis];
  385.       for (k=1; k<3; k++ )    {
  386.           if (Max<(c=(Boxes[SelectedBox].Hi[k]-Boxes[SelectedBox].Lo[k])))    {
  387.               Max = c;
  388.               axis = k;
  389.           }
  390.       }
  391.  
  392.       TargetBox = NumBoxes;
  393.       for (c=0; c<NumBoxes; c++ )    {
  394.           if (Boxes[c].NumElements == 0 )    {
  395.               TargetBox = c;
  396.               break;
  397.           }
  398.       }
  399.  
  400.       switch(axis)    {
  401.           case 0:
  402.               aax1=1; aax2=2; break;
  403.           case 1:
  404.               aax1=0; aax2=2; break;
  405.           case 2:
  406.               aax1=0; aax2=1;
  407.       }
  408.  
  409.       if (Boxes[SelectedBox].Hi[axis] != Boxes[SelectedBox].Lo[axis])    {
  410.           ElementSum = 0;
  411.           for (ind[axis]=Boxes[SelectedBox].Lo[axis]; ind[axis]<=Boxes[SelectedBox].Hi[axis]; ind[axis]++ )    {
  412.               PlaneSum = 0;
  413.               for (ind[aax1]=Boxes[SelectedBox].Lo[aax1]; ind[aax1]<=Boxes[SelectedBox].Hi[aax1]; ind[aax1]++ )
  414.                   for (ind[aax2]=Boxes[SelectedBox].Lo[aax2]; ind[aax2]<=Boxes[SelectedBox].Hi[aax2]; ind[aax2]++ )
  415.                       PlaneSum += RGBCube[ (ind[0]<<10)+(ind[2]<<5)+ ind[1] ];
  416.               ElementSum += PlaneSum;
  417.               if (ElementSum > Boxes[SelectedBox].NumElements/2)
  418.                   break;
  419.           }
  420.           if (ind[axis] == Boxes[SelectedBox].Hi[axis])    {
  421.               ind[axis]--;
  422.               ElementSum -= PlaneSum;
  423.           }
  424.  
  425.           for (c=0; c< 3; c++ )    {
  426.               Boxes[TargetBox].Lo[c] = Boxes[SelectedBox].Lo[c];
  427.               Boxes[TargetBox].Hi[c] = Boxes[SelectedBox].Hi[c];
  428.           }
  429.           Boxes[TargetBox].Lo[axis] = ind[axis]+1;
  430.           Boxes[TargetBox].NumElements = Boxes[SelectedBox].NumElements - ElementSum;
  431.  
  432.           Boxes[SelectedBox].Hi[axis] = ind[axis];
  433.           Boxes[SelectedBox].NumElements = ElementSum;
  434.           Shrink(SelectedBox);
  435.           Shrink(TargetBox);
  436.  
  437.           if (TargetBox == NumBoxes )   {
  438.             NumBoxes++;
  439.           }
  440.       }
  441.   }
  442.  
  443.   AllowedColors = NumBoxes;
  444.  
  445.   for (Index=0; Index < AllowedColors; Index++ )    {
  446.       rsum = bsum = gsum = 0;
  447.       for (r=Boxes[Index].Lo[0]; r<=Boxes[Index].Hi[0]; r++ )
  448.           for (b=Boxes[Index].Lo[1]; b<=Boxes[Index].Hi[1]; b++ )
  449.               for (g=Boxes[Index].Lo[2]; g<=Boxes[Index].Hi[2]; g++ )    {
  450.                   tmp = RGBCube[ (r<<10)+(g<<5)+b ];
  451.                   rsum += r*tmp;
  452.                   bsum += b*tmp;
  453.                   gsum += g*tmp;
  454.               }
  455.               ColRegs[Index+16].Red   = (BYTE)((rsum*2) / Boxes[Index].NumElements);
  456.               ColRegs[Index+16].Blue  = (BYTE)((bsum*2) / Boxes[Index].NumElements);
  457.               ColRegs[Index+16].Green = (BYTE)((gsum*2) / Boxes[Index].NumElements);
  458.   }
  459.  
  460.   AllowedColors += 16;
  461.  
  462.   ColRegs[0].Red =  0; ColRegs[0].Green = 0; ColRegs[0].Blue = 0;
  463.   ColRegs[1].Red =  0; ColRegs[1].Green = 0; ColRegs[1].Blue =42;
  464.   ColRegs[2].Red =  0; ColRegs[2].Green =42; ColRegs[2].Blue = 0;
  465.   ColRegs[3].Red =  0; ColRegs[3].Green =42; ColRegs[3].Blue =42;
  466.   ColRegs[4].Red = 42; ColRegs[4].Green = 0; ColRegs[4].Blue = 0;
  467.   ColRegs[5].Red = 42; ColRegs[5].Green = 0; ColRegs[5].Blue =42;
  468.   ColRegs[6].Red = 42; ColRegs[6].Green =21; ColRegs[6].Blue = 0;
  469.   ColRegs[7].Red = 42; ColRegs[7].Green =42; ColRegs[7].Blue =42;
  470.   ColRegs[8].Red = 21; ColRegs[8].Green =21; ColRegs[8].Blue =21;
  471.   ColRegs[9].Red = 21; ColRegs[9].Green =21; ColRegs[9].Blue =63;
  472.   ColRegs[10].Red = 21; ColRegs[10].Green =63; ColRegs[10].Blue =21;
  473.   ColRegs[11].Red = 21; ColRegs[11].Green =63; ColRegs[11].Blue =63;
  474.   ColRegs[12].Red = 63; ColRegs[12].Green =21; ColRegs[12].Blue =21;
  475.   ColRegs[13].Red = 63; ColRegs[13].Green =21; ColRegs[13].Blue =63;
  476.   ColRegs[14].Red = 63; ColRegs[14].Green =63; ColRegs[14].Blue =21;
  477.   ColRegs[15].Red = 63; ColRegs[15].Green =63; ColRegs[15].Blue =63;
  478.  
  479. }
  480.  
  481.  
  482. void GammaCorrect()
  483. {
  484.     int i;
  485.     for (i=0; i<AllowedColors; i++ )
  486.     {
  487.         ColRegs[i].Red = Gamma32[ColRegs[i].Red];
  488.         ColRegs[i].Green = Gamma32[ColRegs[i].Green];
  489.         ColRegs[i].Blue = Gamma32[ColRegs[i].Blue];
  490.     }
  491. }
  492.  
  493. void SortPalette1()
  494. {
  495.     BYTE t;
  496.     int i, j, k;
  497.  
  498.     printf( "Sorting palette by usage...\n" );
  499.  
  500.     for (i=1; i<AllowedColors; i++) {
  501.         j=i;
  502.         while (j && (Usage[j] < Usage[j-1])) {
  503.             t = ColRegs[j-1].Red;
  504.             ColRegs[j-1].Red=ColRegs[j].Red;
  505.             ColRegs[j].Red=t;
  506.             t = ColRegs[j-1].Green;
  507.             ColRegs[j-1].Green=ColRegs[j].Green;
  508.             ColRegs[j].Green=t;
  509.             t = ColRegs[j-1].Blue;
  510.             ColRegs[j-1].Blue=ColRegs[j].Blue;
  511.             ColRegs[j].Blue=t;
  512.             k = Usage[j-1];
  513.             Usage[j-1] = Usage[j];
  514.             Usage[j] = k;
  515.             j--;
  516.         }
  517.     }
  518. }
  519.  
  520. BYTE FindColor( int r, int g, int b )
  521. {
  522.     int i, minerr, e;
  523.     BYTE best;
  524.  
  525.     //index = (r<<12)+(g<<6)+b;
  526.     //if (Lookup[index] != -1)
  527.     //    return Lookup[index];
  528.  
  529.     minerr = 64*64*64*64;
  530.     best = 0;
  531.  
  532.     for (i=0; i<AllowedColors; i++ )
  533.     {
  534.  
  535.         e =  SQUARE(ColRegs[i].Red - r);
  536.         e += SQUARE(ColRegs[i].Green - g);
  537.         e += SQUARE(ColRegs[i].Blue - b);
  538.  
  539.         if ( e < minerr  )   {
  540.             minerr = e;
  541.             best = (BYTE)i;
  542.             if (minerr == 0) break;
  543.         }
  544.     }
  545.  
  546.     return best;
  547. }
  548.  
  549. BITMAP8 * ReduceTo8bpp( BITMAP15 * in, char * filename )
  550. {
  551.     char new[20];
  552.     char * p;
  553.     int i, j, size, r, g, b;
  554.     BITMAP8 * out;
  555.  
  556.     char * tmp;
  557.  
  558.     strcpy(new, filename );
  559.     p = strstr( new, "." );
  560.     if (p!=NULL )
  561.     {
  562.         p[1] = 'B';
  563.         p[2] = 'M';
  564.         p[3] = '1';
  565.         p[4] = 0;
  566.         printf( "Writing %s...\n", new );
  567.         WriteFile( new, in, in->Width*in->Height*2+sizeof(BITMAP15)  );
  568.  
  569.         p[3] = '2';
  570.         printf( "Writing %s...\n", new );
  571.         tmp = malloc( in->Width*in->Height*4 );
  572.         if (tmp==NULL) exit(1);
  573.  
  574.         for (i=0; i< in->Width*in->Height; i++ )
  575.         {
  576.             tmp[i*4+0] = (in->Data[i]>>10) & 31;
  577.             tmp[i*4+1] = (in->Data[i]>>5) & 31;
  578.             tmp[i*4+2] = in->Data[i] & 31;
  579.             tmp[i*4+3] = 0;
  580.         }
  581.  
  582.         WriteFile( new, tmp, in->Width*in->Height*4  );
  583.         free(tmp);
  584.     }
  585.  
  586.  
  587.     printf( "Reducing colors in %s...\n", filename );
  588.  
  589.  
  590.     size = in->Height * in->Width;
  591.  
  592.     out = (BITMAP8 *)in;
  593.  
  594.     out->Rowsize = out->Width;
  595.     out->Type = BM_LINEAR;
  596.     out->DataPtr = 0;
  597.  
  598.     for (i=0; i< size; i++ )
  599.     {
  600.         if (in->Data[i]==0)
  601.             out->Data[i] = 255;
  602.         else    {
  603.             out->Data[i] = LookupTable[ in->Data[i] ];
  604.             Usage[ out->Data[i] ]++;
  605.         }
  606.     }
  607.  
  608.     return out;
  609. }
  610.  
  611. void WritePalette()
  612. {
  613.     printf( "Writing palette...\n" );
  614.  
  615.     WriteFile( "PALETTE.TBL", ColRegs, 256*3 );
  616.  
  617. }
  618.  
  619. BITMAP15 * ReadImage( char * filename )
  620. {
  621.     printf( "Reading in %s...\n", filename );
  622.     return IFF_To_15BPP( filename );
  623.  
  624. }
  625.  
  626.  
  627. void PrintUsage()
  628. {
  629.     printf( "Usage:  TESTP [-c#] files...\n" );
  630. }
  631.  
  632. void DisplayPalette()
  633. {
  634.     int i, j, k;
  635.     gr_set_current_canvas(NULL);
  636.     for (i=0; i<AllowedColors; i++ )
  637.     {
  638.         for (j=0; j<16; j++ )
  639.         {
  640.             gr_setcolor( ColorTable[j][i] );
  641.             for (k=0; k<10; k++ )
  642.                 gr_pixel( i, (j*10)+k );
  643.         }
  644.     }
  645. }
  646.  
  647.  
  648. void DisplayImage( BITMAP8 * Image )
  649. {
  650.     int x,y,i,j, l, lt;
  651.  
  652.     lt = MessageBox( 320, 240, 4, "Animation?", "Add Red", "Add Green", "Add Blue", "Fade out" );
  653.  
  654.     gr_set_current_canvas(NULL);
  655.  
  656.     if (lt==4)
  657.     {
  658.         for (j=15; j>=0; j-- )
  659.         {
  660.             i=0;
  661.             for (y=0; y< Image->Height; y++ )
  662.             {
  663.                 for (x=0; x< Image->Width; x++ )
  664.                 {
  665.                     gr_setcolor( ColorTable[j][Image->Data[i++]] );
  666.                     gr_rect( x*3, y*3, x*3+3, y*3+3 );
  667.                     //gr_pixel(x,y);
  668.                 }
  669.             }
  670.             key_getch();
  671.         }
  672.     }
  673.     else
  674.     {
  675.         for (j=15; j>=0; j-- )
  676.         {
  677.             if (lt==1)
  678.                 l = LookupTable[((15-j)*2)<<10] << 8;
  679.             if (lt==2)
  680.                 l = LookupTable[((15-j)*2)<<5] << 8;
  681.             if (lt==3)
  682.                 l = LookupTable[((15-j)*2)] << 8;
  683.  
  684.             i=0;
  685.             for (y=0; y< Image->Height; y++ )
  686.             {
  687.                 for (x=0; x< Image->Width; x++ )
  688.                 {
  689.                     gr_setcolor( AverageTable[l+Image->Data[i++]] );
  690.                     gr_rect( x*3, y*3, x*3+3, y*3+3 );
  691.                     //gr_pixel(x,y);
  692.                 }
  693.             }
  694.             key_getch();
  695.         }
  696.     }
  697.  
  698. }
  699.  
  700.  
  701. void FactorInShades()
  702. {
  703.     int j, i, r, g, b;
  704.  
  705.     printf( "Factoring in shades...\n" );
  706.  
  707.     for (j=1; j<=16; j++ )
  708.     {
  709.         for (i=0; i < AllowedColors; i++ )
  710.         {
  711.                 r = (j*ColRegs[i].Red)/(16*2);
  712.                 g = (j*ColRegs[i].Green)/(16*2);
  713.                 b = (j*ColRegs[i].Blue)/(16*2);
  714.  
  715.                 if ((r+g+b)>0)  {
  716.                     RGBCube[ (r<<10)+(g<<5)+b ] += (Boxes[i].NumElements*2)/j;
  717.                     TotalPixels+=(Boxes[i].NumElements*2)/j;
  718.                 }
  719.         }
  720.     }
  721. }
  722.  
  723. void FactorInAlternateLights()
  724. {
  725.     int j, i, r, g, b;
  726.  
  727.     printf( "Factoring in alternate lighting...\n" );
  728.  
  729.     for (j=1; j<=16; j++ )
  730.     {
  731.         for (i=0; i < AllowedColors; i++ )
  732.         {
  733.                 r = (j*ColRegs[i].Red)/(16*2);
  734.                 g = (j*ColRegs[i].Green)/(16*2);
  735.                 b = (j*ColRegs[i].Blue)/(16*2);
  736.  
  737.                 r += j;
  738.                 if (r>31) r=31;
  739.  
  740.                 if ((r+g+b)>0)  {
  741.                     RGBCube[ (r<<10)+(g<<5)+b ] += (Boxes[i].NumElements*2)/j;
  742.                     TotalPixels+=(Boxes[i].NumElements*2)/j;
  743.                 }
  744.         }
  745.     }
  746.     for (j=1; j<=16; j++ )
  747.     {
  748.         for (i=0; i < AllowedColors; i++ )
  749.         {
  750.                 r = (j*ColRegs[i].Red)/(16*2);
  751.                 g = (j*ColRegs[i].Green)/(16*2);
  752.                 b = (j*ColRegs[i].Blue)/(16*2);
  753.  
  754.                 g += j;
  755.                 if (g>31) g=31;
  756.  
  757.                 if ((r+g+b)>0)  {
  758.                     RGBCube[ (r<<10)+(g<<5)+b ] += (Boxes[i].NumElements*2)/j;
  759.                     TotalPixels+=(Boxes[i].NumElements*2)/j;
  760.                 }
  761.         }
  762.     }
  763.     for (j=1; j<=16; j++ )
  764.     {
  765.         for (i=0; i < AllowedColors; i++ )
  766.         {
  767.                 r = (j*ColRegs[i].Red)/(16*2);
  768.                 g = (j*ColRegs[i].Green)/(16*2);
  769.                 b = (j*ColRegs[i].Blue)/(16*2);
  770.  
  771.                 b += j;
  772.                 if (b>31) b=31;
  773.  
  774.                 if ((r+g+b)>0)  {
  775.                     RGBCube[ (r<<10)+(g<<5)+b ] += (Boxes[i].NumElements*2)/j;
  776.                     TotalPixels+=(Boxes[i].NumElements*2)/j;
  777.                 }
  778.         }
  779.     }
  780.  
  781. }
  782.  
  783.  
  784. void CalculateLookupTable()
  785. {
  786.     int r, g, b, i;
  787.  
  788.     printf( "Creating inverse lookup table...\n" );
  789.  
  790.     LookupTable= (BYTE *)malloc(32768);
  791.     if (LookupTable==NULL) exit(1);
  792.  
  793.     i = 0;
  794.     for (r=0; r<32; r++ )
  795.         for (g=0; g<32; g++ )
  796.             for (b=0; b<32; b++ )
  797.                 LookupTable[i++] = FindColor( r*2, g*2, b*2 );
  798.  
  799.     WriteFile( "IPAL.TBL", LookupTable, 32768 );
  800.  
  801. }
  802.  
  803. void CalculateShadeTables()
  804. {
  805.     int j, i, r, g, b;
  806.  
  807.     printf( "Creating and writing shade lookup tables...\n" );
  808.  
  809.     for (j=1; j<=16; j++ )
  810.     {
  811.       ColorTable[j-1][255] = 255;
  812.       for (i=0; i < AllowedColors; i++ )
  813.       {
  814.           r = (j*ColRegs[i].Red)/16;
  815.           g = (j*ColRegs[i].Green)/16;
  816.           b = (j*ColRegs[i].Blue)/16;
  817.           if (j<16)
  818.             ColorTable[j-1][i] = FindColor( r, g, b);
  819.           else
  820.             ColorTable[15][i] = i;
  821.  
  822.       }
  823.     }
  824.     WriteFile( "FADE.TBL", ColorTable, 256*16 );
  825. }
  826.  
  827. void CreateBlendTable()
  828. {
  829.     int i,j,r,g,b, c;
  830.  
  831.     printf( "Creating and writing color averaging table...\n" );
  832.  
  833.     AverageTable= (BYTE *)malloc(256*256);
  834.     if (AverageTable==NULL) exit(1);
  835.  
  836.     for (i=0; i<256; i++ )
  837.     {
  838.         for (j=i; j<256; j++ )
  839.         {
  840.             r = (ColRegs[i].Red+ColRegs[j].Red);
  841.             g = (ColRegs[i].Green+ColRegs[j].Green);
  842.             b = (ColRegs[i].Blue+ColRegs[j].Blue);
  843.             if (r>63) r=63;
  844.             if (g>63) g=63;
  845.             if (b>63) b=63;
  846.             c = FindColor( r,g,b );
  847.             AverageTable[(i<<8)+j] = c;
  848.             AverageTable[(j<<8)+i] = c;
  849.         }
  850.     }
  851.     WriteFile( "BLEND.TBL", AverageTable, 256*256 );
  852. }
  853.  
  854. void NormalizePalette()
  855. {
  856.     int i, max;
  857.  
  858.     max = 0;
  859.  
  860.     for (i=0; i<AllowedColors; i++ )
  861.     {
  862.         if (ColRegs[i].Red > max ) max = ColRegs[i].Red;
  863.         if (ColRegs[i].Green > max ) max = ColRegs[i].Green;
  864.         if (ColRegs[i].Blue > max ) max = ColRegs[i].Blue;
  865.     }
  866.  
  867.     //printf( "Max=%d\n", max );
  868.     //getch();
  869.  
  870.     for (i=0; i<AllowedColors; i++ )
  871.     {
  872.         ColRegs[i].Red = ((int)ColRegs[i].Red*63)/max;
  873.         ColRegs[i].Green = ((int)ColRegs[i].Green*63)/max;
  874.         ColRegs[i].Blue = ((int)ColRegs[i].Blue*63)/max;
  875.     }
  876.  
  877. }
  878.  
  879. void DisplayIPAL()
  880. {
  881.     int i,x,y;
  882.  
  883.     x=y=0;
  884.  
  885.     gr_set_current_canvas(NULL);
  886.  
  887.     for (i=0; i<32768; i++ )
  888.     {
  889.         x++;
  890.         if (x > 320) {
  891.             x = 0; y++;
  892.         }
  893.         gr_setcolor( LookupTable[i] );
  894.         gr_upixel( x, y );
  895.     }
  896. }
  897.  
  898.  
  899. void DoInterface()
  900. {
  901.     int i;
  902.     int menu1, NumItems1;
  903.     char * MenuItems[256];
  904.  
  905.     gr_init( SM_640x480V );
  906.     gr_init_font( "/miner/fonts/pc8x16.fnt" );
  907.  
  908.     ColRegs[255].Red   = 0;
  909.     ColRegs[255].Blue  = 30;
  910.     ColRegs[255].Green = 0;
  911.  
  912.     gr_set_palette(0, 256, (BYTE *)ColRegs );
  913.  
  914.  
  915.     gr_setcolor(255);
  916.     gr_rect(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
  917.  
  918.     ui_init();
  919.  
  920.     for (NumItems1=0; NumItems1<NumImages; NumItems1++ )
  921.     {
  922.         sprintf(temp,"Fade %s", Filename[NumItems1]);
  923.         MenuItems[NumItems1] = strdup( temp );
  924.     }
  925.     MenuItems[NumItems1++] = strdup( "Show IPAL" );
  926.     MenuItems[NumItems1++] = strdup( "Show palette" );
  927.     MenuItems[NumItems1++] = strdup( "Quit program" );
  928.  
  929.     gr_pal_fade_in( grd_curscreen->pal );
  930.  
  931.     menu1 = 2;
  932.  
  933.     while( menu1 != 1 )
  934.     {
  935.         while ( menu1 != NumItems1 )
  936.         {
  937.             ui_mouse_process();
  938.  
  939.             menu1 = PopupMenu( NumItems1, MenuItems );
  940.  
  941.             if (menu1<(NumItems1-2) && (menu1>0) )
  942.             {
  943.                 DisplayImage( Image8[menu1-1] );
  944.             }
  945.  
  946.             if (menu1==(NumItems1-2))
  947.             {
  948.                 DisplayIPAL();
  949.             }
  950.  
  951.             if (menu1==(NumItems1-1))
  952.             {
  953.                 DisplayPalette();
  954.             }
  955.         }
  956.         menu1 = MessageBox( -1, -1, 2, "Exit to DOS?", "Yes", "No" );
  957.     }
  958.  
  959.     ui_close();
  960.  
  961.     gr_close();
  962.  
  963.  
  964.  
  965.     for (i=0; i< AllowedColors; i++ )
  966.     {
  967.         if ((i%20)==0) getch();
  968.         printf( "%d  %d,%d,%d   %d\n", i, ColRegs[i].Red,ColRegs[i].Green,ColRegs[i].Blue, Usage[i] );
  969.     }
  970.  
  971.  
  972. }
  973.  
  974. void ParseCommandLine( int argc, char * argv[] )
  975. {
  976.     struct find_t find;
  977.     char * cp;
  978.     char * cp1;
  979.  
  980.     if (argc < 2 )  {
  981.         PrintUsage();
  982.         exit(1);
  983.     }
  984.  
  985.     RequestedColors = 256;
  986.  
  987.     argv++; argc--;
  988.     for (;argc--;argv++)
  989.     {
  990.         if ((**argv=='-') || (**argv=='/'))
  991.         {
  992.             cp=(*argv)+1;
  993.             cp1 = cp;
  994.             switch (*cp++)
  995.             {
  996.                 case 'c':
  997.                     RequestedColors = atoi( cp );
  998.                     break;
  999.                 case '?':
  1000.                 case 'h':
  1001.                     PrintUsage();
  1002.                     exit(1);
  1003.                 default:
  1004.                     printf( "Unrecognized switch '%s'\n", cp1 );
  1005.                     break;
  1006.             }
  1007.         }
  1008.         else
  1009.         {
  1010.             if( !_dos_findfirst( *argv, 0xffff, &find ) )
  1011.             {
  1012.                 Filename[NumImages++] = strdup( find.name );
  1013.                 while( !_dos_findnext( &find ) )
  1014.                 {
  1015.                     Filename[NumImages++] = strdup( find.name );
  1016.                 }
  1017.             }
  1018.             else
  1019.             {
  1020.                 printf( "No files matching '%s' were found.\n", *argv );
  1021.                 exit(1);
  1022.             }
  1023.         }
  1024.     }
  1025.  
  1026.     if ( NumImages == 0 )   {
  1027.         printf( "Error: Input files must be specified.\n\n" );
  1028.         PrintUsage();
  1029.         exit(1);
  1030.     }
  1031.  
  1032.     if (RequestedColors < 16) RequestedColors = 16;
  1033.     if (RequestedColors > 256) RequestedColors = 256;
  1034.     RequestedColors--;
  1035.  
  1036. }
  1037.  
  1038.  
  1039. void WriteBitmaps()
  1040. {
  1041.     char new[20];
  1042.     char * p;
  1043.     int i, j;
  1044.  
  1045.     for (j=0; j<NumImages; j++ )
  1046.     {
  1047.         strcpy(new, Filename[j] );
  1048.         p = strstr( new, "." );
  1049.         if (p!=NULL )
  1050.         {
  1051.             p[1] = 'B';
  1052.             p[2] = 'M';
  1053.             p[3] = 'S';
  1054.             p[4] = 0;
  1055.             printf( "Writing %s...\n", new );
  1056.             WriteFile( new, Image8[j], Image8[j]->Width*Image8[j]->Height+sizeof(BITMAP8)  );
  1057.         }
  1058.     }
  1059. }
  1060.  
  1061. void ReduceImages()
  1062. {
  1063.     int i;
  1064.  
  1065.     for (i=0; i<NumImages; i++ )
  1066.     {
  1067.         Image8[i] = ReduceTo8bpp( Image15[i], Filename[i] );
  1068.     }
  1069. }
  1070.  
  1071. void AnalyzeImages()
  1072. {
  1073.     int i;
  1074.  
  1075.     for (i=0; i<NumImages; i++ )
  1076.     {
  1077.         printf( "Reading in %s\n", Filename[i] );
  1078.         Image15[i] = IFF_To_15BPP( Filename[i] );
  1079.         ScanColorFrequencies( Image15[i], Filename[i] );
  1080.     }
  1081. }
  1082.  
  1083. int main(int argc, char * argv[] )
  1084. {
  1085.  
  1086.     ParseCommandLine( argc, argv );
  1087.  
  1088.     FillGamma();
  1089.  
  1090.     AllowedColors = 239;
  1091.  
  1092.     InitializeMixer();
  1093.  
  1094.     AnalyzeImages();
  1095.  
  1096.     CombinePalettes();
  1097.  
  1098.     //AllowedColors = 255;
  1099.  
  1100.     //InitializeMixer();
  1101.  
  1102.     //FactorInShades();
  1103.  
  1104.     //FactorInAlternateLights();
  1105.  
  1106.     //CombinePalettes();
  1107.  
  1108.     //SortPalette();
  1109.  
  1110.     CalculateLookupTable();
  1111.  
  1112.     ReduceImages();
  1113.  
  1114.     CalculateShadeTables();
  1115.  
  1116.     CreateBlendTable();
  1117.  
  1118.     NormalizePalette();
  1119.  
  1120.     WritePalette();
  1121.  
  1122.     WriteBitmaps();
  1123.  
  1124.     DoInterface();
  1125.  
  1126.     exit(1);
  1127. }
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.