[80] | 1 | /********************************************************************** <BR>
|
---|
| 2 | This file is part of Crack dot Com's free source code release of
|
---|
| 3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
| 4 | information about compiling & licensing issues visit this URL</a>
|
---|
| 5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
| 6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
| 7 | ***********************************************************************/
|
---|
| 8 |
|
---|
| 9 | #include "arch.hh"
|
---|
| 10 | #include "quantize/median.hh"
|
---|
| 11 | #include "quantize/histogram.hh"
|
---|
| 12 | #include <stdlib.h>
|
---|
| 13 | #include "memory/malloc.hh"
|
---|
| 14 |
|
---|
| 15 | // counts for each color, global so that it can be accessed by qsort function
|
---|
| 16 | static w32 *counts;
|
---|
| 17 |
|
---|
| 18 |
|
---|
| 19 | static int red_compare(const void *a, const void *b)
|
---|
| 20 | {
|
---|
| 21 | w16 color1=counts[*((w16 *)a)],
|
---|
| 22 | color2=counts[*((w16 *)b)];
|
---|
| 23 |
|
---|
| 24 | return ((sw32) ((color1 & ( (1 | 2 | 4 | 8 | 16) << 11))>>11))-
|
---|
| 25 | ((sw32) ((color2 & ( (1 | 2 | 4 | 8 | 16) << 11))>>11));
|
---|
| 26 | }
|
---|
| 27 |
|
---|
| 28 |
|
---|
| 29 | static int green_compare(const void *a, const void *b)
|
---|
| 30 | {
|
---|
| 31 | w16 color1=counts[*((w16 *)a)],
|
---|
| 32 | color2=counts[*((w16 *)b)];
|
---|
| 33 |
|
---|
| 34 | return ((sw32) (color1 & ( (1 | 2 | 4 | 8 | 16 | 32) << 5)))-
|
---|
| 35 | ((sw32) (color2 & ( (1 | 2 | 4 | 8 | 16 | 32) << 5)));
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 |
|
---|
| 39 | static int blue_compare(const void *a, const void *b)
|
---|
| 40 | {
|
---|
| 41 | w16 color1=counts[*((w16 *)a)],
|
---|
| 42 | color2=counts[*((w16 *)b)];
|
---|
| 43 |
|
---|
| 44 | return ((sw32) (color1 & ( (1 | 2 | 4 | 8 | 16) << 0)))-
|
---|
| 45 | ((sw32) (color2 & ( (1 | 2 | 4 | 8 | 16) << 0)));
|
---|
| 46 | }
|
---|
| 47 |
|
---|
| 48 |
|
---|
| 49 | struct box
|
---|
| 50 | {
|
---|
| 51 | w32 index;
|
---|
| 52 | w32 colors;
|
---|
| 53 | w32 sum;
|
---|
| 54 | };
|
---|
| 55 |
|
---|
| 56 | static int box_compare(const void *a, const void *b)
|
---|
| 57 | {
|
---|
| 58 | return ((box *)b)->sum-((box *)a)->sum;
|
---|
| 59 | }
|
---|
| 60 |
|
---|
| 61 | inline void _16_to_rgb(w32 rgb, w8 &r, w8 &g, w8 &b)
|
---|
| 62 | {
|
---|
| 63 | b=(rgb & (1 | 2 | 4 | 8 | 16))<<3;
|
---|
| 64 | rgb>>=5;
|
---|
| 65 |
|
---|
| 66 | g=(rgb & (1 | 2 | 4 | 8 | 16 | 32))<<2;
|
---|
| 67 | rgb>>=6;
|
---|
| 68 |
|
---|
| 69 | r=(rgb & (1 | 2 | 4 | 8 | 16))<<3;
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | void i4_median_cut(i4_histogram_class *hist,
|
---|
| 73 | w32 skip_colors,
|
---|
| 74 | w32 t_colors,
|
---|
| 75 | w32 *return_palette)
|
---|
| 76 |
|
---|
| 77 | {
|
---|
| 78 | enum { HIST_SIZE=0x10000, // 16 bit histogram table
|
---|
| 79 | MAX_COLORS=256 };
|
---|
| 80 |
|
---|
| 81 | counts=hist->counts;
|
---|
| 82 |
|
---|
| 83 | box *box_list=(box *)i4_malloc(sizeof(box) * MAX_COLORS, "boxes");
|
---|
| 84 |
|
---|
| 85 | // setup the initial box
|
---|
| 86 | w32 total_boxes = 1;
|
---|
| 87 | box_list[0].index = 0;
|
---|
| 88 | box_list[0].colors = hist->tcolors;
|
---|
| 89 | box_list[0].sum = hist->total_pixels;
|
---|
| 90 |
|
---|
| 91 | w32 box_index;
|
---|
| 92 | w32 loop_count;
|
---|
| 93 |
|
---|
| 94 | // split boxes until we have all the colors
|
---|
| 95 | while ( total_boxes < t_colors-skip_colors )
|
---|
| 96 | {
|
---|
| 97 | // Find the first splittable box.
|
---|
| 98 | for ( box_index = 0; box_index < total_boxes; ++box_index )
|
---|
| 99 | if (box_list[box_index].colors >= 2)
|
---|
| 100 | break;
|
---|
| 101 |
|
---|
| 102 | if ( box_index == total_boxes)
|
---|
| 103 | break; /* ran out of colors! */
|
---|
| 104 |
|
---|
| 105 |
|
---|
| 106 | w32 start = box_list[box_index].index;
|
---|
| 107 | w32 end = start + box_list[box_index].colors;
|
---|
| 108 |
|
---|
| 109 | w8 min_r=0xff, max_r=0x00,
|
---|
| 110 | min_g=0xff, max_g=0x00,
|
---|
| 111 | min_b=0xff, max_b=0x00,
|
---|
| 112 | r,g,b;
|
---|
| 113 |
|
---|
| 114 |
|
---|
| 115 | // now find the minimum and maximum r g b values for this box
|
---|
| 116 | for (loop_count = start; loop_count<end; loop_count++)
|
---|
| 117 | {
|
---|
| 118 | _16_to_rgb(hist->reference[loop_count],r,g,b);
|
---|
| 119 |
|
---|
| 120 | if (r>max_r) max_r=r;
|
---|
| 121 | if (r<min_r) min_r=r;
|
---|
| 122 |
|
---|
| 123 | if (g>max_g) max_g=g;
|
---|
| 124 | if (g<min_g) min_g=g;
|
---|
| 125 |
|
---|
| 126 | if (b>max_b) max_b=b;
|
---|
| 127 | if (b<min_b) min_b=b;
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 |
|
---|
| 131 | // Find the largest dimension, and sort by that component.
|
---|
| 132 | if (((max_r - min_r) >= (max_g - min_g)) && ((max_r - min_r) >= (max_b - min_b)))
|
---|
| 133 | qsort(hist->reference + start,
|
---|
| 134 | end-start, // total elements to sort
|
---|
| 135 | sizeof(w16),
|
---|
| 136 | red_compare);
|
---|
| 137 | else if ( (max_g - min_g) >= (max_b - min_b) )
|
---|
| 138 | qsort(hist->reference + start,
|
---|
| 139 | end-start, // total elements to sort
|
---|
| 140 | sizeof(w16),
|
---|
| 141 | green_compare);
|
---|
| 142 | else
|
---|
| 143 | qsort(hist->reference + start,
|
---|
| 144 | end-start, // total elements to sort
|
---|
| 145 | sizeof(w16),
|
---|
| 146 | blue_compare);
|
---|
| 147 |
|
---|
| 148 |
|
---|
| 149 |
|
---|
| 150 | // now find the division which closest divides into an equal number of pixels
|
---|
| 151 | w32 low_count= counts[hist->reference[start]];
|
---|
| 152 | w32 mid_number=box_list[box_index].sum/2;
|
---|
| 153 |
|
---|
| 154 | for (loop_count = start+1; loop_count<end-1 && low_count<mid_number ; loop_count++)
|
---|
| 155 | low_count+=counts[hist->reference[loop_count]];
|
---|
| 156 |
|
---|
| 157 |
|
---|
| 158 | // now split the box
|
---|
| 159 | box_list[total_boxes].index = loop_count;
|
---|
| 160 | box_list[total_boxes].colors = end-loop_count;
|
---|
| 161 | box_list[total_boxes].sum = box_list[box_index].sum-low_count;
|
---|
| 162 | total_boxes++;
|
---|
| 163 |
|
---|
| 164 | box_list[box_index].colors= loop_count-start;
|
---|
| 165 | box_list[box_index].sum = low_count;
|
---|
| 166 |
|
---|
| 167 | // sort to bring the biggest boxes to the top
|
---|
| 168 | qsort(box_list, total_boxes, sizeof(box), box_compare );
|
---|
| 169 |
|
---|
| 170 | /* for (int z=0;z<total_boxes;z++)
|
---|
| 171 | {
|
---|
| 172 | printf("box #%d : index = %d, colors= %d, sum=%d\n",z,
|
---|
| 173 | box_list[z].index, box_list[z].colors, box_list[z].sum);
|
---|
| 174 | } */
|
---|
| 175 |
|
---|
| 176 | }
|
---|
| 177 |
|
---|
| 178 |
|
---|
| 179 | // we should have 256 boxes, we now need to choose a color for each box
|
---|
| 180 | // we do this by averaging all the colors within the box
|
---|
| 181 | w32 r_tot, g_tot, b_tot;
|
---|
| 182 | for (box_index = 0; box_index<total_boxes-skip_colors; box_index++)
|
---|
| 183 | {
|
---|
| 184 | r_tot = g_tot = b_tot = 0;
|
---|
| 185 |
|
---|
| 186 | w32 start = box_list[box_index].index;
|
---|
| 187 | w32 end = start + box_list[box_index].colors;
|
---|
| 188 |
|
---|
| 189 | w8 r,g,b;
|
---|
| 190 | for (loop_count = start; loop_count < end; loop_count++)
|
---|
| 191 | {
|
---|
| 192 | _16_to_rgb(hist->reference[loop_count],r,g,b);
|
---|
| 193 |
|
---|
| 194 | r_tot+=r;
|
---|
| 195 | g_tot+=g;
|
---|
| 196 | b_tot+=b;
|
---|
| 197 | }
|
---|
| 198 |
|
---|
| 199 | r_tot/=(end-start);
|
---|
| 200 | g_tot/=(end-start);
|
---|
| 201 | b_tot/=(end-start);
|
---|
| 202 |
|
---|
| 203 | return_palette[box_index+skip_colors] = (r_tot<<16)|
|
---|
| 204 | (g_tot<<8) |
|
---|
| 205 | b_tot;
|
---|
| 206 | }
|
---|
| 207 |
|
---|
| 208 | for (;box_index + skip_colors<t_colors; box_index++)
|
---|
| 209 | return_palette[box_index+skip_colors] = 0;
|
---|
| 210 |
|
---|
| 211 |
|
---|
| 212 | i4_free(box_list);
|
---|
| 213 |
|
---|
| 214 | }
|
---|
| 215 |
|
---|