#include #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Ł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˘n que leer  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˘n que carga y */ /* activa la paleta nueva */ }