| 1 | #include "stdlib.h" |
|---|
| 2 | #include "platform.h" |
|---|
| 3 | #include "core.h" |
|---|
| 4 | #include "keyboard.h" |
|---|
| 5 | #include "conf.h" |
|---|
| 6 | #include "math.h" |
|---|
| 7 | #include "ubasic.h" |
|---|
| 8 | #include "gui.h" |
|---|
| 9 | #include "gui_draw.h" |
|---|
| 10 | #include "histogram.h" |
|---|
| 11 | |
|---|
| 12 | #define HISTOGRAM_IDLE_STAGE (6) |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | static float identity(float x); |
|---|
| 16 | static float locarithmic(float x); |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | unsigned char histogram[5][HISTO_WIDTH]; // RGBYG |
|---|
| 20 | long exposition_thresh; |
|---|
| 21 | long under_exposed; |
|---|
| 22 | long over_exposed; |
|---|
| 23 | long histo_magnification; |
|---|
| 24 | |
|---|
| 25 | static unsigned int histogram_proc[5][HISTO_WIDTH]; // RGBYG |
|---|
| 26 | static float histo_max_invw[5], histo_max_center_invw[5]; // RGBYG |
|---|
| 27 | static long histogram_stage=0; |
|---|
| 28 | static unsigned int histo_max[5], histo_max_center[5]; // RGBYG |
|---|
| 29 | static float (*histogram_transform)(float) = identity; |
|---|
| 30 | static int histo_main = HISTO_RGB; |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | float identity(float x) |
|---|
| 34 | { |
|---|
| 35 | return x; |
|---|
| 36 | } |
|---|
| 37 | |
|---|
| 38 | float locarithmic(float x) { |
|---|
| 39 | return log(x); |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | void histogram_set_mode(unsigned int mode) { |
|---|
| 43 | switch (mode) { |
|---|
| 44 | case HISTO_MODE_LOG: |
|---|
| 45 | histogram_transform = locarithmic; |
|---|
| 46 | break; |
|---|
| 47 | case HISTO_MODE_LINEAR: |
|---|
| 48 | default: |
|---|
| 49 | histogram_transform = identity; |
|---|
| 50 | break; |
|---|
| 51 | } |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | void histogram_set_main(unsigned int main) { |
|---|
| 55 | histo_main = main; |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | static int clip(int v) { |
|---|
| 59 | if (v<0) v=0; |
|---|
| 60 | if (v>255) v=255; |
|---|
| 61 | return v; |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | void histogram_process() |
|---|
| 65 | { |
|---|
| 66 | static unsigned char *img; |
|---|
| 67 | int i, hi, c; |
|---|
| 68 | int y, v, u; |
|---|
| 69 | static int viewport_size; |
|---|
| 70 | unsigned int histo_fill[5]; |
|---|
| 71 | |
|---|
| 72 | switch (histogram_stage) { |
|---|
| 73 | case 0: |
|---|
| 74 | img=((mode_get()&MODE_MASK) == MODE_PLAY)?vid_get_viewport_fb_d():((kbd_is_key_pressed(KEY_SHOOT_HALF))?vid_get_viewport_fb():vid_get_viewport_live_fb()); |
|---|
| 75 | |
|---|
| 76 | if (img==NULL){ |
|---|
| 77 | img = vid_get_viewport_fb(); |
|---|
| 78 | } |
|---|
| 79 | viewport_size = vid_get_viewport_height() * vid_get_viewport_width(); |
|---|
| 80 | for (c=0; c<5; ++c) { |
|---|
| 81 | for (i=0; i<HISTO_WIDTH; ++i) { |
|---|
| 82 | histogram_proc[c][i]=0; |
|---|
| 83 | } |
|---|
| 84 | histo_max[c] = histo_max_center[c] = 0; |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | histogram_stage=1; |
|---|
| 88 | break; |
|---|
| 89 | |
|---|
| 90 | case 1: |
|---|
| 91 | case 2: |
|---|
| 92 | case 3: |
|---|
| 93 | for (i=(histogram_stage-1)*6; i<viewport_size*3; i+=6*3*2) { |
|---|
| 94 | y = img[i+1]; |
|---|
| 95 | u = *(signed char*)(&img[i]); |
|---|
| 96 | if (u&0x00000080) u|=0xFFFFFF00; |
|---|
| 97 | v = *(signed char*)(&img[i+2]); |
|---|
| 98 | if (v&0x00000080) v|=0xFFFFFF00; |
|---|
| 99 | |
|---|
| 100 | hi = y*HISTO_WIDTH/256; // Y |
|---|
| 101 | ++histogram_proc[HISTO_Y][hi]; |
|---|
| 102 | hi = clip(((y<<12) + v*5743 + 2048)/4096)*HISTO_WIDTH/256; // R |
|---|
| 103 | ++histogram_proc[HISTO_R][hi]; |
|---|
| 104 | hi = clip(((y<<12) - u*1411 - v*2925 + 2048)/4096)*HISTO_WIDTH/256; // G |
|---|
| 105 | ++histogram_proc[HISTO_G][hi]; |
|---|
| 106 | hi = clip(((y<<12) + u*7258 + 2048)/4096)*HISTO_WIDTH/256; // B |
|---|
| 107 | ++histogram_proc[HISTO_B][hi]; |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | ++histogram_stage; |
|---|
| 111 | break; |
|---|
| 112 | |
|---|
| 113 | case 4: |
|---|
| 114 | for (i=0; i<HISTO_WIDTH; ++i) { // G |
|---|
| 115 | histogram_proc[HISTO_RGB][i]=histogram_proc[HISTO_R][i]+histogram_proc[HISTO_G][i]+histogram_proc[HISTO_B][i]; |
|---|
| 116 | } |
|---|
| 117 | for (c=0; c<5; ++c) { // calculate maximums |
|---|
| 118 | for (i=0; i<HISTO_WIDTH; ++i) { |
|---|
| 119 | if (histo_max[c]<histogram_proc[c][i]) |
|---|
| 120 | histo_max[c]=histogram_proc[c][i]; |
|---|
| 121 | if (histo_max_center[c]<histogram_proc[c][i] && i>=conf.histo_ignore_boundary && i<HISTO_WIDTH-conf.histo_ignore_boundary) |
|---|
| 122 | histo_max_center[c]=histogram_proc[c][i]; |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | if (histo_max[c] > 0) { |
|---|
| 126 | histo_max_invw[c] = ((float)HISTO_HEIGHT)/histogram_transform((float)histo_max[c]); |
|---|
| 127 | } else { |
|---|
| 128 | histo_max_invw[c] = 0.0f; |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | if (histo_max_center[c] > 0) { |
|---|
| 132 | histo_max_center_invw[c] = ((float)HISTO_HEIGHT)/histogram_transform((float)histo_max_center[c]); |
|---|
| 133 | } else { |
|---|
| 134 | histo_max_center_invw[c] = 0.0f; |
|---|
| 135 | } |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | if (histo_max[HISTO_RGB] > 0) { // over- / under- expos |
|---|
| 139 | under_exposed = (histogram_proc[HISTO_RGB][0]*8 |
|---|
| 140 | +histogram_proc[HISTO_RGB][1]*4 |
|---|
| 141 | +histogram_proc[HISTO_RGB][2]) > exposition_thresh; |
|---|
| 142 | |
|---|
| 143 | over_exposed = (histogram_proc[HISTO_RGB][HISTO_WIDTH-3] |
|---|
| 144 | +histogram_proc[HISTO_RGB][HISTO_WIDTH-2]*4 |
|---|
| 145 | +histogram_proc[HISTO_RGB][HISTO_WIDTH-1]*8) > exposition_thresh; |
|---|
| 146 | } else { |
|---|
| 147 | over_exposed = 0; |
|---|
| 148 | under_exposed = 1; |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | histogram_stage=5; |
|---|
| 152 | state_expos_recalculated = 1; |
|---|
| 153 | break; |
|---|
| 154 | |
|---|
| 155 | case 5: |
|---|
| 156 | for (c=0; c<5; ++c) { |
|---|
| 157 | histo_fill[c]=0; |
|---|
| 158 | for (i=0; i<HISTO_WIDTH; ++i) { |
|---|
| 159 | histogram[c][i] = (histogram_transform((float)histogram_proc[c][i]))*histo_max_center_invw[c]; |
|---|
| 160 | if (histogram[c][i] > HISTO_HEIGHT) |
|---|
| 161 | histogram[c][i] = HISTO_HEIGHT; |
|---|
| 162 | histo_fill[c]+=histogram[c][i]; |
|---|
| 163 | } |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | if (conf.histo_auto_ajust) { |
|---|
| 167 | histo_magnification = histo_fill[histo_main]*1000/(HISTO_HEIGHT*HISTO_WIDTH); |
|---|
| 168 | if (histo_magnification<200) { // try to ajust if average level is less than 20% |
|---|
| 169 | histo_magnification=200*1000/histo_magnification; |
|---|
| 170 | for (c=0; c<5; ++c) { |
|---|
| 171 | for (i=0;i<HISTO_WIDTH;i++) { |
|---|
| 172 | histogram[c][i] = (histogram_transform((float)histogram_proc[c][i]))*histo_max_center_invw[c]*histo_magnification/1000; |
|---|
| 173 | if (histogram[c][i] > HISTO_HEIGHT) |
|---|
| 174 | histogram[c][i] = HISTO_HEIGHT; |
|---|
| 175 | } |
|---|
| 176 | } |
|---|
| 177 | } else |
|---|
| 178 | histo_magnification=0; |
|---|
| 179 | } else { |
|---|
| 180 | histo_magnification=0; |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | histogram_stage=0; |
|---|
| 184 | break; |
|---|
| 185 | |
|---|
| 186 | case HISTOGRAM_IDLE_STAGE: |
|---|
| 187 | break; |
|---|
| 188 | } |
|---|
| 189 | |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | void histogram_stop() |
|---|
| 193 | { |
|---|
| 194 | histogram_stage=HISTOGRAM_IDLE_STAGE; |
|---|
| 195 | } |
|---|
| 196 | |
|---|
| 197 | |
|---|
| 198 | void histogram_restart() |
|---|
| 199 | { |
|---|
| 200 | histogram_stage = 0; |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | |
|---|