#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "3dtable.h"
struct match_array *creatematcharray(int rbits, int gbits,
int bbits, struct rgb_color *palette, int palettesize)
{
int rval, gval, bval, len, r, g, b;
char *taken, *match, *same;
int i, set, sqstep, tp, maxtp, *entryr, *entryg, *entryb;
struct match_array *table;
if(rbits<1 || rbits>8 || gbits<1 || gbits>8 || bbits<1 || bbits>8)
return NULL;
table=(struct match_array *)malloc(sizeof(struct match_array));
if (table==NULL) return NULL;
/* Set up some values: */
table->rb=rbits;
table->gb=gbits;
table->bb=bbits;
rval=1<<rbits;
gval=1<<gbits;
bval=1<<bbits;
len=rval*gval*bval;
/* Prepare table buffers: */
table->match=(char *)malloc(len*sizeof(char));
if (table->match==NULL)
{
free((void *)table);
return NULL;
}
taken=(char *)malloc(len*sizeof(char));
if (taken==NULL)
{
free((void *)table->match);
free((void *)table);
return NULL;
};
memset((void *)taken, 0, len*sizeof(char));
/* Select colors to use for fill: */
set=0;
entryr=(int *)malloc(palettesize*sizeof(int));
entryg=(int *)malloc(palettesize*sizeof(int));
entryb=(int *)malloc(palettesize*sizeof(int));
same=(char *)malloc(palettesize*sizeof(char));
if (entryr==NULL || entryg==NULL || entryb==NULL || same==NULL)
{
free((void *)table->match), free((void *)table),
free((void *)entryr), free((void *)entryg),
free((void *)entryb), free((void *)same);
return NULL;
}
match=table->match;
for (i=0; i<palettesize; i++)
{
same[i]=0;
/* Compute 3d-table coordinates of palette rgb color: */
r=palette[i].r&0xff, g=palette[i].g&0xff, b=palette[i].b&0xff;
r>>=8-rbits;
g>>=8-gbits;
b>>=8-bbits;
/* Put color in position: */
if (taken[b*rval*gval+g*rval+r]==0) set++;
else same[match[b*rval*gval+g*rval+r]]=1;
match[b*rval*gval+g*rval+r]=i;
taken[b*rval*gval+g*rval+r]=1;
entryr[i]=r; entryg[i]=g; entryb[i]=b;
}
/* @@@ Fill match_array by steps: @@@ */
for (set=len-set, sqstep=1; set>0; sqstep++)
{
for (i=0; i<palettesize && set>0; i++)
if (same[i]==0)
{
/* Fill all six sides of incremented cube
(by pairs, 3 loops): */
for (b=entryb[i]-sqstep; b<=entryb[i]+sqstep; b+=sqstep*2)
if (b>=0 && b<bval)
for (r=entryr[i]-sqstep; r<=entryr[i]+sqstep; r++)
if (r>=0 && r<rval)
{ /* Draw one 3d line: */
tp=b*rval*gval+(entryg[i]-sqstep)*rval+r;
maxtp=b*rval*gval+(entryg[i]+sqstep)*rval+r;
if (tp<b*rval*gval+0*rval+r)
tp=b*rval*gval+0*rval+r;
if (maxtp>b*rval*gval+(gval-1)*rval+r)
maxtp=b*rval*gval+(gval-1)*rval+r;
for (; tp<=maxtp; tp+=rval)
if (!taken[tp])
taken[tp]=1, match[tp]=i, set--;
}
for (g=entryg[i]-sqstep; g<=entryg[i]+sqstep; g+=sqstep*2)
if (g>=0 && g<gval)
for (b=entryb[i]-sqstep; b<=entryb[i]+sqstep; b++)
if (b>=0 && b<bval)
{ /* Draw one 3d line: */
tp=b*rval*gval+g*rval+(entryr[i]-sqstep);
maxtp=b*rval*gval+g*rval+(entryr[i]+sqstep);
if (tp<b*rval*gval+g*rval+0)
tp=b*rval*gval+g*rval+0;
if (maxtp>b*rval*gval+g*rval+(rval-1))
maxtp=b*rval*gval+g*rval+(rval-1);
for (; tp<=maxtp; tp++)
if (!taken[tp])
taken[tp]=1, match[tp]=i, set--;
}
for (r=entryr[i]-sqstep; r<=entryr[i]+sqstep; r+=sqstep*2)
if (r>=0 && r<rval)
for (g=entryg[i]-sqstep; g<=entryg[i]+sqstep; g++)
if (g>=0 && g<gval)
{ /* Draw one 3d line: */
tp=(entryb[i]-sqstep)*rval*gval+g*rval+r;
maxtp=(entryb[i]+sqstep)*rval*gval+g*rval+r;
if (tp<0*rval*gval+g*rval+r)
tp=0*rval*gval+g*rval+r;
if (maxtp>(bval-1)*rval*gval+g*rval+r)
maxtp=(bval-1)*rval*gval+g*rval+r;
for (; tp<=maxtp; tp+=rval*gval)
if (!taken[tp])
taken[tp]=1, match[tp]=i, set--;
}
}
}
free((void *)same);
free((void *)entryr);
free((void *)entryg);
free((void *)entryb);
free((void *)taken);
return table;
}
void deletematcharray(struct match_array *table)
{
if (table!=NULL)
{
free((void *)table->match);
free((void *)table);
}
}
int findcolor(struct match_array *table, struct rgb_color c)
{
int r=c.r, g=c.g, b=c.b;
if (r<0) r=0; if (r>255) r=255;
if (g<0) g=0; if (g>255) g=255;
if (b<0) b=0; if (b>255) b=255;
if (table!=NULL)
{
r>>=8-table->rb;
g>>=8-table->gb;
b>>=8-table->bb;
return table->match[(b<<table->gb<<table->rb)+(g<<table->rb)+r];
}
return -1;
}
/* End of File */