Subversion Repositories eduke32

Rev

Rev 5367 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5359 hendricks2 1
 
2
#include "colmatch.h"
3
 
4
#define FASTPALCOLDEPTH 256
5
#define FASTPALRIGHTSHIFT 3
6
#define FASTPALRGBDIST (FASTPALCOLDEPTH*2+1)
7
static int32_t rdist[FASTPALRGBDIST], gdist[FASTPALRGBDIST], bdist[FASTPALRGBDIST];
8
#define FASTPALGRIDSIZ (FASTPALCOLDEPTH>>FASTPALRIGHTSHIFT)
9
static char colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
10
static char colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
11
static int32_t colnext[256];
12
#define FASTPALCOLDIST (1<<FASTPALRIGHTSHIFT)
13
#define FASTPALCOLDISTMASK (FASTPALCOLDIST-1)
14
static uint8_t coldist[FASTPALCOLDIST];
15
static int32_t colscan[27];
16
 
17
static uint8_t const * colmatch_palette;
18
 
19
#define pow2char(x) (1u << (x))
20
 
21
//
22
// initfastcolorlookup
23
//
24
void initfastcolorlookup_scale(int32_t rscale, int32_t gscale, int32_t bscale)
25
{
26
    int32_t j = 0;
27
    for (int i=256; i>=0; i--)
28
    {
29
        //j = (i-64)*(i-64);
30
        rdist[i] = rdist[FASTPALCOLDEPTH*2-i] = j*rscale;
31
        gdist[i] = gdist[FASTPALCOLDEPTH*2-i] = j*gscale;
32
        bdist[i] = bdist[FASTPALCOLDEPTH*2-i] = j*bscale;
33
        j += FASTPALRGBDIST-(i<<1);
34
    }
35
}
36
void initfastcolorlookup_palette(uint8_t const * const pal)
37
{
38
    Bmemset(colhere,0,sizeof(colhere));
39
    Bmemset(colhead,0,sizeof(colhead));
40
 
41
    colmatch_palette = pal;
42
 
43
    char const *pal1 = (char *)&pal[768-3];
44
    for (int i=255; i>=0; i--,pal1-=3)
45
    {
46
        int32_t const j = (pal1[0]>>FASTPALRIGHTSHIFT)*FASTPALGRIDSIZ*FASTPALGRIDSIZ
47
            + (pal1[1]>>FASTPALRIGHTSHIFT)*FASTPALGRIDSIZ + (pal1[2]>>FASTPALRIGHTSHIFT)
48
            + FASTPALGRIDSIZ*FASTPALGRIDSIZ + FASTPALGRIDSIZ + 1;
49
        if (colhere[j>>3]&pow2char(j&7)) colnext[i] = colhead[j]; else colnext[i] = -1;
50
        colhead[j] = i;
51
        colhere[j>>3] |= pow2char(j&7);
52
    }
53
}
54
void initfastcolorlookup_gridvectors(void)
55
{
56
    int i = 0;
57
    int32_t x, y, z;
58
    for (x=-FASTPALGRIDSIZ*FASTPALGRIDSIZ; x<=FASTPALGRIDSIZ*FASTPALGRIDSIZ; x+=FASTPALGRIDSIZ*FASTPALGRIDSIZ)
59
        for (y=-FASTPALGRIDSIZ; y<=FASTPALGRIDSIZ; y+=FASTPALGRIDSIZ)
60
            for (z=-1; z<=1; z++)
61
                colscan[i++] = x+y+z;
62
    i = colscan[13]; colscan[13] = colscan[26]; colscan[26] = i;
63
 
64
    for (i = 0; i < FASTPALCOLDIST/2; i++)
65
        coldist[i] = i;
66
    for (; i < FASTPALCOLDIST; i++)
67
        coldist[i] = FASTPALCOLDIST-i;
68
}
69
 
70
#define COLRESULTSIZ 4096
71
 
72
static uint32_t getclosestcol_results[COLRESULTSIZ];
73
static int32_t numclosestcolresults;
74
 
75
void getclosestcol_flush(void)
76
{
77
    Bmemset(getclosestcol_results, 0, COLRESULTSIZ * sizeof(uint32_t));
78
    numclosestcolresults = 0;
79
}
80
 
