Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F90716337
colortab.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Nov 4, 03:14
Size
6 KB
Mime Type
text/x-c
Expires
Wed, Nov 6, 03:14 (2 d)
Engine
blob
Format
Raw Data
Handle
22124108
Attached To
R10977 RADIANCE Photon Map
colortab.c
View Options
#ifndef lint
static
const
char
RCSid
[]
=
"$Id: colortab.c,v 2.12 2016/03/18 22:52:05 schorsch Exp $"
;
#endif
/*
* colortab.c - allocate and control dynamic color table.
*
* We start off with a uniform partition of color space.
* As pixels are sent to the frame buffer, a histogram is built.
* When a new color table is requested, the histogram is used
* to make a pseudo-optimal partition, after which the
* histogram is cleared. This algorithm
* performs only as well as the next drawing's color
* distribution is correlated to the last.
*
* External symbols declared in drvier.h
*/
#include "copyright.h"
#include <string.h>
#include "standard.h"
#include "color.h"
#include "driver.h"
/* histogram resolution */
#define NRED 24
#define NGRN 32
#define NBLU 16
#define HMAX NGRN
/* minimum box count for adaptive partition */
#define MINSAMP 7
/* maximum distance^2 before color reassign */
#define MAXDST2 12
/* map a color */
#define map_col(c,p) clrmap[p][ colval(c,p)<1. ? \
(int)(colval(c,p)*256.) : 255 ]
/* color partition tree */
#define CNODE short
#define set_branch(p,c) ((c)<<2|(p))
#define set_pval(pv) ((pv)<<2|3)
#define is_branch(cn) (((cn)&3)!=3)
#define is_pval(cn) (((cn)&3)==3)
#define part(cn) ((cn)>>2)
#define prim(cn) ((cn)&3)
#define pval(cn) ((cn)>>2)
/* our color table */
static
struct
tabent
{
long
sum
[
3
];
/* sum of colors using this entry */
int
n
;
/* number of colors */
uby8
ent
[
3
];
/* current table value */
}
*
clrtab
=
NULL
;
/* color cube partition */
static
CNODE
*
ctree
=
NULL
;
/* our color correction map */
static
uby8
clrmap
[
3
][
256
];
/* histogram of colors used */
static
unsigned
short
histo
[
NRED
][
NGRN
][
NBLU
];
/* initial color cube boundary */
static
int
CLRCUBE
[
3
][
2
]
=
{{
0
,
NRED
},{
0
,
NGRN
},{
0
,
NBLU
}};
static
int
split
();
static
void
cut
();
int
new_ctab
(
ncolors
)
/* start new color table with max ncolors */
int
ncolors
;
{
int
treesize
;
if
(
ncolors
<
1
)
return
(
0
);
/* free old tables */
if
(
clrtab
!=
NULL
)
free
((
void
*
)
clrtab
);
if
(
ctree
!=
NULL
)
free
((
void
*
)
ctree
);
/* get new tables */
for
(
treesize
=
1
;
treesize
<
ncolors
;
treesize
<<=
1
)
;
treesize
<<=
1
;
clrtab
=
(
struct
tabent
*
)
calloc
(
ncolors
,
sizeof
(
struct
tabent
));
ctree
=
(
CNODE
*
)
malloc
(
treesize
*
sizeof
(
CNODE
));
if
(
clrtab
==
NULL
||
ctree
==
NULL
)
return
(
0
);
/* partition color space */
cut
(
ctree
,
0
,
CLRCUBE
,
0
,
ncolors
);
/* clear histogram */
memset
((
void
*
)
histo
,
'\0'
,
sizeof
(
histo
));
/* return number of colors used */
return
(
ncolors
);
}
int
get_pixel
(
/* get pixel for color */
COLOR
col
,
dr_newcolrf_t
*
newcolr
)
{
int
r
,
g
,
b
;
int
cv
[
3
];
CNODE
*
tp
;
int
h
;
/* map color */
r
=
map_col
(
col
,
RED
);
g
=
map_col
(
col
,
GRN
);
b
=
map_col
(
col
,
BLU
);
/* reduce resolution */
cv
[
RED
]
=
(
r
*
NRED
)
>>
8
;
cv
[
GRN
]
=
(
g
*
NGRN
)
>>
8
;
cv
[
BLU
]
=
(
b
*
NBLU
)
>>
8
;
/* add to histogram */
histo
[
cv
[
RED
]][
cv
[
GRN
]][
cv
[
BLU
]]
++
;
/* find pixel in tree */
for
(
tp
=
ctree
,
h
=
0
;
is_branch
(
*
tp
);
h
++
)
if
(
cv
[
prim
(
*
tp
)]
<
part
(
*
tp
))
tp
+=
(
size_t
)
1
<<
h
;
/* left branch */
else
tp
+=
(
size_t
)
1
<<
(
h
+
1
);
/* right branch */
h
=
pval
(
*
tp
);
/* add to color table */
clrtab
[
h
].
sum
[
RED
]
+=
r
;
clrtab
[
h
].
sum
[
GRN
]
+=
g
;
clrtab
[
h
].
sum
[
BLU
]
+=
b
;
clrtab
[
h
].
n
++
;
/* recompute average */
r
=
clrtab
[
h
].
sum
[
RED
]
/
clrtab
[
h
].
n
;
g
=
clrtab
[
h
].
sum
[
GRN
]
/
clrtab
[
h
].
n
;
b
=
clrtab
[
h
].
sum
[
BLU
]
/
clrtab
[
h
].
n
;
/* check for movement */
if
(
clrtab
[
h
].
n
==
1
||
(
r
-
clrtab
[
h
].
ent
[
RED
])
*
(
r
-
clrtab
[
h
].
ent
[
RED
])
+
(
g
-
clrtab
[
h
].
ent
[
GRN
])
*
(
g
-
clrtab
[
h
].
ent
[
GRN
])
+
(
b
-
clrtab
[
h
].
ent
[
BLU
])
*
(
b
-
clrtab
[
h
].
ent
[
BLU
])
>
MAXDST2
)
{
clrtab
[
h
].
ent
[
RED
]
=
r
;
clrtab
[
h
].
ent
[
GRN
]
=
g
;
/* reassign pixel */
clrtab
[
h
].
ent
[
BLU
]
=
b
;
#ifdef DEBUG
sprintf
(
errmsg
,
"pixel %d = (%d,%d,%d) (%d refs)
\n
"
,
h
,
r
,
g
,
b
,
clrtab
[
h
].
n
);
eputs
(
errmsg
);
#endif
(
*
newcolr
)(
h
,
r
,
g
,
b
);
}
return
(
h
);
/* return pixel value */
}
void
make_gmap
(
gam
)
/* make gamma correction map */
double
gam
;
{
int
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
clrmap
[
RED
][
i
]
=
clrmap
[
GRN
][
i
]
=
clrmap
[
BLU
][
i
]
=
256.0
*
pow
((
i
+
0.5
)
/
256.0
,
1.0
/
gam
);
}
void
set_cmap
(
rmap
,
gmap
,
bmap
)
/* set custom color correction map */
uby8
*
rmap
,
*
gmap
,
*
bmap
;
{
memcpy
((
void
*
)
clrmap
[
RED
],
(
void
*
)
rmap
,
256
);
memcpy
((
void
*
)
clrmap
[
GRN
],
(
void
*
)
gmap
,
256
);
memcpy
((
void
*
)
clrmap
[
BLU
],
(
void
*
)
bmap
,
256
);
}
void
map_color
(
rgb
,
col
)
/* map a color to a byte triplet */
uby8
rgb
[
3
];
COLOR
col
;
{
rgb
[
RED
]
=
map_col
(
col
,
RED
);
rgb
[
GRN
]
=
map_col
(
col
,
GRN
);
rgb
[
BLU
]
=
map_col
(
col
,
BLU
);
}
static
void
cut
(
tree
,
level
,
box
,
c0
,
c1
)
/* partition color space */
CNODE
*
tree
;
int
level
;
int
box
[
3
][
2
];
int
c0
,
c1
;
{
int
kb
[
3
][
2
];
if
(
c1
-
c0
<=
1
)
{
/* assign pixel */
*
tree
=
set_pval
(
c0
);
return
;
}
/* split box */
*
tree
=
split
(
box
);
memcpy
((
void
*
)
kb
,
(
void
*
)
box
,
sizeof
(
kb
));
/* do left (lesser) branch */
kb
[
prim
(
*
tree
)][
1
]
=
part
(
*
tree
);
cut
(
tree
+
((
size_t
)
1
<<
level
),
level
+
1
,
kb
,
c0
,
(
c0
+
c1
)
>>
1
);
/* do right branch */
kb
[
prim
(
*
tree
)][
0
]
=
part
(
*
tree
);
kb
[
prim
(
*
tree
)][
1
]
=
box
[
prim
(
*
tree
)][
1
];
cut
(
tree
+
((
size_t
)
1
<<
(
level
+
1
)),
level
+
1
,
kb
,
(
c0
+
c1
)
>>
1
,
c1
);
}
static
int
split
(
box
)
/* find median cut for box */
int
box
[
3
][
2
];
{
#define c0 r
int
r
,
g
,
b
;
int
pri
;
long
t
[
HMAX
],
med
;
/* find dominant axis */
pri
=
RED
;
if
(
box
[
GRN
][
1
]
-
box
[
GRN
][
0
]
>
box
[
pri
][
1
]
-
box
[
pri
][
0
])
pri
=
GRN
;
if
(
box
[
BLU
][
1
]
-
box
[
BLU
][
0
]
>
box
[
pri
][
1
]
-
box
[
pri
][
0
])
pri
=
BLU
;
/* sum histogram over box */
med
=
0
;
switch
(
pri
)
{
case
RED
:
for
(
r
=
box
[
RED
][
0
];
r
<
box
[
RED
][
1
];
r
++
)
{
t
[
r
]
=
0
;
for
(
g
=
box
[
GRN
][
0
];
g
<
box
[
GRN
][
1
];
g
++
)
for
(
b
=
box
[
BLU
][
0
];
b
<
box
[
BLU
][
1
];
b
++
)
t
[
r
]
+=
histo
[
r
][
g
][
b
];
med
+=
t
[
r
];
}
break
;
case
GRN
:
for
(
g
=
box
[
GRN
][
0
];
g
<
box
[
GRN
][
1
];
g
++
)
{
t
[
g
]
=
0
;
for
(
b
=
box
[
BLU
][
0
];
b
<
box
[
BLU
][
1
];
b
++
)
for
(
r
=
box
[
RED
][
0
];
r
<
box
[
RED
][
1
];
r
++
)
t
[
g
]
+=
histo
[
r
][
g
][
b
];
med
+=
t
[
g
];
}
break
;
case
BLU
:
for
(
b
=
box
[
BLU
][
0
];
b
<
box
[
BLU
][
1
];
b
++
)
{
t
[
b
]
=
0
;
for
(
r
=
box
[
RED
][
0
];
r
<
box
[
RED
][
1
];
r
++
)
for
(
g
=
box
[
GRN
][
0
];
g
<
box
[
GRN
][
1
];
g
++
)
t
[
b
]
+=
histo
[
r
][
g
][
b
];
med
+=
t
[
b
];
}
break
;
}
if
(
med
<
MINSAMP
)
/* if too sparse, split at midpoint */
return
(
set_branch
(
pri
,(
box
[
pri
][
0
]
+
box
[
pri
][
1
])
>>
1
));
/* find median position */
med
>>=
1
;
for
(
c0
=
box
[
pri
][
0
];
med
>
0
;
c0
++
)
med
-=
t
[
c0
];
if
(
c0
>
(
box
[
pri
][
0
]
+
box
[
pri
][
1
])
>>
1
)
/* if past the midpoint */
c0
--
;
/* part left of median */
return
(
set_branch
(
pri
,
c0
));
#undef c0
}
Event Timeline
Log In to Comment