home *** CD-ROM | disk | FTP | other *** search
- /*********************************** dither.c ********************************/
- /* error dispersion code from DGIF v2.0 */
- /* compiled using BC++ (sans++) */
- /* last change 4/08/91 */
-
- #pragma inline
-
- #include <stdio.h>
- #include <dir.h>
- #include <dos.h>
- #include <alloc.h>
- #include <string.h>
- #include <math.h>
- #include "dither.h"
-
- #define TMEMSIZE (0x00010010L) /* 64k + 16 */
-
- static int RGBTableSeg; /* offset 0 */
-
-
- static unsigned char far *RGBTable;
-
- /* decompress stuff */
- static int NumValues;
- static unsigned char Value;
- static unsigned char far *pTable;
- static unsigned char LastLine[32];
- static FILE *ptetra;
-
-
- int NumDColors; /* Number of dither colors */
-
- int DitherColorTable[3*16] = {
- /* index rgb color
- /* 0 */ 0, 0, 0,
- /* 1 */ 0, 0, 255,
- /* 2 */ 0, 255, 0,
- /* 3 */ 0, 255, 255,
- /* 4 */ 255, 0, 0,
- /* 5 */ 255, 0, 255,
- /* 6 */ 255, 255, 0,
- /* 7 */ 255, 255, 255,
- /* 8 */ 0, 128, 128,
- /* 9 */ 255, 128, 128,
- /* 10 */ 128, 0, 128,
- /* 11 */ 128, 255, 128,
- /* 12 */ 128, 128, 0,
- /* 13 */ 128, 128, 255,
- /* 14 */ 128, 128, 128,
- /* 15 */ 39, 39, 39};
-
-
- unsigned char EGAColorPalette[17] =
- {0,9,18,27,36,45,54,63,3,39,5,23,6,15,7,56,0};
-
-
- int Dtype; /* error dispersion = 0, uniform ordered = 1 */
- unsigned int NTetra; /* if Dtype = 1, number of tetrahedrons */
- ITETRA *TetraList; /* if Dtype = 1, pointer to tetrahedron array */
-
- static int getLine(void)
- { /* read and decompress one row (32 bytes) of RGB table data */
- unsigned char Cur,temp[2];
- int k;
- for(k = 0; k < 32; k++)
- {
- if( NumValues-- <= 0)
- {
- if( fread(temp,1,2,ptetra) != 2) return(-1);
- NumValues = temp[0] -1;
- Value = temp[1];
- }
- Cur = LastLine[k] + Value;
- *(pTable++) = Cur;
- LastLine[k] = Cur;
- }
- return(0);
- }
-
- unsigned char gamma(float value, int intensity)
- {
- float I,V,invgamma;
-
- /* (I/255) = (V/63) ** gamma */
- /* (V/63) = (I/255) ** (1/gamma) */
- /* V = 63* (I/255) ** ( 1/gamma); */
- invgamma = 1.0/value;
- I = intensity/255.0;
- V = 63.0*pow(I,invgamma);
- return(V + 0.5);
- }
-
- /* VGA DAC rgb value in, returns EGA color */
- static unsigned char ega_color(unsigned char *rgb)
- {
- int temp,C,c,k;
- unsigned char index;
- index = 0;
- for( k = 0,C = 4, c = 32; k < 3; k++, C >>= 1, c >>= 1)
- {
- temp = ((int) rgb[k] + 10)/21;
- switch(temp)
- {
- case 1:
- index += c;
- break;
- case 2:
- index += C;
-
- break;
- case 3:
- index += c + C;
- break;
- }
- }
- return(index);
- }
-
-
- void FreeLookUp(void)
- {
- farfree(RGBTable);
- }
-
-
- int LoadTetraFile(char *argv0,char *fname)
- {
-
- char drive[MAXDRIVE];
- char dir[MAXDIR];
- char file[MAXFILE];
- char ext[MAXEXT];
- char tempfile[MAXFILE];
- char tempext[MAXEXT];
- char s[MAXPATH];
- unsigned char temp,rgb[3],type,comp;
- int k,j;
-
- ptetra = fopen(fname,"rb");
-
- if (ptetra == NULL)
- { /* not in current directory */
- fnsplit(fname,drive,dir,file,ext);
- fnsplit(argv0,drive,dir,tempfile,tempext);
- fnmerge(s,drive,dir,file,ext);
- ptetra = fopen(s,"rb");
- }
-
- if (ptetra == NULL)
- {
-
- printf("\n Tetra File %s not found",fname);
- return(NOFOUND);
- }
-
- /* check if Tetra file */
-
- fread(s,1,5,ptetra);
- s[5] = 0;
- if( strcmp(s,"TETRA") != 0)
- { /* not a tetra file */
- printf("\n %s Not a Tetra File",fname);
- fclose(ptetra);
- return(SYNERR);
- }
-
- fread(s,1,2,ptetra); /* skip version number */
-
- fread(&temp,1,1,ptetra);
- NumDColors = temp +1;
- if( NumDColors > 16)
- { /* max 16 colors */
- printf("\n 16 Colors max, found %d",NumDColors);
- fclose(ptetra);
- return(SYNERR);
- }
-
- fread(&comp,1,1,ptetra);
- fread(&type,1,1,ptetra);
- Dtype = type;
- fread(&NTetra,2,1,ptetra);
- fread(s,1,4,ptetra); /* skip reserved */
-
- if( (type == 0) && (comp != 1) )
- { /* only compressed error dispersion supported */
- printf("\n Only Compressed Tetra files supported");
- fclose(ptetra);
- return(SYNERR);
- }
-
- /* read color table */
- for( k = 0 ; k < NumDColors; k++)
- {
- fread(rgb,1,3,ptetra); /* read rgb */
- for( j = 0; j < 3 ; j++)
- {
- DitherColorTable[3*k +j] = rgb[j];
- rgb[j] = gamma(1.7,rgb[j]); /* gamma for ega */
- }
- /* EGA Color Palette with fixed 1.7 gamma */
- EGAColorPalette[k] = ega_color(rgb);
- }
-
- if(Dtype == 0)
- { /* error dispersion */
- RGBTable = (unsigned char far *) farmalloc(TMEMSIZE);
- if(RGBTable == NULL)
- {
- printf("\n Not Enough Memory for Color LookUp Table");
- fclose(ptetra);
- return(NOMEMORY);
- }
-
- /* set segment */
-
- RGBTableSeg = FP_SEG(RGBTable);
- RGBTableSeg++; /* table required zero offset */
- pTable = MK_FP(RGBTableSeg,0);
-
- /* init decompression */
-
- NumValues = 0;
- Value = 0;
- for(k = 0; k < 32; k++) LastLine[k] = 0;
-
- /* load table */
-
- for( k = 0; k < 2048; k++)
- {
- if(getLine() < 0)
- {
- printf("\n LookUp Table Load Error");
- fclose(ptetra);
- return(READERR);
- }
- }
- fclose(ptetra);
- return(OK);
- }
-
- /* this stuff is only included so main can list the tetrahedron data */
- /* uniform ordered dither */
- TetraList = (ITETRA *) malloc(NTetra*sizeof(ITETRA));
- if(TetraList == NULL)
- {
- fclose(ptetra);
- return(NOMEMORY);
- }
- for( k = 0; k < NTetra; k++)
- {
- if( fread(&TetraList[k],1,sizeof(ITETRA),ptetra) != sizeof(ITETRA) )
- {
- fclose(ptetra);
- return(READERR);
- }
- }
- return(OK);
-
- }
-
- /* convert to assemby if you don't have TC or BC */
- /* getFastColor converts the rgb color to a 17 bit */
- /* index into the lookup table. The look up table */
- /* dither color entry is returned */
-
- int getFastColor(int near *rgb)
- {
-
- asm mov bx, rgb;
-
-
- asm mov dx, [bx +4];
- asm and dl, 0f8h;
- asm xchg dh,dl;
-
- asm mov ax,[bx +2];
- asm and al, 0fch;
- asm mov cl,3;
- asm shl ax,cl;
- asm or dx, ax;
-
-
- asm mov ax,[bx];
- asm mov ch,al; /* save */
- asm mov cl,3;
- asm shr ax,cl;
- asm or dx,ax;
- asm mov es, RGBTableSeg;
- asm mov bx,dx;
- asm xor ah,ah;
- asm mov al, es:[bx];
-
- asm and ch,04;
- asm jz Even;
- asm mov cl,4;
- asm shr al,cl;
- Even:
- asm and al,0fh;
- }
-
-
- /* used by main to compare color selection */
-
- static int ClosestColor(int *rgb)
- {
- long min,temp,sum;
- int k,j,kmin;
-
- min = 0x7fffffff;
- kmin = -1;
- for(k = 0; k < NumDColors; k++)
- {
- sum = 0;
- for( j = 0; j < 3; j++)
- {
- temp = DitherColorTable[3*k + j] - rgb[j];
- sum += temp*temp;
- }
- if( sum < min)
- {
- kmin = k;
- min = sum;
- }
- }
- return(kmin);
- }
-
-
- static void ConvertRGB(float *out, int *in)
- {
- int k;
-
- for(k = 0; k < 3; k++)
- out[k] = in[k]/64.0;
- }
-
- static float ConvertTrig(int value)
- {
- return( value/32767.0);
- }
-
- static float ConvertProb(unsigned int value)
- {
- return( value/65535.0);
- }
-
- /* example use of error dispersion functions */
-
- int cdecl main(int argc, char *argv[])
- {
- int error,k,rgb[3],color,j;
- float frgb[3];
- if( argc > 1)
- error = LoadTetraFile(argv[0],argv[1]);
- else
- error = LoadTetraFile(argv[0],"DGIF.TET");
-
- if( error < 0)
- {
- printf("\n LoadTetraFile Error # %d",error);
- return(0);
- }
-
- if(Dtype == 0)
- printf("\n Tetra Type = Error Dispersion");
- else if(Dtype == 1)
- printf("\n Tetra Type = Uniform Ordered");
- else
- {
- printf("\n Tetra Type Error");
- return(0);
- }
-
-
- /* You would normally set up graphics here. */
- /* If EGA,load palette registers with the values stored in EGAColorPalette[]*/
- /* In EGA mode the display gamma is fixed at 1.7 */
-
- /* If VGA, gamma correct the dither palette before setting the color DAC. */
-
- /* output dither colors */
- printf("\n Number of Dither Colors = %d\n",NumDColors);
- for(k = 0; k < NumDColors; k++)
- printf("\n [%2d], (%3d,%3d,%3d)",k,
- DitherColorTable[3*k],
- DitherColorTable[3*k +1],
- DitherColorTable[3*k +2]);
-
- if(Dtype == 0)
- { /* error dispersion */
- /* use getFastColor function */
-
- rgb[0] = 17;
-
- printf("\n\n getFastColor Test:\n\n");
-
- for( k = 0; k <= 16; k++)
- {
- rgb[1] = (255*k +8)/16;
- rgb[2] = (128*k +8)/16;
- color = getFastColor(rgb);
- printf(" %2d",color);
- }
-
- /* compare with closest color */
-
- printf("\n");
- for( k = 0; k <= 16; k++)
- {
- rgb[1] = (255*k +8)/16;
- rgb[2] = (128*k +8)/16;
- color = ClosestColor(rgb);
- printf(" %2d",color);
- }
- FreeLookUp();
- return(0);
- }
-
- /* Uniform Ordered Dither */
- /* output tetrahedron data */
-
- printf("\n\n NTetra = %u",NTetra);
-
- for(k = 0; k < NTetra; k++)
- {
- printf("\n\n Tetra[%3d] Num Daughter Tetra = %1u",
- k+1,TetraList[k].flags);
-
- printf("\n DIndex[] = {%3d,%3d,%3d,%3d}",
- (int) TetraList[k].DIndex[0],
- (int) TetraList[k].DIndex[1],
- (int) TetraList[k].DIndex[2],
- (int) TetraList[k].DIndex[3]);
-
- ConvertRGB(frgb,TetraList[k].V1);
- printf("\n V1[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
- ConvertRGB(frgb,TetraList[k].V2);
- printf("\n V2[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
- ConvertRGB(frgb,TetraList[k].V3);
- printf("\n V3[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
- ConvertRGB(frgb,TetraList[k].V4);
- printf("\n V4[] = (%8.2f,%8.2f,%8.2f)",frgb[0],frgb[1],frgb[2]);
-
- printf("\n SinA = %8.5f",ConvertTrig(TetraList[k].SinA));
- printf("\n CosA = %8.5f",ConvertTrig(TetraList[k].CosA));
- printf("\n SinB = %8.5f",ConvertTrig(TetraList[k].SinB));
- printf("\n CosB = %8.5f",ConvertTrig(TetraList[k].CosB));
-
- if(TetraList[k].flags > 0)
- { /* print daughter info */
-
- for( j = 0; j < 4; j++)
- {
- printf("\n p[%1d] = %8.5f",j,ConvertProb(TetraList[k].p[j]));
- }
-
- for( j = 0; j < 4; j++)
- {
- printf("\n next[%1d] = %3u",j,TetraList[k].next[j]);
- }
- }
-
-
-
- }
-
- return(0);
- }
-
-
-
-
-
-