Ejemplo n.º 1
0
void histogram_process()
{
    static unsigned char *img;
    static int viewport_size, viewport_width, viewport_row_offset;

    register int x, i, hi;
    int y, v, u, c;
    float (*histogram_transform)(float);
    unsigned int histo_fill[5];
    int histo_main;

    long exposition_thresh = camera_screen.size / 500;

    // Select transform function
    switch (conf.histo_mode)
    {
        case HISTO_MODE_LOG: 
            histogram_transform = logarithmic; 
            break;
        case HISTO_MODE_LINEAR: 
        default:
            histogram_transform = identity; 
            break;
    }

    // Select which calculated histogram channel determines magnification / scaling
    if (conf.histo_layout == OSD_HISTO_LAYOUT_Y || conf.histo_layout == OSD_HISTO_LAYOUT_Y_argb)
        histo_main = HISTO_Y;
    else
        histo_main = HISTO_RGB;

    histogram_alloc();

    // This function is called in the main spytask loop roughly every 20msec
    // To avoid hogging all the CPU it performs it's work in stages controlled by histogram-stage
    // Stage  Function
    //   0      Initialize global variables used in next stages
    //   1,2,3  Count number of values for a third of the viewport image at each stage
    //   4      Calculate max values, over and under exposure setting
    //   5      Calculate the histogram display values
    switch (histogram_stage)
    {
        case 0:
            img=vid_get_viewport_active_buffer();
            if (!img) return;

            img += vid_get_viewport_image_offset();		// offset into viewport for when image size != viewport size (e.g. 16:9 image on 4:3 LCD)
            viewport_size = vid_get_viewport_height() * vid_get_viewport_byte_width() * vid_get_viewport_yscale();
            viewport_width = vid_get_viewport_width();
            viewport_row_offset = vid_get_viewport_row_offset();
            for (c=0; c<5; ++c) {
                memset(histogram_proc[c],0,256*sizeof(unsigned short));
                histo_max[c] = histo_max_center[c] = 0;
            }

            histogram_stage=1;
            break;

        case 1:
        case 2:
        case 3:
            x = 0;  // count how many blocks we have done on the current row (to skip unused buffer space at end of each row)
            for (i=(histogram_stage-1)*6; i<viewport_size; i+=HISTO_STEP_SIZE*6) {
                y = img[i+1];
                u = *(signed char*)(&img[i]);
                //if (u&0x00000080) u|=0xFFFFFF00;  // Compiler should handle the unsigned -> signed conversion
                v = *(signed char*)(&img[i+2]);
                //if (v&0x00000080) v|=0xFFFFFF00;  // Compiler should handle the unsigned -> signed conversion

                ++histogram_proc[HISTO_Y][y];                       // Y
                hi = clip(((y<<12)          + v*5743 + 2048)>>12);  // R
                ++histogram_proc[HISTO_R][hi];
                hi = clip(((y<<12) - u*1411 - v*2925 + 2048)>>12);  // G
                ++histogram_proc[HISTO_G][hi];
                hi = clip(((y<<12) + u*7258          + 2048)>>12);  // B
                ++histogram_proc[HISTO_B][hi];

                // Handle case where viewport memory buffer is wider than the actual buffer.
                x += HISTO_STEP_SIZE * 2;	// viewport width is measured in blocks of three bytes each even though the data is stored in six byte chunks !
                if (x == viewport_width)
                {
                    i += viewport_row_offset;
                    x = 0;
                }
            }

            ++histogram_stage;
            break;

        case 4:
            for (i=0, c=0; i<HISTO_WIDTH; ++i, c+=2) { // G
                // Merge each pair of values into a single value (for width = 128)
                // Warning: this is optimised for HISTO_WIDTH = 128, don't change the width unless you re-write this code as well.
                histogram_proc[HISTO_Y][i] = histogram_proc[HISTO_Y][c] + histogram_proc[HISTO_Y][c+1];
                histogram_proc[HISTO_R][i] = histogram_proc[HISTO_R][c] + histogram_proc[HISTO_R][c+1];
                histogram_proc[HISTO_G][i] = histogram_proc[HISTO_G][c] + histogram_proc[HISTO_G][c+1];
                histogram_proc[HISTO_B][i] = histogram_proc[HISTO_B][c] + histogram_proc[HISTO_B][c+1];
                // Calc combined RGB totals
                histogram_proc[HISTO_RGB][i] = histogram_proc[HISTO_R][i] + histogram_proc[HISTO_G][i] + histogram_proc[HISTO_B][i];
            }

            // calculate maximums
            for (c=0; c<5; ++c) {
                for (i=0; i<HISTO_WIDTH; ++i) {
                    if (histo_max[c]<histogram_proc[c][i])
                        histo_max[c]=histogram_proc[c][i];
                    if (histo_max_center[c]<histogram_proc[c][i] && i>=conf.histo_ignore_boundary && i<HISTO_WIDTH-conf.histo_ignore_boundary)
                        histo_max_center[c]=histogram_proc[c][i];
                }

                if (histo_max_center[c] > 0) {
                    histo_max_center_invw[c] = ((float)HISTO_HEIGHT)/histogram_transform((float)histo_max_center[c]);
                } else if (histo_max[c] > 0) {
                    histo_max_center_invw[c] = ((float)HISTO_HEIGHT)/histogram_transform((float)histo_max[c]);
                } else {
                    histo_max_center_invw[c] = 0.0f;
                }
            }

            if (histo_max[HISTO_RGB] > 0) { // over- / under- expos
                under_exposed = (histogram_proc[HISTO_RGB][0]*8
                                +histogram_proc[HISTO_RGB][1]*4
                                +histogram_proc[HISTO_RGB][2]) > exposition_thresh;

                over_exposed  = (histogram_proc[HISTO_RGB][HISTO_WIDTH-3]
                                +histogram_proc[HISTO_RGB][HISTO_WIDTH-2]*4
                                +histogram_proc[HISTO_RGB][HISTO_WIDTH-1]*8) > exposition_thresh;
            } else {
                over_exposed = 0;
                under_exposed = 1;
            }

            histogram_stage=5;
            break;

        case 5:
            for (c=0; c<5; ++c) {
                histo_fill[c]=0;
                for (i=0; i<HISTO_WIDTH; ++i) {
                    histogram[c][i] = (histogram_transform((float)histogram_proc[c][i]))*histo_max_center_invw[c];
                    if (histogram[c][i] > HISTO_HEIGHT)
                        histogram[c][i] = HISTO_HEIGHT;
                    histo_fill[c]+=histogram[c][i];
                }
            }

            histo_magnification = 0;
            if (conf.histo_auto_ajust) {
                if (histo_fill[histo_main] < (HISTO_HEIGHT*HISTO_WIDTH)/5) { // try to ajust if average level is less than 20%
                    histo_magnification = (20*HISTO_HEIGHT*HISTO_WIDTH) / histo_fill[histo_main];
                    for (c=0; c<5; ++c) {
                        for (i=0;i<HISTO_WIDTH;i++) {
                            histogram[c][i] = histogram[c][i] * histo_magnification / 100;
                            if (histogram[c][i] > HISTO_HEIGHT)
                                histogram[c][i] = HISTO_HEIGHT;
                        }
                    }
                }
            }

            histogram_stage=0;
            break;
    }

}
Ejemplo n.º 2
0
void histogram_process()
{
    static unsigned char *img;
    int i, hi, c;
    int y, v, u;
	static int x;
    static int viewport_size;
    unsigned int histo_fill[5];

	    switch (histogram_stage) {
        case 0:
            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());
      	
        	if (img==NULL){
	    	  img = vid_get_viewport_fb();
		    }
			img += vid_get_viewport_image_offset();		// offset into viewport for when image size != viewport size (e.g. 16:9 image on 4:3 LCD)
            viewport_size = vid_get_viewport_height() * vid_get_viewport_buffer_width();
            for (c=0; c<5; ++c) {
                for (i=0; i<HISTO_WIDTH; ++i) {
                    histogram_proc[c][i]=0;
                }
                histo_max[c] = histo_max_center[c] = 0;
            }

            histogram_stage=1;
            break;
        
        case 1:
        case 2:
        case 3:
			x = 0;	// count how many blocks we have done on the current row (to skip unused buffer space at end of each row)
            for (i=(histogram_stage-1)*6; i<viewport_size*3; i+=HISTO_STEP_SIZE*6) {
                y = img[i+1];
                u = *(signed char*)(&img[i]);
                if (u&0x00000080) u|=0xFFFFFF00;
                v = *(signed char*)(&img[i+2]);
                if (v&0x00000080) v|=0xFFFFFF00;

                hi = y*HISTO_WIDTH/256; // Y
                ++histogram_proc[HISTO_Y][hi];
                hi = clip(((y<<12)          + v*5743 + 2048)/4096)*HISTO_WIDTH/256; // R
                ++histogram_proc[HISTO_R][hi];
                hi = clip(((y<<12) - u*1411 - v*2925 + 2048)/4096)*HISTO_WIDTH/256; // G
                ++histogram_proc[HISTO_G][hi];
                hi = clip(((y<<12) + u*7258          + 2048)/4096)*HISTO_WIDTH/256; // B
                ++histogram_proc[HISTO_B][hi];

				// Handle case where viewport memory buffer is wider than the actual buffer.
				x += HISTO_STEP_SIZE * 2;	// viewport width is measured in blocks of three bytes each even though the data is stored in six byte chunks !
				if (x == vid_get_viewport_width())
				{
					i += vid_get_viewport_row_offset();
					x = 0;
				}
			}

            ++histogram_stage;
            break;

        case 4:
            for (i=0; i<HISTO_WIDTH; ++i) { // G
                histogram_proc[HISTO_RGB][i]=histogram_proc[HISTO_R][i]+histogram_proc[HISTO_G][i]+histogram_proc[HISTO_B][i];
            }
            for (c=0; c<5; ++c) { // calculate maximums
                for (i=0; i<HISTO_WIDTH; ++i) {
                    if (histo_max[c]<histogram_proc[c][i])
                        histo_max[c]=histogram_proc[c][i];
                    if (histo_max_center[c]<histogram_proc[c][i] && i>=conf.histo_ignore_boundary && i<HISTO_WIDTH-conf.histo_ignore_boundary)
                        histo_max_center[c]=histogram_proc[c][i];
                }
                
                if (histo_max[c] > 0) {
                    histo_max_invw[c] = ((float)HISTO_HEIGHT)/histogram_transform((float)histo_max[c]);
                } else {
                    histo_max_invw[c] = 0.0f;
                }

                if (histo_max_center[c] > 0) {
                    histo_max_center_invw[c] = ((float)HISTO_HEIGHT)/histogram_transform((float)histo_max_center[c]);
                } else {
                    histo_max_center_invw[c] = 0.0f;
                }
            }

            if (histo_max[HISTO_RGB] > 0) { // over- / under- expos
                under_exposed = (histogram_proc[HISTO_RGB][0]*8
                                +histogram_proc[HISTO_RGB][1]*4
                                +histogram_proc[HISTO_RGB][2]) > exposition_thresh;

                over_exposed = (histogram_proc[HISTO_RGB][HISTO_WIDTH-3]
                               +histogram_proc[HISTO_RGB][HISTO_WIDTH-2]*4
                               +histogram_proc[HISTO_RGB][HISTO_WIDTH-1]*8) > exposition_thresh;
            } else {
                over_exposed = 0;
                under_exposed = 1;
            }

            histogram_stage=5;
            state_expos_recalculated = 1;
            break;

        case 5:
            for (c=0; c<5; ++c) {
                histo_fill[c]=0;
                for (i=0; i<HISTO_WIDTH; ++i) {
                    histogram[c][i] = (histogram_transform((float)histogram_proc[c][i]))*histo_max_center_invw[c];
                    if (histogram[c][i] > HISTO_HEIGHT)
                        histogram[c][i] = HISTO_HEIGHT;
                    histo_fill[c]+=histogram[c][i];
                }
            }

            if (conf.histo_auto_ajust) {
                histo_magnification = histo_fill[histo_main]*1000/(HISTO_HEIGHT*HISTO_WIDTH);
                if (histo_magnification<200) { // try to ajust if average level is less than 20%
                    histo_magnification=200*1000/histo_magnification;
                    for (c=0; c<5; ++c) {
                        for (i=0;i<HISTO_WIDTH;i++) {
                            histogram[c][i] = (histogram_transform((float)histogram_proc[c][i]))*histo_max_center_invw[c]*histo_magnification/1000;
                            if (histogram[c][i] > HISTO_HEIGHT)
                                histogram[c][i] = HISTO_HEIGHT;
                        }
                    }
                } else 
                    histo_magnification=0;
            } else {
                histo_magnification=0;
            }

            histogram_stage=0;
            break;

        case HISTOGRAM_IDLE_STAGE:
            break;
    }

}