home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / grphutil / dgif.arj / DITHER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  11.0 KB  |  474 lines

  1. /*********************************** dither.c ********************************/
  2. /* error dispersion code from DGIF v2.0 */
  3. /* compiled using BC++ (sans++) */
  4. /* last change 4/08/91 */
  5.  
  6. #pragma inline
  7.  
  8. #include <stdio.h>
  9. #include <dir.h>
  10. #include <dos.h>
  11. #include <alloc.h>
  12. #include <string.h>
  13. #include <math.h>
  14. #include "dither.h"
  15.  
  16. #define   TMEMSIZE (0x00010010L) /* 64k + 16 */
  17.  
  18. static int RGBTableSeg; /* offset 0 */
  19.  
  20.  
  21. static unsigned char far *RGBTable; 
  22.  
  23. /* decompress stuff */
  24. static int NumValues;
  25. static unsigned char Value;
  26. static unsigned char far *pTable;
  27. static unsigned char LastLine[32];
  28. static FILE *ptetra;
  29.  
  30.  
  31. int NumDColors;  /* Number of dither colors */
  32.  
  33. int DitherColorTable[3*16] = { 
  34. /* index      rgb color    
  35.   /* 0 */     0,   0,    0,
  36.   /* 1 */     0,   0,  255,
  37.   /* 2 */     0, 255,    0,
  38.   /* 3 */     0, 255,  255,
  39.   /* 4 */   255,   0,    0,
  40.   /* 5 */   255,   0,  255,
  41.   /* 6 */   255, 255,    0,
  42.   /* 7 */   255, 255,  255,
  43.   /* 8 */    0,  128,  128,
  44.   /* 9 */    255, 128,  128,
  45.   /* 10 */   128, 0,   128,
  46.   /* 11 */   128, 255, 128,
  47.   /* 12 */  128, 128,   0,
  48.   /* 13 */  128, 128,  255,
  49.   /* 14 */  128, 128,  128,
  50.   /* 15 */   39,  39,   39};
  51.  
  52.  
  53. unsigned char EGAColorPalette[17] = 
  54.  {0,9,18,27,36,45,54,63,3,39,5,23,6,15,7,56,0};
  55.  
  56.  
  57. int Dtype;              /* error dispersion = 0, uniform ordered  = 1 */
  58. unsigned int NTetra;    /* if Dtype = 1, number of tetrahedrons */
  59. ITETRA  *TetraList;  /* if Dtype = 1, pointer to tetrahedron array */
  60.  
  61. static int getLine(void)
  62. {  /* read and decompress one row (32 bytes) of RGB table data */
  63.     unsigned char Cur,temp[2]; 
  64.     int k;
  65.     for(k = 0; k < 32; k++)
  66.     {
  67.        if( NumValues-- <= 0)
  68.        {
  69.           if( fread(temp,1,2,ptetra) != 2) return(-1);
  70.           NumValues = temp[0] -1;
  71.           Value = temp[1];
  72.        }
  73.        Cur = LastLine[k] + Value;
  74.        *(pTable++) = Cur;
  75.        LastLine[k] = Cur;
  76.     }
  77.     return(0);
  78. }
  79.  
  80. unsigned char  gamma(float value, int intensity)
  81. {
  82.     float I,V,invgamma;
  83.     
  84.     /*  (I/255) = (V/63) ** gamma  */
  85.     /*    (V/63)  = (I/255) ** (1/gamma) */
  86.     /*    V = 63* (I/255) ** ( 1/gamma); */
  87.     invgamma = 1.0/value;
  88.     I = intensity/255.0;
  89.     V = 63.0*pow(I,invgamma);
  90.     return(V + 0.5);
  91. }
  92.  
  93. /* VGA DAC rgb value in, returns EGA color */
  94. static unsigned char ega_color(unsigned char *rgb)
  95. {
  96.    int temp,C,c,k;
  97.    unsigned char index;
  98.    index = 0;
  99.    for( k = 0,C = 4, c = 32; k < 3; k++, C >>= 1, c >>= 1)
  100.    {
  101.       temp = ((int) rgb[k] + 10)/21;
  102.       switch(temp)
  103.       {
  104.          case 1:
  105.                  index += c;
  106.                  break;
  107.          case 2:
  108.                  index += C;
  109.  
  110.                  break;
  111.          case 3:
  112.                  index += c + C;
  113.                  break;
  114.       }
  115.    }
  116.    return(index);
  117. }
  118.  
  119.  
  120. void FreeLookUp(void)
  121. {
  122.    farfree(RGBTable); 
  123. }
  124.  
  125.  
  126. int LoadTetraFile(char *argv0,char *fname)
  127. {
  128.  
  129.    char drive[MAXDRIVE];
  130.    char dir[MAXDIR];
  131.    char file[MAXFILE];
  132.    char ext[MAXEXT];
  133.    char tempfile[MAXFILE];
  134.    char tempext[MAXEXT];
  135.    char s[MAXPATH];
  136.    unsigned char temp,rgb[3],type,comp;
  137.    int k,j;
  138.  
  139.    ptetra = fopen(fname,"rb");
  140.  
  141.    if (ptetra == NULL)
  142.    { /* not in current directory */
  143.       fnsplit(fname,drive,dir,file,ext);    
  144.       fnsplit(argv0,drive,dir,tempfile,tempext);
  145.       fnmerge(s,drive,dir,file,ext);
  146.       ptetra = fopen(s,"rb");
  147.    }
  148.  
  149.    if (ptetra == NULL)
  150.    {
  151.  
  152.        printf("\n Tetra File %s not found",fname);
  153.        return(NOFOUND);
  154.    }
  155.  
  156.    /* check if Tetra file */
  157.  
  158.    fread(s,1,5,ptetra);
  159.    s[5] = 0;
  160.    if( strcmp(s,"TETRA") != 0)
  161.    { /* not a tetra file */
  162.        printf("\n %s Not a Tetra File",fname);
  163.        fclose(ptetra);
  164.        return(SYNERR);
  165.    }
  166.  
  167.    fread(s,1,2,ptetra); /* skip version number */
  168.  
  169.    fread(&temp,1,1,ptetra);
  170.    NumDColors = temp +1;
  171.    if( NumDColors > 16)
  172.    { /* max 16 colors */
  173.        printf("\n 16 Colors max, found %d",NumDColors);
  174.        fclose(ptetra);
  175.        return(SYNERR);
  176.    }
  177.  
  178.    fread(&comp,1,1,ptetra);
  179.    fread(&type,1,1,ptetra);
  180.    Dtype = type;
  181.    fread(&NTetra,2,1,ptetra);
  182.    fread(s,1,4,ptetra); /* skip reserved */
  183.  
  184.    if( (type == 0) && (comp != 1) )
  185.    { /* only compressed error dispersion supported */
  186.        printf("\n Only Compressed Tetra files supported");
  187.        fclose(ptetra);
  188.        return(SYNERR);
  189.    }
  190.  
  191.    /* read color table */
  192.    for( k = 0 ; k < NumDColors; k++)
  193.    {
  194.        fread(rgb,1,3,ptetra); /* read rgb */
  195.        for( j = 0; j < 3 ; j++)
  196.        {
  197.           DitherColorTable[3*k +j] = rgb[j];
  198.           rgb[j] = gamma(1.7,rgb[j]); /* gamma for ega */
  199.        }
  200.        /*  EGA Color Palette with fixed 1.7 gamma */
  201.        EGAColorPalette[k] = ega_color(rgb);
  202.    }
  203.  
  204.    if(Dtype == 0)
  205.    {  /* error dispersion */
  206.        RGBTable = (unsigned char far *) farmalloc(TMEMSIZE);
  207.        if(RGBTable == NULL)
  208.        {
  209.            printf("\n Not Enough Memory for Color LookUp Table");
  210.            fclose(ptetra);
  211.            return(NOMEMORY);
  212.        }
  213.  
  214.        /* set segment */
  215.  
  216.        RGBTableSeg = FP_SEG(RGBTable);
  217.        RGBTableSeg++; /* table required zero offset */
  218.        pTable = MK_FP(RGBTableSeg,0);
  219.  
  220.        /* init decompression */
  221.  
  222.        NumValues = 0;
  223.        Value = 0;
  224.        for(k = 0; k < 32; k++) LastLine[k] = 0;
  225.  
  226.        /* load table */
  227.  
  228.        for( k = 0; k < 2048; k++)
  229.        {
  230.           if(getLine() < 0)
  231.           {
  232.               printf("\n LookUp Table Load Error");
  233.               fclose(ptetra);
  234.               return(READERR);
  235.           }
  236.        }
  237.        fclose(ptetra);
  238.        return(OK);
  239.    }
  240.  
  241.    /* this stuff is only included so main can list the tetrahedron data */
  242.    /* uniform ordered dither */
  243.    TetraList = (ITETRA *) malloc(NTetra*sizeof(ITETRA));
  244.    if(TetraList == NULL)
  245.    {
  246.        fclose(ptetra);
  247.        return(NOMEMORY);
  248.    }
  249.    for( k = 0; k < NTetra; k++)
  250.    {
  251.       if( fread(&TetraList[k],1,sizeof(ITETRA),ptetra) != sizeof(ITETRA) )
  252.       {
  253.            fclose(ptetra);
  254.            return(READERR);
  255.       }
  256.    }
  257.    return(OK);
  258.  
  259. }
  260.  
  261. /* convert to assemby if you don't have TC or BC  */ 
  262. /* getFastColor converts the rgb color to a 17 bit */
  263. /* index into the lookup table. The look up table */
  264. /* dither color entry is returned */
  265.  
  266. int getFastColor(int near *rgb)
  267. {
  268.  
  269.     asm mov bx, rgb;
  270.  
  271.  
  272.     asm mov dx, [bx +4];
  273.     asm and dl, 0f8h;
  274.     asm xchg dh,dl;
  275.  
  276.     asm mov ax,[bx +2];
  277.     asm and al, 0fch;
  278.     asm mov cl,3;
  279.     asm shl ax,cl;
  280.     asm or dx, ax;
  281.  
  282.  
  283.     asm mov ax,[bx];
  284.     asm mov ch,al;   /* save */
  285.     asm mov cl,3;
  286.     asm shr ax,cl;
  287.     asm or dx,ax;
  288.     asm mov es, RGBTableSeg;
  289.     asm mov bx,dx;
  290.     asm xor ah,ah;
  291.     asm mov al, es:[bx];
  292.  
  293.     asm and ch,04;
  294.     asm jz Even;
  295.     asm mov cl,4;
  296.     asm shr al,cl;
  297. Even:
  298.     asm and al,0fh;
  299. }
  300.  
  301.  
  302. /* used by main to compare color selection */
  303.  
  304. static int ClosestColor(int *rgb)
  305. {
  306.    long min,temp,sum;
  307.    int k,j,kmin;
  308.  
  309.    min = 0x7fffffff;
  310.    kmin = -1;
  311.    for(k = 0; k < NumDColors; k++)
  312.    {
  313.       sum = 0;
  314.       for( j = 0; j < 3; j++)
  315.       {
  316.          temp = DitherColorTable[3*k + j] - rgb[j];
  317.          sum += temp*temp;
  318.       }
  319.       if( sum < min)
  320.       {
  321.          kmin = k;
  322.          min = sum;
  323.       }
  324.    }
  325.    return(kmin);
  326. }
  327.  
  328.  
  329. static void ConvertRGB(float *out, int *in)
  330. {
  331.    int k;
  332.  
  333.    for(k = 0; k < 3; k++)
  334.       out[k] = in[k]/64.0;
  335. }
  336.  
  337. static float ConvertTrig(int value)
  338. {
  339.    return( value/32767.0);
  340. }
  341.  
  342. static float ConvertProb(unsigned int value)
  343. {
  344.    return( value/65535.0);
  345. }
  346.  
  347. /*  example use of error dispersion functions */
  348.  
  349. int cdecl main(int argc, char *argv[])
  350. {
  351.     int error,k,rgb[3],color,j;
  352.     float frgb[3];
  353.     if( argc > 1)
  354.        error = LoadTetraFile(argv[0],argv[1]);   
  355.     else
  356.        error = LoadTetraFile(argv[0],"DGIF.TET");
  357.  
  358.     if( error < 0)
  359.     {
  360.        printf("\n LoadTetraFile Error # %d",error);
  361.        return(0);
  362.     }
  363.  
  364.     if(Dtype == 0)
  365.        printf("\n Tetra Type = Error Dispersion");
  366.     else if(Dtype == 1)
  367.        printf("\n Tetra Type = Uniform Ordered");
  368.     else
  369.     {
  370.        printf("\n Tetra Type Error");
  371.        return(0);
  372.     }
  373.  
  374.  
  375. /* You would normally set up graphics here. */
  376. /* If EGA,load palette registers with the values stored in EGAColorPalette[]*/
  377. /* In EGA mode the display gamma is fixed at 1.7 */ 
  378.  
  379. /* If VGA, gamma correct the dither palette before setting the color DAC. */
  380.  
  381.   /* output dither colors */
  382.   printf("\n Number of Dither Colors = %d\n",NumDColors);
  383.   for(k = 0; k < NumDColors; k++)
  384.      printf("\n  [%2d], (%3d,%3d,%3d)",k,
  385.         DitherColorTable[3*k],
  386.         DitherColorTable[3*k +1],
  387.         DitherColorTable[3*k +2]);
  388.  
  389.   if(Dtype == 0)
  390.   {  /* error dispersion */
  391.       /* use getFastColor function */
  392.  
  393.       rgb[0] = 17;
  394.  
  395.       printf("\n\n getFastColor Test:\n\n");
  396.  
  397.       for( k = 0; k <= 16; k++)
  398.       {
  399.          rgb[1] = (255*k +8)/16;
  400.          rgb[2] = (128*k +8)/16;
  401.          color = getFastColor(rgb);
  402.          printf(" %2d",color);
  403.       }
  404.  
  405.       /* compare with closest color */
  406.  
  407.       printf("\n");
  408.       for( k = 0; k <= 16; k++)
  409.       {
  410.          rgb[1] = (255*k +8)/16;
  411.          rgb[2] = (128*k +8)/16;
  412.          color = ClosestColor(rgb);
  413.          printf(" %2d",color);
  414.       }
  415.       FreeLookUp();
  416.       return(0);
  417.    }
  418.  
  419.    /* Uniform Ordered Dither */
  420.    /* output tetrahedron data */
  421.  
  422.    printf("\n\n NTetra = %u",NTetra);
  423.  
  424.    for(k = 0; k < NTetra; k++)
  425.    {
  426.         printf("\n\n Tetra[%3d]  Num Daughter Tetra = %1u",
  427.                   k+1,TetraList[k].flags);
  428.  
  429.         printf("\n    DIndex[] =  {%3d,%3d,%3d,%3d}",
  430.                   (int) TetraList[k].DIndex[0],
  431.                   (int) TetraList[k].DIndex[1],
  432.                   (int) TetraList[k].DIndex[2],
  433.                   (int) TetraList[k].DIndex[3]);
  434.  
  435.         ConvertRGB(frgb,TetraList[k].V1);
  436.         printf("\n    V1[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
  437.         ConvertRGB(frgb,TetraList[k].V2);
  438.         printf("\n    V2[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
  439.         ConvertRGB(frgb,TetraList[k].V3);
  440.         printf("\n    V3[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
  441.         ConvertRGB(frgb,TetraList[k].V4);
  442.         printf("\n    V4[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
  443.  
  444.         printf("\n    SinA = %8.5f",ConvertTrig(TetraList[k].SinA));
  445.         printf("\n    CosA = %8.5f",ConvertTrig(TetraList[k].CosA));
  446.         printf("\n    SinB = %8.5f",ConvertTrig(TetraList[k].SinB));
  447.         printf("\n    CosB = %8.5f",ConvertTrig(TetraList[k].CosB));
  448.  
  449.         if(TetraList[k].flags > 0)
  450.         { /* print daughter info */
  451.  
  452.              for( j = 0; j < 4; j++)
  453.              {
  454.                 printf("\n    p[%1d] = %8.5f",j,ConvertProb(TetraList[k].p[j]));
  455.              }
  456.  
  457.              for( j = 0; j < 4; j++)
  458.              {
  459.                 printf("\n    next[%1d] = %3u",j,TetraList[k].next[j]);
  460.              }
  461.         }
  462.  
  463.  
  464.  
  465.    }
  466.  
  467.    return(0);
  468. }
  469.  
  470.  
  471.  
  472.  
  473.  
  474.