/**************************************************************************** * NCSA Mosaic for the X Window System * * Software Development Group * * National Center for Supercomputing Applications * * University of Illinois at Urbana-Champaign * * 605 E. Springfield, Champaign IL 61820 * * mosaic@ncsa.uiuc.edu * * * * Copyright (C) 1993, Board of Trustees of the University of Illinois * * * * NCSA Mosaic software, both binary and source (hereafter, Software) is * * copyrighted by The Board of Trustees of the University of Illinois * * (UI), and ownership remains with the UI. * * * * The UI grants you (hereafter, Licensee) a license to use the Software * * for academic, research and internal business purposes only, without a * * fee. Licensee may distribute the binary and source code (if released) * * to third parties provided that the copyright notice and this statement * * appears on all copies and that no charge is associated with such * * copies. * * * * Licensee may make derivative works. However, if Licensee distributes * * any derivative work based on or derived from the Software, then * * Licensee will (1) notify NCSA regarding its distribution of the * * derivative work, and (2) clearly notify users that such derivative * * work is a modified version and not the original NCSA Mosaic * * distributed by the UI. * * * * Any Licensee wishing to make commercial use of the Software should * * contact the UI, c/o NCSA, to negotiate an appropriate license for such * * commercial use. Commercial use includes (1) integration of all or * * part of the source code into a product for sale or license by or on * * behalf of Licensee to third parties, or (2) distribution of the binary * * code or source code to third parties that need it to utilize a * * commercial product sold or licensed by or on behalf of Licensee. * * * * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR * * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED * * WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE * * USERS OF THIS SOFTWARE. * * * * By using or copying this Software, Licensee agrees to abide by the * * copyright law and all other applicable laws of the U.S. including, but * * not limited to, export control laws, and the terms of this license. * * UI shall have the right to terminate this license immediately by * * written notice upon Licensee's breach of, or non-compliance with, any * * of its terms. Licensee may be held legally responsible for any * * copyright infringement that is caused or encouraged by Licensee's * * failure to abide by the terms of this license. * * * * Comments and questions are welcome and can be sent to * * mosaic-x@ncsa.uiuc.edu. * ****************************************************************************/ #include "../config.h" #include #include #define RED 0 #define GREEN 1 #define BLUE 2 #ifndef DISABLE_TRACE extern int srcTrace; #endif #if 0 #define FindHash(red, green, blue, h_ptr) \ h_ptr = Hash[((red * 299) + (green * 587) + (blue * 114)) / 1000 * NCells / 65536]; \ while(h_ptr != NULL) \ { \ if ((h_ptr->pixel[RED] == red)&& \ (h_ptr->pixel[GREEN] == green)&& \ (h_ptr->pixel[BLUE] == blue)) \ { \ break; \ } \ h_ptr = h_ptr->hash_next; \ } #endif #define FindHash(red, green, blue, h_ptr) \ h_ptr = Hash[((((red * 306) + (green * 601) + (blue * 117)) >> 10) * NCells) >> 16]; \ while(h_ptr != NULL) \ { \ if ((h_ptr->pixel[RED] == red)&& \ (h_ptr->pixel[GREEN] == green)&& \ (h_ptr->pixel[BLUE] == blue)) \ { \ break; \ } \ h_ptr = h_ptr->hash_next; \ } static struct color_rec { int pixel[3]; int box_num; struct color_rec *hash_next; struct color_rec *next; } *Hash[256]; static struct c_box_rec { int min_pix[3]; int max_pix[3]; int count; struct color_rec *c_data; } C_boxes[256]; static int BoxCount; static struct color_rec *hash_ptr; static struct color_rec *free_hash = (struct color_rec *)NULL; static struct color_rec *tptr; static int Width, Height; static int ColorCnt; static int NCells; void InitMinMax(boxnum) int boxnum; { C_boxes[boxnum].min_pix[RED] = 65536; C_boxes[boxnum].max_pix[RED] = 0; C_boxes[boxnum].min_pix[GREEN] = 65536; C_boxes[boxnum].max_pix[GREEN] = 0; C_boxes[boxnum].min_pix[BLUE] = 65536; C_boxes[boxnum].max_pix[BLUE] = 0; } struct color_rec *AddHash(red, green, blue) int red, green, blue; { int lum; #if 0 lum = ((red * 299) + (green * 587) + (blue * 114)) / 1000 * NCells / 65536;; #endif lum = ((((red * 306) + (green * 601) + (blue * 117)) >> 10) * NCells) >> 16;; if (free_hash != NULL) { hash_ptr = free_hash; free_hash = free_hash->hash_next; } else { hash_ptr = (struct color_rec *) XtMalloc(sizeof(struct color_rec)); } if (hash_ptr == NULL) { fprintf(stderr, "Cannot malloc %dth color\n", ColorCnt); exit(1); } hash_ptr->pixel[RED] = red; hash_ptr->pixel[GREEN] = green; hash_ptr->pixel[BLUE] = blue; hash_ptr->box_num = 0; hash_ptr->next = NULL; hash_ptr->hash_next = Hash[lum]; Hash[lum] = hash_ptr; return(hash_ptr); } void AddColor(cptr, boxnum) struct color_rec *cptr; int boxnum; { struct color_rec *ptr; while (cptr != NULL) { ptr = cptr; cptr = cptr->next; ptr->box_num = boxnum; ptr->next = C_boxes[boxnum].c_data; C_boxes[boxnum].c_data = ptr; if (ptr->pixel[RED] < C_boxes[boxnum].min_pix[RED]) C_boxes[boxnum].min_pix[RED] = ptr->pixel[RED]; if (ptr->pixel[RED] > C_boxes[boxnum].max_pix[RED]) C_boxes[boxnum].max_pix[RED] = ptr->pixel[RED]; if (ptr->pixel[GREEN] < C_boxes[boxnum].min_pix[GREEN]) C_boxes[boxnum].min_pix[GREEN] = ptr->pixel[GREEN]; if (ptr->pixel[GREEN] > C_boxes[boxnum].max_pix[GREEN]) C_boxes[boxnum].max_pix[GREEN] = ptr->pixel[GREEN]; if (ptr->pixel[BLUE] < C_boxes[boxnum].min_pix[BLUE]) C_boxes[boxnum].min_pix[BLUE] = ptr->pixel[BLUE]; if (ptr->pixel[BLUE] > C_boxes[boxnum].max_pix[BLUE]) C_boxes[boxnum].max_pix[BLUE] = ptr->pixel[BLUE]; } } void CountColors(data, colrs, color_used) unsigned char *data; XColor *colrs; int *color_used; { unsigned char *dptr; register int i; int red, green, blue; register struct color_rec *tptr; InitMinMax(0); C_boxes[0].c_data = NULL; tptr = C_boxes[0].c_data; ColorCnt = 0; for (i=0; i<256; i++) { color_used[i] = 0; } dptr = data; for (i=(Width * Height); i>0; i--) { color_used[(int)(*dptr)] = 1; dptr++; } for (i=0; i<256; i++) { if (!color_used[i]) { continue; } red = colrs[i].red; green = colrs[i].green; blue = colrs[i].blue; FindHash(red, green, blue, tptr); if (tptr == NULL) { tptr = AddHash(red, green, blue); tptr->next = NULL; AddColor(tptr, 0); ColorCnt++; } } } int FindTarget(tptr) int *tptr; { int range, i, indx; range = 0; for (i=0; i range) { range = rr; *tptr = i; indx = RED; } if (gr > range) { range = gr; *tptr = i; indx = GREEN; } if (br > range) { range = br; *tptr = i; indx = BLUE; } } return(indx); } void SplitBox(boxnum, color_indx) int boxnum, color_indx; { struct color_rec *low, *high; struct color_rec *data; int med_cnt, split_val; int low_cnt, high_cnt; int Low_cnt, High_cnt; int Greater, Lesser; Greater = BoxCount++; Lesser = boxnum; InitMinMax(Lesser); InitMinMax(Greater); data = C_boxes[boxnum].c_data; med_cnt = C_boxes[boxnum].count / 2; C_boxes[Lesser].c_data = NULL; C_boxes[Greater].c_data = NULL; Low_cnt = 0; High_cnt = 0; while(med_cnt > 0) { if (data->pixel[color_indx] < data->next->pixel[color_indx]) { low = data; high = data->next; data = high->next; } else { high = data; low = data->next; data = low->next; } low->next = NULL; high->next = NULL; low_cnt = 1; high_cnt = 1; split_val = low->pixel[color_indx]; while(data != NULL) { tptr = data; data = data->next; if (tptr->pixel[color_indx] > split_val) { tptr->next = high; high = tptr; high_cnt++; } else { tptr->next = low; low = tptr; low_cnt++; } } /* end while data->next != NULL */ if (low_cnt <= med_cnt) { AddColor(low, Lesser); Low_cnt += low_cnt; med_cnt -= low_cnt; if (med_cnt == 0) { AddColor(high, Greater); High_cnt += high_cnt; } data = high; } else { AddColor(high, Greater); High_cnt += high_cnt; data = low; } } /* end while med_cnt */ C_boxes[Lesser].count = Low_cnt; C_boxes[Greater].count = High_cnt; } void SplitColors(e_cnt) int e_cnt; { if (ColorCnt < e_cnt) { int i; tptr = C_boxes[0].c_data; for (i=0; inext; C_boxes[i].c_data = hash_ptr; C_boxes[i].count = 1; hash_ptr->box_num = i; hash_ptr->next = NULL; } BoxCount = ColorCnt; } else { BoxCount = 1; while (BoxCount < e_cnt) { int target, color_indx; target = 0; color_indx = 0; color_indx = FindTarget(&target); SplitBox(target, color_indx); } } } void ConvertData(data, colrs, colors_used) unsigned char *data; XColor *colrs; int *colors_used; { unsigned char *dptr; register int i/*, j*/; int red, green, blue; register struct color_rec *hash_ptr; int pixel_map[256]; /* * Generate translation map. */ for (i=0; i<256; i++) { if (!colors_used[i]) { continue; } red = colrs[i].red; green = colrs[i].green; blue = colrs[i].blue; FindHash(red, green, blue, hash_ptr); if (hash_ptr == NULL) { #ifndef DISABLE_TRACE if (srcTrace) { fprintf(stderr, "Unknown color (%d,%d,%d)\n", red, green, blue); } #endif hash_ptr = Hash[0]; } pixel_map[i] = hash_ptr->box_num; } dptr = data; for (i=(Width*Height); i>0; i--) { *dptr = (unsigned char)pixel_map[(int)*dptr]; dptr++; } } void PrintColormap(e_cnt, colrs) int e_cnt; XColor *colrs; { int i; for(i=0; ipixel[RED]; Tgreen += tptr->pixel[GREEN]; Tblue += tptr->pixel[BLUE]; c_cnt++; tptr = tptr->next; } colrs[i].red = Tred / c_cnt; colrs[i].green = Tgreen / c_cnt; colrs[i].blue = Tblue / c_cnt; } for(i=BoxCount; ihash_next; tptr->hash_next = free_hash; free_hash = tptr; } } }