81
// Finds a color index in [0 .. lastokcol] closest to (r, g, b).
82
// <lastokcol> must be in [0 .. 255].
83
int32_t getclosestcol_lim(int32_t r, int32_t g, int32_t b, int32_t lastokcol)
84
{
85
    const int j = (r>>FASTPALRIGHTSHIFT)*FASTPALGRIDSIZ*FASTPALGRIDSIZ
86
        + (g>>FASTPALRIGHTSHIFT)*FASTPALGRIDSIZ + (b>>FASTPALRIGHTSHIFT)
87
        + FASTPALGRIDSIZ*FASTPALGRIDSIZ
88
        + FASTPALGRIDSIZ + 1;
89
 
90
#ifdef DEBUGGINGAIDS
91
    Bassert(lastokcol >= 0 && lastokcol <= 255);
92
#endif
93
 
94
    uint32_t const col = r | (g<<8) | (b<<16);
95
 
96
    int mindist = -1;
97
 
98
    int const k = (numclosestcolresults > COLRESULTSIZ) ? (COLRESULTSIZ-4) : (numclosestcolresults-4);
99
 
100
    if (!numclosestcolresults) goto skip;
101
 
102
    if (col == (getclosestcol_results[(numclosestcolresults-1) & (COLRESULTSIZ-1)] & 0x00ffffff))
103
        return getclosestcol_results[(numclosestcolresults-1) & (COLRESULTSIZ-1)]>>24;
104
 
105
    int i;
106
 
107
    for (i = 0; i < k+4; i+=4)
108
    {
109
        if (col == (getclosestcol_results[i]   & 0x00ffffff)) { mindist = i; break; }
110
        if (col == (getclosestcol_results[i+1] & 0x00ffffff)) { mindist = i+1; break; }
111
        if (col == (getclosestcol_results[i+2] & 0x00ffffff)) { mindist = i+2; break; }
112
        if (col == (getclosestcol_results[i+3] & 0x00ffffff)) { mindist = i+3; break; }
113
    }
114
 
115
    if (mindist == -1)
116
    for (; i < k; i++)
117
        if (col == (getclosestcol_results[i] & 0x00ffffff)) { mindist = i; break; }
118
 
119
    if (mindist != -1 && getclosestcol_results[mindist]>>24 < (unsigned)lastokcol)
120
        return getclosestcol_results[mindist]>>24;
121
 
122
skip:
123
    getclosestcol_results[numclosestcolresults & (COLRESULTSIZ-1)] = col;
124
 
125
    int const minrdist = rdist[coldist[r&FASTPALCOLDISTMASK]+FASTPALCOLDEPTH];
126
    int const mingdist = gdist[coldist[g&FASTPALCOLDISTMASK]+FASTPALCOLDEPTH];
127
    int const minbdist = bdist[coldist[b&FASTPALCOLDISTMASK]+FASTPALCOLDEPTH];
128
 
129
    mindist = min(minrdist, mingdist);
130
    mindist = min(mindist, minbdist) + 1;
131
 
132
    r = FASTPALCOLDEPTH-r, g = FASTPALCOLDEPTH-g, b = FASTPALCOLDEPTH-b;
133
 
134
    int retcol = -1;
135
 
136
    for (int k=26; k>=0; k--)
137
    {
138
        i = colscan[k]+j;
139
 
140
        if ((colhere[i>>3]&pow2char(i&7)) == 0)
141
            continue;
142
 
143
        i = colhead[i];
144
 
145
        do
146
        {
147
            char const * const pal1 = (char *)&colmatch_palette[i*3];
148
            int dist = gdist[pal1[1]+g];
149
 
150
            if (dist >= mindist || i > lastokcol) continue;
151
            if ((dist += rdist[pal1[0]+r]) >= mindist) continue;
152
            if ((dist += bdist[pal1[2]+b]) >= mindist) continue;
153
 
154
            mindist = dist;
155
            retcol = i;
156
        }
157
        while ((i = colnext[i]) >= 0);
158
    }
159
 
160
    if (retcol >= 0)
161
    {
162
        getclosestcol_results[numclosestcolresults++ & (COLRESULTSIZ-1)] |= retcol<<24;
163
        return retcol;
164
    }
165
 
166
    mindist = INT32_MAX;
167
 
168
    for (i=lastokcol; i>=0; i--)
169
    {
170
        char const * const pal1 = (char *)&colmatch_palette[i*3];
171
        int dist = gdist[pal1[1]+g];
172
 
173
        if (dist >= mindist) continue;
174
        if ((dist += rdist[pal1[0]+r]) >= mindist) continue;
175
        if ((dist += bdist[pal1[2]+b]) >= mindist) continue;
176
 
177
        mindist = dist;
178
        retcol = i;
179
    }
180
 
181
    getclosestcol_results[numclosestcolresults++ & (COLRESULTSIZ-1)] |= retcol<<24;
182
    return retcol;
183
}