First commit 16/09/1994
This commit is contained in:
181
BGI/OCTREE.C
Normal file
181
BGI/OCTREE.C
Normal file
@ -0,0 +1,181 @@
|
||||
#include <string.h>
|
||||
#include "alloc.h"
|
||||
#include "dos.h"
|
||||
#include "quant.h"
|
||||
#include "octree.h"
|
||||
|
||||
#define TESTBIT(a,i) ( ((a) >> (i)) & 1)
|
||||
#define MAXDEPTH 8
|
||||
#define BYTE unsigned char
|
||||
|
||||
UCHAR palette [MAXCOLORS][3];
|
||||
|
||||
static UINT size;
|
||||
static UINT reducelevel;
|
||||
static UINT leaflevel;
|
||||
static OCTREE tree;
|
||||
static BYTE rgb_mio[3];
|
||||
static OCTREE reducelist[MAXDEPTH + 1];
|
||||
|
||||
static unsigned char quant_r,
|
||||
quant_g,
|
||||
quant_b;
|
||||
|
||||
/* Quantiza seg<65>n TESTBIT, pero solamente de retorno */
|
||||
|
||||
static char quant2(OCTREE tree)
|
||||
{
|
||||
if (tree->leaf) return(tree->colorindex);
|
||||
else return(quant2(tree->next[
|
||||
TESTBIT(quant_r, MAXDEPTH - tree->level) * 4 +
|
||||
TESTBIT(quant_g, MAXDEPTH - tree->level) * 2 +
|
||||
TESTBIT(quant_b, MAXDEPTH - tree->level)]));
|
||||
}
|
||||
|
||||
/* devuelve el indice a la paleta quantizada de acuerdo con RGB apuntado */
|
||||
|
||||
int pal_index(UCHAR *p)
|
||||
{
|
||||
quant_r = p[RED];
|
||||
quant_g = p[GREEN];
|
||||
quant_b = p[BLUE];
|
||||
return quant2(tree);
|
||||
}
|
||||
|
||||
static double init_Cfactor;
|
||||
static UINT init_col_num;
|
||||
|
||||
static void initpalette(OCTREE tree)
|
||||
{
|
||||
UINT j;
|
||||
|
||||
if (tree == NULL) return;
|
||||
if (tree->leaf || tree->level == leaflevel) {
|
||||
palette[init_col_num][RED] = (char) ((init_Cfactor * tree->rgbsum.r) / tree->colorcount + .5);
|
||||
palette[init_col_num][GREEN] = (char) ((init_Cfactor * tree->rgbsum.g) / tree->colorcount + .5);
|
||||
palette[init_col_num][BLUE] = (char) ((init_Cfactor * tree->rgbsum.b) / tree->colorcount + .5);
|
||||
tree->colorindex = init_col_num;
|
||||
tree->leaf = TRUE;
|
||||
init_col_num++;
|
||||
} else {
|
||||
for (j = 0; j < 8; j++)
|
||||
initpalette(tree->next[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* calcula la paleta de acuerdo con un factor introducido */
|
||||
|
||||
UINT calc_palette(UINT i, double Cfactor)
|
||||
{
|
||||
init_Cfactor = Cfactor;
|
||||
init_col_num = i;
|
||||
initpalette(tree);
|
||||
return init_col_num;
|
||||
}
|
||||
|
||||
|
||||
static void newandinit(OCTREE *tree, UINT depth)
|
||||
{
|
||||
unsigned long rest;
|
||||
*tree = (OCTREE)calloc(1,sizeof(struct node));
|
||||
if (*tree == NULL) {
|
||||
rest=coreleft();
|
||||
printf("No hay bastante Memoria");
|
||||
exit(1);
|
||||
}
|
||||
(*tree)->level = depth;
|
||||
(*tree)->leaf = (depth >= leaflevel);
|
||||
if ((*tree)->leaf)
|
||||
size++;
|
||||
}
|
||||
|
||||
static void getreduceable(OCTREE *node)
|
||||
{
|
||||
UINT newreducelevel;
|
||||
|
||||
newreducelevel = reducelevel;
|
||||
while (reducelist[newreducelevel] == NULL)
|
||||
newreducelevel--;
|
||||
*node = reducelist[newreducelevel];
|
||||
reducelist[newreducelevel] =
|
||||
reducelist[newreducelevel]->nextreduceable;
|
||||
}
|
||||
|
||||
static void makereduceable(UINT level,OCTREE node)
|
||||
{
|
||||
node->nextreduceable = reducelist[level];
|
||||
reducelist[level] = node;
|
||||
}
|
||||
|
||||
/* reduzcamos el arbol, pues K+1>size */
|
||||
|
||||
static void reducetree(void)
|
||||
{
|
||||
OCTREE node;
|
||||
UINT depth;
|
||||
|
||||
getreduceable(&node);
|
||||
node->leaf = 1;
|
||||
size = size - node->children + 1;
|
||||
depth = node->level;
|
||||
if (depth < reducelevel) {
|
||||
reducelevel = depth;
|
||||
leaflevel = reducelevel + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static UCHAR insert_rgb[3];
|
||||
|
||||
/* para insertar cada color dentro del arbol */
|
||||
|
||||
static void inserttree(OCTREE *tree, UINT depth)
|
||||
{
|
||||
UINT branch;
|
||||
|
||||
if (*tree == NULL)
|
||||
newandinit(tree,depth);
|
||||
(*tree)->colorcount++;
|
||||
(*tree)->rgbsum.r += insert_rgb[RED];
|
||||
(*tree)->rgbsum.g += insert_rgb[GREEN];
|
||||
(*tree)->rgbsum.b += insert_rgb[BLUE];
|
||||
if ((*tree)->leaf == FALSE && depth < leaflevel) {
|
||||
branch = TESTBIT(insert_rgb[RED],MAXDEPTH - depth) * 4 +
|
||||
TESTBIT(insert_rgb[GREEN],MAXDEPTH - depth) * 2 +
|
||||
TESTBIT(insert_rgb[BLUE],MAXDEPTH - depth);
|
||||
if ((*tree)->next[branch] == NULL) {
|
||||
(*tree)->children++;
|
||||
if ((*tree)->children == 2)
|
||||
makereduceable(depth,*tree);
|
||||
}
|
||||
inserttree(&((*tree)->next[branch]), depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void lee(FILE *uno,double gamm) /* funci<63>n que leer<65> la 1<> vez el TGA */
|
||||
{
|
||||
union REGS regset;
|
||||
struct SREGS sregset;
|
||||
|
||||
reducelevel = MAXDEPTH;
|
||||
leaflevel = reducelevel + 1;
|
||||
|
||||
while (!feof(uno)) {
|
||||
fread(&rgb_mio,3,1,uno);
|
||||
insert_rgb[0]=rgb_mio[2]; // CUIDADO, valores de TGA tipo 2
|
||||
insert_rgb[1]=rgb_mio[1]; // Estan BGR no RGB
|
||||
insert_rgb[2]=rgb_mio[0];
|
||||
inserttree(&tree, 0);
|
||||
if (size > MAXCOLORS - 1) /* > K+1? (colores) */
|
||||
reducetree();
|
||||
}
|
||||
calc_palette((unsigned int)0,gamm);
|
||||
regset.x.ax=0x1012;
|
||||
regset.x.bx=0;
|
||||
regset.x.cx=256;
|
||||
regset.x.dx=FP_OFF(palette);
|
||||
sregset.es=FP_SEG(palette);
|
||||
int86x(0x10,®set,®set,&sregset); /* interrupci<63>n que carga y */
|
||||
/* activa la paleta nueva */
|
||||
}
|
||||
|
Reference in New Issue
Block a user