home *** CD-ROM | disk | FTP | other *** search
- /* wasp - copyright Steven Reiz 1990, 1991
- * see wasp.c for further info
- * wriffdistr.c, 4/12/90 - 30/1/91, 2/6/91, 23/6/91,
- * 3/7/91 - 10/7/91
- * symbols: SORT_SLICED, SHAM_BLACK
- */
-
- struct hs_t {
- char dist;
- char pad;
- short color;
- };
-
- #include "wasp.h"
- #include "wriff.h"
- #ifndef NOSH
- #include "wriffdistr.sh"
- #endif
- #define SORT_SLICED
- /* #define SHAM_BLACK */
-
-
- static char regind;
- static long squares[]={
- 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225
- };
-
-
- #ifdef __STDC__
- compute_distr(int firstrow, int lastrow)
- #else
- compute_distr(firstrow, lastrow)
- int firstrow, lastrow;
- #endif
- {
- assert(counts!=NULL1);
- if (icolors<=nregs)
- no_distr();
- else {
- switch (distrmeth) {
- case DISTRMETH_MOSTUSED:
- mostused_distr();
- break;
- case DISTRMETH_WORSTFIRST:
- worstfirst_distr();
- break;
- case DISTRMETH_EHB:
- ehb_distr();
- break;
- case DISTRMETH_MUE:
- mue_distr();
- break;
- case DISTRMETH_HAMSHARP:
- hamsharp_distr();
- break;
- case DISTRMETH_CONTRACTION:
- contraction_distr();
- break;
- default:
- error0(E0_FATAL, E1_IFF, E2_OPTION, E3_DISTRMETH);
- break;
- }
- }
- if (xmode!=EHB) {
- #ifdef SORT_SLICED
- sort_cm();
- #else
- if (!slicedo)
- sort_cm();
- #endif
- }
- count_pixels(firstrow, lastrow, 1);
- fill_newcol();
- }
-
-
- #ifdef __STDC__
- PRIVATE no_distr(void)
- #else
- PRIVATE no_distr()
- #endif
- {
- short i;
- u_long th, *p;
- u_short *q;
-
- p=counts+NRGB;
- th=threshold;
- q=curcm;
- i=NRGB-1;
- if (th<=1) {
- do {
- if (*--p)
- *q++ =i;
- } while (--i>=0);
- } else {
- do {
- if (*--p >=th)
- *q++ =i;
- } while (--i>=0);
- }
- assert(q==curcm+icolors);
- while (q<curcm+nregs)
- *q++ =0;
- }
-
-
- #ifdef __STDC__
- PRIVATE mostused_distr(void)
- #else
- PRIVATE mostused_distr()
- #endif
- {
- static u_long regcounts[MAXNREGS];
- u_long *countp, *countp2, th;
- static u_long *savecountp;
- u_short *cmp;
- short i;
-
- countp=regcounts;
- i=nregs-1;
- do {
- *countp++ =0;
- } while (--i>=0);
- th=0;
- countp=counts+NRGB;
- i=NRGB-1;
- do {
- if (*--countp>th) {
- th= *countp;
- savecountp=countp;
- countp=regcounts;
- do {
- /* tight loop! */
- } while (*countp++ >=th);
- countp2=regcounts+nregs;
- cmp=curcm+nregs;
- if (countp2>countp) {
- do {
- *--countp2= *(countp2-2);
- *--cmp = *(cmp-2);
- } while (countp2>countp);
- }
- *--countp2=th;
- *--cmp=i;
- th=regcounts[nregs-1];
- countp=savecountp;
- }
- } while (--i>=0);
- #ifdef SHAM_BLACK
- if (slicedo) {
- for (i=0; i<nregs; ++i)
- if (curcm[i]==0x000)
- break;
- if (i>=nregs) { /* black isn't amongst the colors, add it */
- curcm[nregs-1]=0x000;
- }
- }
- #endif
- }
-
-
- #ifdef __STDC__
- PRIVATE worstfirst_distr(void)
- #else
- PRIVATE worstfirst_distr()
- #endif
- {
- static int sicolors= -1;
- static int startreg;
- int i;
- short rgb1, rgb2;
-
- if (sicolors<icolors) {
- if (sicolors== -1) {
- if (icolors<128)
- sicolors=128;
- else
- sicolors=icolors;
- } else {
- free(wfmindist);
- free(wfminind);
- free(wfrgb);
- if (icolors<256)
- sicolors=256;
- else
- sicolors=icolors;
- }
- wfmindist=Malloc(sicolors);
- wfminind=Malloc(sicolors);
- wfrgb=Malloc(sicolors*3);
- }
- fill_wf_rgb();
- startreg=2;
- #ifdef SHAM_BLACK
- if (slicedo) {
- startreg=1;
- rgb1=0x000; regind=0;
- fill_wf_dist_1(rgb1);
- } else {
- #endif
- find_2_furthest(&rgb1, &rgb2);
- curcm[0]=rgb1; regind=0;
- fill_wf_dist_1(rgb1);
- curcm[1]=rgb2; regind=1;
- fill_wf_dist_2(rgb2);
- #ifdef SHAM_BLACK
- }
- #endif
- for (i=startreg; i<nregs; ++i) {
- find_1_furthest(&rgb1);
- curcm[i]=rgb1; regind=i;
- fill_wf_dist_2(rgb1);
- }
- fill_wf2rgbweight();
- wf2_redo_curcm();
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_wf_rgb(void)
- #else
- PRIVATE fill_wf_rgb()
- #endif
- {
- long i;
- u_long th, *p;
- char *q;
-
- p=counts+NRGB;
- th=threshold;
- q=wfrgb;
- i=NRGB-1;
- if (th<=1) {
- do {
- if (*--p) {
- *q++ =i>>8;
- *q++ =(i>>4)&0x0f;
- *q++ =i&0x0f;
- }
- } while (--i>=0);
- } else {
- do {
- if (*--p >=th) {
- *q++ =i>>8;
- *q++ =(i>>4)&0x0f;
- *q++ =i&0x0f;
- }
- } while (--i>=0);
- }
- assert(q==wfrgb+3*icolors);
- }
-
-
- #ifdef __STDC__
- PRIVATE find_2_furthest(short *rgb1p, short *rgb2p)
- #else
- PRIVATE find_2_furthest(rgb1p, rgb2p)
- short *rgb1p, *rgb2p;
- #endif
- {
- REG char *p, *q;
- REG char r, g, b, t, dist, bigdist;
- NON_REG char *bigp, *bigq;
-
- bigdist=0;
- p=wfrgb+3*icolors;
- while (p>wfrgb) {
- b= *--p;
- g= *--p;
- r= *--p;
- q=wfrgb;
- do {
- if ((dist=r- *q++)<0) dist= -dist;
- if ((t=g- *q++)<0) dist-=t; else dist+=t;
- if ((t=b- *q++)<0) dist-=t; else dist+=t;
- if (dist>bigdist) {
- bigdist=dist;
- bigp=p;
- bigq=q;
- }
- } while (q<p);
- }
- *rgb1p=(*bigp<<8) |(*(bigp+1)<<4)|(*(bigp+2));
- *rgb2p=(*(bigq-3)<<8)|(*(bigq-2)<<4)|(*(bigq-1));
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_wf_dist_1(short color)
- #else
- PRIVATE fill_wf_dist_1(color)
- short color;
- #endif
- {
- short i;
- char r, g, b, t, dist;
- char *mdp, *mip, *rgbp;
-
- r=color>>8;
- g=(color>>4)&0x0f;
- b=color&0x0f;
- mdp=wfmindist+icolors;
- mip=wfminind+icolors;
- rgbp=wfrgb+3*icolors;
- i=icolors-1;
- do {
- if ((dist=b- *--rgbp)<0) dist= -dist;
- if ((t=g- *--rgbp)<0) dist-=t; else dist+=t;
- if ((t=r- *--rgbp)<0) dist-=t; else dist+=t;
- *--mdp=dist;
- *--mip=regind;
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_wf_dist_2(short color)
- #else
- PRIVATE fill_wf_dist_2(color)
- short color;
- #endif
- {
- short i;
- char r, g, b, t, dist;
- char *mdp, *mip, *rgbp;
-
- r=color>>8;
- g=(color>>4)&0x0f;
- b=color&0x0f;
- mdp=wfmindist+icolors;
- mip=wfminind+icolors;
- rgbp=wfrgb+3*icolors;
- i=icolors-1;
- do {
- if ((dist=b- *--rgbp)<0) dist= -dist;
- if ((t=g- *--rgbp)<0) dist-=t; else dist+=t;
- if ((t=r- *--rgbp)<0) dist-=t; else dist+=t;
- if (dist< *--mdp) {
- *mdp=dist;
- *--mip=regind;
- } else
- --mip;
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE find_1_furthest(short *rgbp)
- #else
- PRIVATE find_1_furthest(rgbp)
- short *rgbp;
- #endif
- {
- char *p, max;
- short i, maxi;
-
- p=wfmindist+icolors;
- max=0;
- i=icolors-1;
- do {
- if (*--p>max) {
- max= *p;
- maxi=i;
- }
- } while (--i>=0);
- p=wfrgb+3*maxi;
- *rgbp=(*p<<8)|(*(p+1)<<4)|(*(p+2));
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_wf2rgbweight(void)
- #else
- PRIVATE fill_wf2rgbweight()
- #endif
- {
- char *rgbp, *mip;
- u_long *weightp, weight;
- short i;
- char r, g, b;
-
- if (wf2rgbweight==NULL1)
- wf2rgbweight=Malloc(nregs*4*sizeof(u_long));
- weightp=wf2rgbweight;
- i=nregs-1;
- do {
- *weightp++ =0;
- *weightp++ =0;
- *weightp++ =0;
- *weightp++ =0;
- } while (--i>=0);
- rgbp=wfrgb;
- mip=wfminind;
- i=icolors-1;
- do {
- r= *rgbp++;
- g= *rgbp++;
- b= *rgbp++;
- weight=counts[(r<<8)|(g<<4)|b];
- weightp=wf2rgbweight+4* (*mip++);
- *weightp++ += r*weight;
- *weightp++ += g*weight;
- *weightp++ += b*weight;
- *weightp += weight;
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE wf2_redo_curcm(void)
- #else
- PRIVATE wf2_redo_curcm()
- #endif
- {
- u_long *weightp, weight, r, g, b;
- short i;
- u_short *cmp;
-
- weightp=wf2rgbweight;
- cmp=curcm;
- i=nregs-1;
- do {
- r= *weightp++;
- g= *weightp++;
- b= *weightp++;
- weight= *weightp++;
- if (!weight)
- weight=1;
- r=(r+weight/2)/weight;
- if (r>15) r=15;
- g=(g+weight/2)/weight;
- if (g>15) g=15;
- b=(b+weight/2)/weight;
- if (b>15) b=15;
- *cmp++ =(r<<8)|(g<<4)|b;
- } while (--i>=0);
- #ifdef SHAM_BLACK
- if (slicedo)
- black_darkest();
- #endif
- }
-
-
- #ifdef __STDC__
- PRIVATE black_darkest(void)
- #else
- PRIVATE black_darkest()
- #endif
- {
- short i, besti, val, bestval;
-
- bestval=100;
- for (i=0; i<nregs; ++i) {
- val=(curcm[i]&0xf)+((curcm[i]>>4)&0xf)+(curcm[i]>>8);
- if (val<bestval) {
- bestval=val;
- besti=i;
- }
- }
- curcm[besti]=0x000;
- }
-
-
- #ifdef __STDC__
- PRIVATE ehb_distr(void)
- #else
- PRIVATE ehb_distr()
- #endif
- {
- static int sicolors= -1;
- int i, nr;
- short rgb1, rgb2;
-
- nr=nregs/2;
- if (sicolors<icolors) {
- if (sicolors== -1) {
- if (icolors<128)
- sicolors=128;
- else
- sicolors=icolors;
- } else {
- free(wfmindist);
- free(wfminind);
- free(wfrgb);
- if (icolors<256)
- sicolors=256;
- else
- sicolors=icolors;
- }
- wfmindist=Malloc(sicolors);
- wfminind=Malloc(sicolors);
- wfrgb=Malloc(sicolors*3);
- }
- fill_wf_rgb();
- find_2_furthest(&rgb1, &rgb2);
- regind=0;
- fill_wf_dist_1(rgb1);
- ehb_pair(rgb1, 0);
- for (i=1; i<nr; ++i) {
- find_1_furthest(&rgb1);
- regind=i;
- fill_wf_dist_2(rgb1);
- ehb_pair(rgb1, i);
- }
- fill_wf2rgbweight();
- ehb_redo_curcm();
- }
-
-
- #ifdef __STDC__
- PRIVATE ehb_pair(short c1, int i)
- #else
- PRIVATE ehb_pair(c1, i)
- short c1;
- int i;
- #endif
- {
- short c2, c3, c4;
- short r, g, b;
- int nr;
-
- nr=nregs/2;
- r=c1>>8;
- g=(c1>>4)&0x0f;
- b=c1&0x0f;
- c2=((r>>1)<<8)|((g>>1)<<4)|(b>>1);
- if (r<8 && g<8 && b<8) {
- c3=(r<<9)|(g<<5)|(b<<1);
- ehb_worst(c2, c3, &c4);
- if (c4==c2) {
- curcm[i]=c1;
- curcm[nr+i]=c2;
- regind=nr+i;
- } else {
- curcm[i]=c4;
- curcm[nr+i]=c1;
- c2=c4;
- ehb_minind_adjust((int)i, (int)(nr+i));
- regind=i;
- }
- } else {
- curcm[i]=c1;
- curcm[nr+i]=c2;
- regind=nr+i;
- }
- fill_wf_dist_2(c2);
- }
-
-
- #ifdef __STDC__
- PRIVATE ehb_worst(short col1, short col8, short *worstp)
- #else
- PRIVATE ehb_worst(col1, col8, worstp)
- short col1, col8;
- short *worstp;
- #endif
- {
- short curcol;
- int curdist, bestdist;
- short i;
-
- bestdist=ehb_farcol(col1);
- *worstp=col1;
- i=7;
- do {
- curcol=col8;
- if (i&1)
- curcol|=0x001;
- if (i&2)
- curcol|=0x010;
- if (i&4)
- curcol|=0x100;
- curdist=ehb_farcol(curcol);
- if (curdist>bestdist) {
- bestdist=curdist;
- *worstp=curcol;
- }
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE int ehb_farcol(short color)
- #else
- PRIVATE int ehb_farcol(color)
- short color;
- #endif
- {
- char r, g, b;
- char *p, *q;
- char t, dist, bigdist;
- short i;
-
- r=color>>8;
- g=(color>>4)&0x0f;
- b=color&0x0f;
- bigdist=0;
- i=icolors-1;
- p=wfmindist;
- q=wfrgb;
- do {
- if ((dist=r- *q++)>0) dist= -dist;
- if ((t=g- *q++)>0) dist-=t; else dist+=t;
- if ((t=b- *q++)>0) dist-=t; else dist+=t;
- dist+= *p++;
- if (dist>bigdist)
- bigdist=dist;
- } while (--i>=0);
- return (int)bigdist;
- }
-
-
- #ifdef __STDC__
- PRIVATE ehb_minind_adjust(int from, int to)
- #else
- PRIVATE ehb_minind_adjust(from, to)
- int from, to;
- #endif
- {
- char *p;
- char fromc, toc;
- short i;
-
- p=wfminind+icolors;
- i=icolors-1;
- fromc=from;
- toc=to;
- do {
- if (*--p ==fromc)
- *p=toc;
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE ehb_redo_curcm(void)
- #else
- PRIVATE ehb_redo_curcm()
- #endif
- {
- short nr, i;
- long r1, g1, b1, w1, r2, g2, b2, w2;
- u_long *p1, *p2;
-
- nr=nregs/2;
- p1=wf2rgbweight;
- p2=wf2rgbweight+4*nr;
- for (i=0; i<nr; ++i) {
- r1= *p1++; g1= *p1++; b1= *p1++; w1= *p1++;
- r2=(*p2++)<<1; g2=(*p2++)<<1; b2=(*p2++)<<1; w2= *p2++;
- w1=w1+w2;
- assert(w1);
- w2=w1/2;
- r1=(r1+r2+w2)/w1;
- if (r1>15) r1=15;
- g1=(g1+g2+w2)/w1;
- if (g1>15) g1=15;
- b1=(b1+b2+w2)/w1;
- if (b1>15) b1=15;
- curcm[i]=(r1<<8)|(g1<<4)|b1;
- r1>>=1; g1>>=1; b1>>=1;
- curcm[nr+i]=(r1<<8)|(g1<<4)|b1;
- }
- }
-
-
- #ifdef __STDC__
- PRIVATE mue_distr(void)
- #else
- PRIVATE mue_distr()
- #endif
- {
- static u_long regcounts[MAXNREGS];
- u_long *countp, *countp2, th;
- static u_long *savecountp;
- u_short *cmp;
- short i, nr;
-
- nr=nregs/2;
- countp=regcounts;
- i=nr-1;
- do {
- *countp++ =0;
- } while (--i>=0);
- th=0;
- countp=counts+NRGB;
- i=NRGB-1;
- do {
- if (*--countp>th) {
- th= *countp;
- savecountp=countp;
- countp=regcounts;
- do {
- /* tight loop! */
- } while (*countp++ >=th);
- countp2=regcounts+nr;
- cmp=curcm+nr;
- if (countp2>countp) {
- do {
- *--countp2= *(countp2-2);
- *--cmp = *(cmp-2);
- } while (countp2>countp);
- }
- *--countp2=th;
- *--cmp=i;
- th=regcounts[nr-1];
- countp=savecountp;
- }
- } while (--i>=0);
- mue_extend();
- }
-
-
- #ifdef __STDC__
- PRIVATE mue_extend(void)
- #else
- PRIVATE mue_extend()
- #endif
- {
- short i;
- short r, g, b, color;
- u_short *p, *q;
-
- i=nregs/2;
- p=curcm;
- q=p+i;
- --i;
- do {
- color= *p++;
- r=color>>9;
- g=(color>>5)&0x07;
- b=(color>>1)&0x07;
- *q++ = (r<<8)|(g<<4)|b;
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE hamsharp_distr(void)
- #else
- PRIVATE hamsharp_distr()
- #endif
- {
- static int sicolors= -1;
- int i;
-
- if (sicolors<icolors) {
- if (sicolors!= -1) {
- for (i=0; i<sicolors; ++i)
- free(hshead[i]);
- free(hshead);
- free(hsmark);
- free(wfminind);
- free(wfrgb);
- }
- sicolors=icolors;
- wfrgb=Malloc(sicolors*3);
- wfminind=Malloc(sicolors);
- hsmark=Malloc(sicolors);
- hshead=Malloc(sicolors*sizeof(void *));
- for (i=0; i<sicolors; ++i)
- hshead[i]=Malloc(sicolors*sizeof(struct hs_t));
- }
- fill_wf_rgb();
- fill_hsmark();
- fill_hshead();
- fill_hs_cm();
- fill_wf2rgbweight();
- wf2_redo_curcm();
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_hsmark(void)
- #else
- PRIVATE fill_hsmark()
- #endif
- {
- short i;
- char *q;
-
- q=hsmark;
- i=icolors-1;
- do {
- *q++ =1;
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE int cmphs(struct hs_t *p1, struct hs_t *p2)
- #else
- PRIVATE int cmphs(p1, p2)
- struct hs_t *p1, *p2;
- #endif
- {
- return p1->dist - p2->dist;
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_hshead(void)
- #else
- PRIVATE fill_hshead()
- #endif
- {
- REG char *p, *q;
- REG struct hs_t *hp;
- NON_REG int ic;
- REG short i;
- REG char r, g, b, t, dist;
-
- p=wfrgb+3*icolors;
- ic=icolors;
- while (p>wfrgb) {
- b= *--p;
- g= *--p;
- r= *--p;
- q=wfrgb+3*icolors;
- hp=hshead[--ic];
- i=icolors-1;
- do {
- if ((dist=b- *--q)<0) dist= -dist;
- if ((t=g- *--q)<0) dist-=t; else dist+=t;
- if ((t=r- *--q)<0) dist-=t; else dist+=t;
- hp->dist=dist;
- hp->color=i;
- ++hp;
- } while (--i>=0);
- qsort((char *)hshead[ic], (int)icolors, sizeof(struct hs_t), cmphs);
- }
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_hs_cm(void)
- #else
- PRIVATE fill_hs_cm()
- #endif
- {
- NON_REG short j;
- REG short i, k, bestk, colperreg;
- REG long dist, bestdist;
- REG struct hs_t *p;
- REG char *q, *r;
-
- colperreg=icolors/nregs;
- q=hsmark;
- for (j=0; j<nregs; ++j) {
- if (j==nregs-1)
- colperreg+=icolors-nregs*colperreg;
- bestdist=1000000000L;
- for (k=0; k<icolors; ++k) {
- dist=0;
- p=hshead[k];
- i=colperreg-1;
- do {
- while (!q[p->color])
- ++p;
- dist+=p->dist;
- ++p;
- } while (--i>=0);
- if (dist<bestdist) {
- bestdist=dist;
- bestk=k;
- }
- }
- p=hshead[bestk];
- i=colperreg-1;
- do {
- while (!q[p->color])
- ++p;
- q[p->color]=0;
- wfminind[p->color]=j;
- ++p;
- } while (--i>=0);
- r=wfrgb+3*bestk;
- curcm[j]=(*r<<8)|(*(r+1)<<4)|*(r+2);
- }
- }
-
-
- #define CONTRACT2
- #ifdef __STDC__
- PRIVATE contraction_distr(void)
- #else
- PRIVATE contraction_distr()
- #endif
- {
- static int sicolors= -1;
- int i;
-
- if (sicolors!= -1) {
- for (i=0; i<sicolors; ++i)
- if (cthead[i])
- free(cthead[i]);
- free(cthead);
- free(ctrgbw);
- }
- sicolors=icolors;
- ctrgbw=Malloc(sicolors*4*sizeof(float));
- cthead=Malloc(sicolors*sizeof(void *));
- cthead[0]=NULL;
- for (i=1; i<sicolors; ++i)
- cthead[i]=Malloc(i*sizeof(float));
- fill_ctrgbw();
- fill_cthead();
- do_contraction();
- fill_ct_cm();
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_ctrgbw(void)
- #else
- PRIVATE fill_ctrgbw()
- #endif
- {
- short i;
- u_long th, *p;
- float *q;
-
- p=counts+NRGB;
- th=threshold;
- q=ctrgbw;
- i=NRGB-1;
- do {
- if (*--p >=th) {
- *q++ =(float)(i>>8);
- *q++ =(float)((i>>4)&0x0f);
- *q++ =(float)(i&0x0f);
- *q++ =(float)*p;
- }
- } while (--i>=0);
- assert(q==ctrgbw+4*icolors);
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_cthead(void)
- #else
- PRIVATE fill_cthead()
- #endif
- {
- short i, j;
- float *p, *q;
- float r, g, b, dist, t;
-
- for (i=1; i<icolors; ++i) {
- p=cthead[i];
- q=ctrgbw+4*i;
- r= *q++;
- g= *q++;
- b= *q;
- q=ctrgbw;
- #ifdef CONTRACT2
- for (j=0; j<i; ++j) {
- t=r- *q++; dist=t*t;
- t=g- *q++; dist+=t*t;
- t=b- *q++; dist+=t*t;
- ++q;
- *p++ =dist;
- }
- #else
- for (j=0; j<i; ++j) {
- if ((dist=r- *q++)<0) dist= -dist;
- if ((t=g- *q++)<0) dist-=t; else dist+=t;
- if ((t=b- *q++)<0) dist-=t; else dist+=t;
- ++q;
- *p++ =dist;
- }
- #endif
- }
- }
-
-
- #ifdef __STDC__
- PRIVATE do_contraction(void)
- #else
- PRIVATE do_contraction()
- #endif
- {
- short ncolors, i, j, besti, bestj;
- float *p, *q, bestdist;
- float newr, newg, newb, neww, wi, wj;
- float t, dist;
-
- ncolors=icolors;
- while (ncolors>nregs) {
- /* find minimum pair */
- bestdist=2000.0;
- for (i=0; i<icolors; ++i) {
- p=cthead[i];
- if (!p)
- continue;
- j=0;
- do {
- if (*p++ <bestdist) {
- besti=i;
- bestj=j;
- bestdist= *(p-1);
- }
- } while (++j<i);
- }
- /* contract pair to new pair */
- p=ctrgbw+4*besti;
- q=ctrgbw+4*bestj;
- wi=p[3];
- wj=q[3];
- neww=wi+wj;
- newr=(wi*p[0]+wj*q[0])/neww;
- newg=(wi*p[1]+wj*q[1])/neww;
- newb=(wi*p[2]+wj*q[2])/neww;
- /* delete 1 of pair */
- if (bestj>besti) {
- i=besti;
- besti=bestj;
- bestj=i;
- }
- free(cthead[besti]);
- cthead[besti]=NULL;
- ctrgbw[4*besti+3]= -1.0;
- for (i=besti+1; i<icolors; ++i) {
- p=cthead[i];
- if (p)
- p[besti]=1000.0;
- }
- /* replace other of pair by new contracted color */
- p=ctrgbw+4*bestj;
- *p++ =newr;
- *p++ =newg;
- *p++ =newb;
- *p =neww;
- for (i=bestj+1, q=ctrgbw+4*i; i<icolors; ++i) {
- p=cthead[i];
- if (p) {
- #ifdef CONTRACT2
- t=newr- *q++; dist=t*t;
- t=newg- *q++; dist+=t*t;
- t=newb- *q++; dist+=t*t;
- #else
- if ((dist=newr- *q++)<0) dist= -dist;
- if ((t=newg- *q++)<0) dist-=t; else dist+=t;
- if ((t=newb- *q++)<0) dist-=t; else dist+=t;
- #endif
- ++q;
- p[bestj]=dist;
- } else {
- q+=4;
- }
- }
- for (i=0, p=cthead[bestj]; i<bestj; ++i) {
- q=ctrgbw+4*i;
- if (q[3]< -0.5) {
- *p++ =1000.0;
- } else {
- #ifdef CONTRACT2
- t=newr- *q++; dist=t*t;
- t=newg- *q++; dist+=t*t;
- t=newb- *q; dist+=t*t;
- #else
- if ((dist=newr- *q++)<0) dist= -dist;
- if ((t=newg- *q++)<0) dist-=t; else dist+=t;
- if ((t=newb- *q)<0) dist-=t; else dist+=t;
- #endif
- *p++ =dist;
- }
- }
- /* decrease number of colors */
- --ncolors;
- }
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_ct_cm(void)
- #else
- PRIVATE fill_ct_cm()
- #endif
- {
- float *p;
- u_short *q, color;
- short i;
-
- p=ctrgbw;
- q=curcm;
- i=icolors-1;
- do {
- if (p[3]< -0.5) {
- p+=4;
- } else {
- color =((int)(*p++ + 0.5)<<8)&0xf00;
- color|=((int)(*p++ + 0.5)<<4)&0x0f0;
- color|=((int)(*p++ + 0.5)) &0x00f;
- ++p;
- *q++ =color;
- }
- } while (--i>=0);
- assert(q==curcm+nregs);
- #ifdef SHAM_BLACK
- if (slicedo)
- black_darkest();
- #endif
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_cmrgb(void)
- #else
- PRIVATE fill_cmrgb()
- #endif
- {
- short i, color;
- u_short *p;
- char *q;
-
- if (cmrgb==NULL1)
- cmrgb=Malloc(3*nregs);
- p=curcm;
- q=cmrgb;
- i=nregs-1;
- do {
- color= *p++;
- *q++ = color>>8;
- *q++ = (color>>4)&0x0f;
- *q++ = color&0x0f;
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- fill_newcol(void)
- #else
- fill_newcol()
- #endif
- {
- short i, mini;
- char r, g, b, min, dist, t;
- NON_REG short savei;
- u_long *countp;
- char *rgbp;
-
- fill_cmrgb();
- if (newcol==NULL1) {
- newcol=Malloc(NRGB);
- error=Malloc(NRGB);
- error2=Malloc(NRGB*sizeof(u_long));
- }
- i=NRGB-1;
- countp=counts+NRGB;
- do {
- if (*--countp) {
- savei=i;
- r=i>>8;
- g=(i>>4)&0x0f;
- b=i&0x0f;
- min=100;
- rgbp=cmrgb+3*nregs;
- i=nregs-1;
- do {
- if ((dist=b- *--rgbp)<0) dist= -dist;
- if ((t=g- *--rgbp)<0) dist-=t; else dist+=t;
- if ((t=r- *--rgbp)<0) dist-=t; else dist+=t;
- if (dist<min) {
- min=dist;
- mini=i;
- }
- } while (--i>=0);
- i=savei;
- newcol[i]=mini;
- error[i]=min;
- rgbp=cmrgb+3*mini;
- if ((t=r- *rgbp++)<0) t= -t; error2[i]=squares[t];
- if ((t=g- *rgbp++)<0) t= -t; error2[i]+=squares[t];
- if ((t=b- *rgbp )<0) t= -t; error2[i]+=squares[t];
- }
- } while (--i>=0);
- }
-
-
- #ifdef __STDC__
- fill_newcol_count(void)
- #else
- fill_newcol_count()
- #endif
- {
- short i, mini;
- char r, g, b, min, dist, t;
- NON_REG short savei;
- u_long *countp;
- char *rgbp;
-
- fill_cmrgb();
- if (newcol==NULL1) {
- newcol=Malloc(NRGB);
- error=Malloc(NRGB);
- error2=Malloc(NRGB*sizeof(u_long));
- }
- i=NRGB-1;
- countp=counts+NRGB;
- do {
- if (*--countp) {
- savei=i;
- r=i>>8;
- g=(i>>4)&0x0f;
- b=i&0x0f;
- min=100;
- rgbp=cmrgb+3*nregs;
- i=nregs-1;
- do {
- if ((dist=b- *--rgbp)<0) dist= -dist;
- if ((t=g- *--rgbp)<0) dist-=t; else dist+=t;
- if ((t=r- *--rgbp)<0) dist-=t; else dist+=t;
- if (dist<min) {
- min=dist;
- mini=i;
- }
- } while (--i>=0);
- i=savei;
- newcol[i]=mini;
- error[i]=min;
- }
- } while (--i>=0);
- }
-