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