root/modules/zebra.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. clip8
  2. gui_osd_zebra_free
  3. gui_osd_zebra_init
  4. draw_pixel_buffered
  5. draw_guard_pixel
  6. gui_osd_draw_zebra_osd
  7. disp_zebra
  8. draw_zebra_aspect_adjust
  9. get_cur_buf
  10. draw_zebra_no_aspect_adjust
  11. gui_osd_draw_zebra
  12. gui_osd_zebra_free
  13. gui_osd_zebra_init
  14. gui_osd_draw_zebra_osd
  15. disp_zebra
  16. draw_zebra_no_aspect_adjust
  17. gui_osd_draw_zebra
  18. _module_unloader
  19. _module_can_unload

   1 #include "camera_info.h"
   2 #include "conf.h"
   3 #include "keyboard.h"
   4 #include "modes.h"
   5 #include "viewport.h"
   6 #include "properties.h"
   7 #include "gui.h"
   8 #include "gui_draw.h"
   9 #include "gui_lang.h"
  10 #include "gui_osd.h"
  11 #include "gui_mbox.h"
  12 #include "gui_batt.h"
  13 #include "gui_space.h"
  14 #include "histogram.h"
  15 
  16 #include "zebra.h"
  17 #include "gui_grid.h"
  18 #include "module_def.h"
  19 
  20 //-------------------------------------------------------------------
  21 
  22 // Notes on Zebra implementation.
  23 
  24 // The zebra code examines the Y (luminance) values of the camera
  25 // viewport to look for overexposed or underexposed pixels. The
  26 // range of low and high values that determine over and under
  27 // exposure is set with the 'zebra_over' and 'zebra_under' settings.
  28 
  29 // There is an RGB mode controlled by zebra_multichannel that
  30 // converts the viewport data from YUV to RGB and looks for exposure
  31 // problems in each channel.
  32 
  33 // Over and underexposed pixels are displayed on the bitmap screen
  34 // using the zebra_color setting - foregound color is used of over
  35 // exposure and background for under exposure.
  36 
  37 // The code tries to allocate a memory buffer that is the same dimensions
  38 // as the bitmap screen. The zebra display is written to this buffer
  39 // and when done the buffer is copied into the camera bitmap screen memory.
  40 // If the code can't allocate a memory buffer it writes the zebra data
  41 // directly to the camera bitmap screen memory. Allocation of the memory
  42 // buffer can also be overridden by setting CAM_ZEBRA_NOBUF in
  43 // platform_camera.h. The code here uses the equivalent setting from
  44 // camera_screen.zebra_nobuf for module platform indepedance.
  45 
  46 // There are two variations of the basic zebra code to cater for
  47 // different camera generations. Older cameras have a 360 byte wide
  48 // bitmap screen (or 480 for wide screen cameras). This matches the
  49 // CHDK virtual screen size so over and under exposed pixels are set
  50 // in the bitmap image buffer directly.
  51 // Newer cameras have a 720 (or 960) byte wide bitmap screen and the
  52 // zebra code write two bytes (pixels) into the buffer for every
  53 // over or underexposed pixel. Again the buffer is copied to the
  54 // camera bitmap memory when done.
  55 
  56 // Determining which code path is done with the CAM_USES_ASPECT_CORRECTION
  57 // value in platform_camera.h (accessed via camera_screen.zebra_aspect_adjust).
  58 // If CAM_USES_ASPECT_CORRECTION is not defined (or 0) the older code
  59 // is used that assumes the bitmap screen is 360 bytes wide.
  60 // Defining CAM_USES_ASPECT_CORRECTION as 1 will use the newer code.
  61 
  62 // Another difference is that the old code path saves the top and bottom
  63 // of the Canon OSD from the bitmap screen memory and overlays this on
  64 // top of the zebra buffer. The new code version does not do this. The
  65 // size of the strips saved is defined by ZFIX_TOP and ZFIX_BOTTOM.
  66 
  67 // The final element comes from cameras that can capture images in
  68 // different aspect ratios. Canon cameras all have a 4:3 ratio sensor
  69 // but many can capture an image in different sizes - e.g. 1:1, 3:2 and 16:9.
  70 // When these alternate ratios are selected the camera displays black
  71 // bars at the top and bottom or left and right edges of the image in
  72 // the viewport. The zebra code attempts to cater for this and not
  73 // display underexposure indicators in these unused areas. The size
  74 // and position of the black bars is also dependant on the aspect ratio
  75 // of the camera LCD. Cameras with 4:3 LCD screens will show a 16:9 image
  76 // with bars above and below. Cameras with 16:9 LCD screens will show
  77 // a 4:3 image with bars to the left and right.
  78 
  79 // For older cameras (that do not define CAM_USES_ASPECT_CORRECTION) the 
  80 // aspect ratio is controlled by the CAM_HAS_VARIABLE_ASPECT value
  81 // in platform_camera.h (camera_screen.has_variable_aspect). Defining
  82 // this value tells the code that the camera has a 16:9 LCD but can
  83 // also display a 4:3 image with black bars on the left and right.
  84 // The value of the PROPCASE_ASPECT_RATIO property determines which
  85 // image size if displayed. The code cannot handle other combinations
  86 // of LCD size and image ratio.
  87 
  88 // For newer cameras the code can handle any combination of LCD size
  89 // and image aspect ratio provided the vid_get_viewport_height(), 
  90 // vid_get_viewport_width(), vid_get_viewport_image_offset(),
  91 // vid_get_viewport_row_offset(), vid_get_viewport_display_xoffset(),
  92 // and vid_get_viewport_display_yoffset() functions have been correctly
  93 // implemented for the camera.
  94 
  95 // philmoz. Jan 2012.
  96 
  97 //-------------------------------------------------------------------
  98 
  99 // Height (in pixels) of half-shoot Canon OSD area of the screen buffer, for restore during 
 100 // Zebra draw, to limit RAM usage of zebra. Only these border areas are stored in RAM.
 101 // Only top and bottom are restored, not left & right.
 102 #define ZFIX_TOP    29
 103 #define ZFIX_BOTTOM 30
 104 
 105 static unsigned char *img_buf;
 106 #ifndef THUMB_FW
 107 static unsigned char *scr_buf;
 108 static unsigned char *cur_buf_top, *cur_buf_bot;
 109 static unsigned char *buf = NULL;
 110 static int buffer_size;
 111 #endif
 112 static int timer = 0;
 113 static color cl_under, cl_over;
 114 
 115 unsigned char clip8(signed short x){ if (x<0) x=0; else if (x>255) x=255; return x; }
 116 
 117 #ifndef THUMB_FW
 118 //-------------------------------------------------------------------
 119 // free and NULL zebra buffers. free(NULL) is always OK.
 120 static void gui_osd_zebra_free()
 121 {
 122     if (buf != scr_buf) free(buf);
 123     buf = NULL;
 124 
 125     free(cur_buf_top);
 126     cur_buf_top = NULL;
 127 
 128     free(cur_buf_bot);
 129     cur_buf_bot = NULL;
 130 }
 131 // prepare zebra resources, or free them
 132 // returns 1 if zebra should be drawn
 133 static int gui_osd_zebra_init(int show)
 134 {
 135     cl_under = BG_COLOR(user_color(conf.zebra_color));
 136     cl_over = FG_COLOR(user_color(conf.zebra_color));
 137 
 138     if (show)
 139     {
 140         if (!buf)
 141         {
 142             timer = 0;
 143             // Determine bitmap buffer size. If physical buffer is taller than displayed height then ignore bottom strip - (used to be ZEBRA_HMARGIN0).
 144             buffer_size = camera_screen.buffer_size - (camera_screen.buffer_height - camera_screen.height) * camera_screen.buffer_width;
 145             scr_buf = vid_get_bitmap_fb();
 146             if (camera_screen.zebra_nobuf == 0)
 147             {
 148                 buf = malloc(buffer_size);
 149                 //gui_mbox_init(LANG_WARNING, (int)"No space to allocate zebra buffer: restart camera", MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
 150             }
 151             if (!buf)
 152             {
 153                 buf = scr_buf;  //without new buffer: directly into screen buffer: we got some flickering in OSD and histogram but it's usable
 154             }
 155             if (camera_screen.zebra_aspect_adjust)
 156             {
 157                 cur_buf_top = cur_buf_bot = 0;
 158             }
 159             else
 160             {
 161                 cur_buf_top = malloc(camera_screen.buffer_width * ZFIX_TOP); 
 162                 cur_buf_bot = malloc(camera_screen.buffer_width * ZFIX_BOTTOM); 
 163                 // cleanup and disable zebra if any mallocs failed
 164                 if (!cur_buf_top || !cur_buf_bot)
 165                     gui_osd_zebra_free();
 166                 if (cur_buf_top) memset(cur_buf_top,0,camera_screen.buffer_width * ZFIX_TOP);
 167                 if (cur_buf_bot) memset(cur_buf_bot,0,camera_screen.buffer_width * ZFIX_BOTTOM);
 168             }
 169             // in variable aspect, the borders would never be cleared
 170             if (camera_screen.has_variable_aspect)
 171                 memset(buf,0,buffer_size);
 172         }
 173     }
 174     else {
 175         if (buf) // if zebra was previously on, restore
 176             gui_set_need_restore();
 177 
 178         gui_osd_zebra_free();
 179     }
 180     return (buf != NULL);
 181 }
 182 
 183 //-------------------------------------------------------------------
 184 // Override for standard drawing function to draw OSD elements
 185 // into the zebra memory buffer instead of the camera screen.
 186 static void draw_pixel_buffered(unsigned int offset, color cl)
 187 {
 188     buf[offset] = cl;
 189 }
 190 
 191 //-------------------------------------------------------------------
 192 int draw_guard_pixel() {
 193     unsigned char* buffer1 = vid_get_bitmap_fb()+camera_screen.buffer_size/2;
 194     unsigned char* buffer2 = buffer1+camera_screen.buffer_size;
 195     int has_disappeared=0;
 196 
 197     if(*buffer1!=COLOR_GREEN) has_disappeared=1;
 198     if(*buffer2!=COLOR_GREEN) has_disappeared=2;
 199     *buffer1 = *buffer2 = COLOR_GREEN;
 200     return has_disappeared;
 201 }
 202 
 203 //-------------------------------------------------------------------
 204 static void gui_osd_draw_zebra_osd() {
 205     switch (conf.zebra_draw_osd) {
 206         case ZEBRA_DRAW_NONE:
 207             break;
 208         case ZEBRA_DRAW_OSD:
 209             if (conf.show_osd) {
 210                 draw_set_draw_proc(draw_pixel_buffered);
 211                 gui_draw_osd_elements(0,1);
 212                 draw_set_draw_proc(NULL);
 213             }
 214             /* no break here */
 215         case ZEBRA_DRAW_HISTO:
 216         default:
 217             draw_set_draw_proc(draw_pixel_buffered);
 218             libhisto->gui_osd_draw_histo(0);
 219             draw_set_draw_proc(NULL);
 220             break;
 221     }
 222 }
 223 
 224 //-------------------------------------------------------------------
 225 static void disp_zebra()
 226 {
 227     // draw CHDK osd and histogram to buf[] (if enabled in config)
 228     gui_osd_draw_zebra_osd();
 229 
 230     // copy buf[] to both display buffers
 231     if (buf != scr_buf)
 232         memcpy(scr_buf, buf, buffer_size);
 233     memcpy(scr_buf+camera_screen.buffer_size, buf, buffer_size);
 234 }
 235 
 236 //-------------------------------------------------------------------
 237 // CHDK uses a virtual screen size of 360 x 240 pixels (480x240 for wide screen models)
 238 // This function calculates the Zebra overlay for cameras where the screen buffer width
 239 // is not equivalent to the CHDK virtual screen width. Newer cameras have a 720
 240 // pixel wide screen (960 for wide screen models).
 241 static int draw_zebra_aspect_adjust(int mrec, unsigned int f, color *cls)
 242 {
 243     int v, s, x, y, over;
 244     static int need_restore=0;
 245     int viewport_height;
 246     int viewport_width; 
 247     int viewport_image_offset;  // for when viewport memory buffer is wider than viewport
 248     int viewport_row_offset;    // for when viewport memory buffer is wider than viewport
 249     int viewport_xoffset;           // used when image size != viewport size
 250     int viewport_yoffset;           // used when image size != viewport size
 251     int zebra_drawn=0;
 252 
 253     viewport_height = vid_get_viewport_height();
 254     viewport_width = vid_get_viewport_width(); 
 255     viewport_image_offset = vid_get_viewport_image_offset(); 
 256     viewport_row_offset = vid_get_viewport_row_offset(); 
 257     viewport_xoffset = vid_get_viewport_display_xoffset();
 258     viewport_yoffset = vid_get_viewport_display_yoffset();
 259 
 260     // if not in no-zebra phase of blink mode zebra, draw zebra to buf[]
 261     if (f) {
 262         if (viewport_yoffset > 0) { // clear top & bottom areas of buffer if image height if smaller than viewport
 263             memset(buf, COLOR_TRANSPARENT, viewport_yoffset*camera_screen.buffer_width);
 264             memset(buf+(viewport_yoffset+viewport_height)*camera_screen.buffer_width, COLOR_TRANSPARENT, viewport_yoffset*camera_screen.buffer_width);
 265         }
 266         int step_x, step_v, sy, sx;
 267         over = 255-conf.zebra_over;
 268         if (conf.zebra_multichannel) {step_x=2; step_v=6;} else {step_x=1; step_v=3;}
 269         for (y=viewport_yoffset, v=viewport_image_offset; y<viewport_yoffset+viewport_height; ++y) {
 270             sy = y*camera_screen.buffer_width;
 271             sx = viewport_xoffset;
 272             if (viewport_xoffset > 0) { // clear left & right areas of buffer if image width if smaller than viewport
 273                 memset(buf+sy, COLOR_TRANSPARENT, sx*2);
 274                 memset(buf+sy+(sx+viewport_width)*2, COLOR_TRANSPARENT, sx*2);
 275             }
 276             for (x=viewport_xoffset; x<viewport_xoffset+viewport_width; x+=step_x, sx+=step_x, v+=step_v) {
 277                 register int yy;
 278                 yy = img_buf[v+1];
 279                 s = sy + sx*2;
 280 
 281                 if (conf.zebra_multichannel) {
 282                     register int uu, vv;
 283                     int sel;
 284                     uu = (signed char)img_buf[v];
 285                     vv = (signed char)img_buf[v+2];
 286                     sel=0;
 287                     if (!((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f)) {
 288                         if (clip8(((yy<<12) +           vv*5743 + 2048)>>12)>over) sel  = 4; // R
 289                         if (clip8(((yy<<12) - uu*1411 - vv*2925 + 2048)>>12)>over) sel |= 2; // G
 290                         if (clip8(((yy<<12) + uu*7258           + 2048)>>12)>over) sel |= 1; // B
 291                     }
 292                     buf[s] = buf[s+1] = cls[sel];
 293                     buf[s+2] = buf[s+3] = cls[sel];
 294                 }
 295                 else if (((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f))
 296                     buf[s] = buf[s+1] = COLOR_TRANSPARENT;
 297                 else 
 298                     buf[s] = buf[s+1] = (yy>over)?cl_over:(yy<conf.zebra_under)?cl_under:COLOR_TRANSPARENT;
 299 
 300                 if (buf[s] != COLOR_TRANSPARENT && !zebra_drawn) 
 301                     zebra_drawn = 1;
 302             }
 303             // adjust for cases where buffer is wider than viewport (e.g. on G12)
 304             v += viewport_row_offset;
 305         }
 306         if (!zebra_drawn) f=0;
 307     }
 308     // if blink mode is in no-zebra phase OR if there was no over/underexposed pixels to draw zebra on
 309     if (!f) {
 310         // if zebra was drawn during previous call of this function
 311         if (need_restore) {
 312             if (conf.zebra_restore_screen || conf.zebra_restore_osd) {
 313                 gui_set_need_restore();
 314             } else {  // clear buf[] of zebra, only leave Canon OSD
 315                 if (!mrec) { // Not REC mode
 316                     // No Canon OSD restore, fill buf[] with transparent color:
 317                     memset(buf, COLOR_TRANSPARENT, buffer_size);
 318                 }
 319                 disp_zebra();
 320             }
 321             need_restore=0;
 322         }
 323         return !(conf.zebra_restore_screen && conf.zebra_restore_osd);
 324         // if zebra was drawn
 325     } else {
 326         disp_zebra();
 327 
 328         need_restore=1;
 329         return 1;
 330     }
 331     return 0;
 332 }
 333 
 334 //-------------------------------------------------------------------
 335 // Get the current Canon OSD pixel value for the top or bottom strip
 336 static unsigned char get_cur_buf(unsigned int idx) {
 337     unsigned int a;
 338 
 339     a=camera_screen.buffer_size - camera_screen.buffer_width * ZFIX_BOTTOM;
 340 
 341     if (idx < (unsigned)camera_screen.buffer_width * ZFIX_TOP) return(cur_buf_top[idx]);
 342     if (idx >= a && idx < (unsigned)camera_screen.buffer_size) return(cur_buf_bot[idx - a]);
 343     return (COLOR_TRANSPARENT);
 344 }
 345 
 346 //-------------------------------------------------------------------
 347 // This function calculates the Zebra overlay for cameras where the screen buffer width
 348 // is equivalent to the CHDK virtual screen width. For older cameras where the screen
 349 // width is 360 pixels (or 480 for wide screen).
 350 static int draw_zebra_no_aspect_adjust(int mrec, unsigned int f, color *cls) {
 351     int v, s, x, y, over;
 352     static int need_restore=0;
 353     int viewport_height;
 354     int zebra_drawn=0;
 355 
 356     unsigned bWide = 1; // if wide (16:9) or standard (4:3) aspect ratio (but 1 in cameras that only have 4:3)
 357     unsigned aspOffset = 0; // offset to add to x-coord (or buffer address) when drawing zebra
 358 
 359     if (camera_screen.has_variable_aspect && camera_info.props.aspect_ratio)
 360     {
 361         if (shooting_get_prop(camera_info.props.aspect_ratio) == 0) // standard requires x-shift to overlay drawing
 362         {
 363             bWide = 0;
 364             //aspOffset = (camera_screen.width - (camera_screen.width * 12 / 16)) / 2; // = actual calculation, simplified below
 365             aspOffset = camera_screen.width / 8; // half of the difference in width between equal height 16:9 and 4:3 screens, = black bar width
 366         }
 367     }
 368 
 369     viewport_height = vid_get_viewport_height();
 370 
 371     // if not in no-zebra phase of blink mode zebra, draw zebra to buf[]
 372     if (f) {
 373         int step_x, step_v;
 374         over = 255-conf.zebra_over;
 375         if (conf.zebra_multichannel) {step_x=2; step_v=6;} else {step_x=1; step_v=3;}
 376         s = aspOffset;
 377         for (y=1, v=0; y<=viewport_height; ++y) {
 378             for (x=0; x<camera_screen.width; x+=step_x, s+=step_x, v+=step_v) {
 379                 register int yy, uu, vv;
 380                 int sel;
 381 
 382                 if (!bWide && (x + aspOffset >= camera_screen.width - aspOffset)) continue; // do not draw "outside screen" 
 383 
 384                 yy = img_buf[v+1];
 385                 if (conf.zebra_multichannel) {
 386                     uu = (signed char)img_buf[v];
 387                     vv = (signed char)img_buf[v+2];
 388                     sel=0;
 389                     if (!((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f)) {
 390                         if (clip8(((yy<<12) +           vv*5743 + 2048)>>12)>over) sel  = 4; // R
 391                         if (clip8(((yy<<12) - uu*1411 - vv*2925 + 2048)>>12)>over) sel |= 2; // G
 392                         if (clip8(((yy<<12) + uu*7258           + 2048)>>12)>over) sel |= 1; // B
 393                     }
 394                     buf[s]=buf[s+1]=cls[sel];
 395                 }
 396                 else if (((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f)) buf[s]=COLOR_TRANSPARENT;
 397                 else buf[s]=(yy>over)?cl_over:(yy<conf.zebra_under)?cl_under:COLOR_TRANSPARENT;
 398                 if (buf[s] != COLOR_TRANSPARENT && !zebra_drawn) zebra_drawn = 1;
 399                 if (mrec) {
 400                     // draw Canon OSD to buf[] if in REC mode
 401                     if(get_cur_buf(s)!=COLOR_TRANSPARENT) buf[s]=get_cur_buf(s); 
 402                     if(conf.zebra_multichannel && get_cur_buf(s+1)!=COLOR_TRANSPARENT) buf[s+1]=get_cur_buf(s+1); 
 403                 }
 404             }
 405             s+=camera_screen.buffer_width-camera_screen.width;
 406             if (y*camera_screen.height/viewport_height == (s+camera_screen.buffer_width)/camera_screen.buffer_width) {
 407                 memcpy(buf+s, buf+s-camera_screen.buffer_width, camera_screen.buffer_width);
 408                 s+=camera_screen.buffer_width;
 409             }
 410         }
 411         if (!zebra_drawn) f=0;
 412     }
 413     // if blink mode is in no-zebra phase OR if there was no over/underexposed pixels to draw zebra on
 414     if (!f) {
 415         // if zebra was drawn during previous call of this function
 416         if (need_restore) {
 417             if (conf.zebra_restore_screen || conf.zebra_restore_osd) {
 418                 gui_set_need_restore();
 419             } else {  // clear buf[] of zebra, only leave Canon OSD
 420                 if (mrec) { // REC mode
 421                     // copy rescued Canon OSD to buf[] top/bottom parts and fill center with transparent color:
 422                     memcpy(buf, cur_buf_top, camera_screen.buffer_width * ZFIX_TOP);
 423                     memcpy(buf + buffer_size - camera_screen.buffer_width * ZFIX_BOTTOM, cur_buf_bot, camera_screen.buffer_width * ZFIX_BOTTOM);
 424                     for (s = camera_screen.buffer_width*ZFIX_TOP; s < buffer_size-camera_screen.buffer_width*ZFIX_BOTTOM; s++) {
 425                         buf[s]=COLOR_TRANSPARENT;
 426                     }
 427                 } else { // Not REC mode
 428                     // No Canon OSD restore, fill buf[] with transparent color:
 429                     memset(buf, COLOR_TRANSPARENT, buffer_size);
 430                 }
 431                 disp_zebra();
 432             }
 433             need_restore=0;
 434         }
 435         return !(conf.zebra_restore_screen && conf.zebra_restore_osd);
 436         // if zebra was drawn
 437     } else {
 438         disp_zebra();
 439 
 440         need_restore=1;
 441         return 1;
 442     }
 443     return 0;
 444 }
 445 
 446 //-------------------------------------------------------------------
 447 int gui_osd_draw_zebra(int show)
 448 {
 449     unsigned int f;
 450 
 451     if (!gui_osd_zebra_init(show))
 452         return 0;
 453 
 454     color cls[] = {
 455         COLOR_TRANSPARENT,
 456         COLOR_BLUE,
 457         COLOR_GREEN,
 458         COLOR_CYAN,
 459         COLOR_RED,
 460         COLOR_MAGENTA,
 461         COLOR_YELLOW,
 462         COLOR_BLACK
 463     };
 464 
 465     img_buf = vid_get_viewport_active_buffer();
 466     if (!img_buf) return 0;
 467 
 468     if (timer==0)
 469     {
 470         draw_guard_pixel();
 471         timer = 1;
 472         return 0;
 473     }
 474 
 475     if (timer==1)
 476     {
 477         int ready;
 478         static int n=0;
 479         if (!camera_info.state.mode_rec) ready=1;
 480         else get_property_case(camera_info.props.shooting, &ready, 4);
 481         n=draw_guard_pixel(); // will be 0 in PLAY mode, should be 1 or 2 in REC mode.
 482         if(!ready) return 0;
 483         if (cur_buf_top)
 484         {
 485             // rescue Canon OSD from scr_buf to cur_buf_top and _bot:
 486             if (n==1) {
 487                 memcpy(cur_buf_top, scr_buf, camera_screen.buffer_width*ZFIX_TOP);
 488                 memcpy(cur_buf_bot, scr_buf + camera_screen.buffer_size - camera_screen.buffer_width*ZFIX_BOTTOM, camera_screen.buffer_width*ZFIX_BOTTOM);
 489             }
 490             else {
 491                 memcpy(cur_buf_top, scr_buf + camera_screen.buffer_size, camera_screen.buffer_width*ZFIX_TOP);
 492                 memcpy(cur_buf_bot, scr_buf + 2*camera_screen.buffer_size - camera_screen.buffer_width*ZFIX_BOTTOM, camera_screen.buffer_width*ZFIX_BOTTOM);
 493             }
 494         }
 495     }
 496     ++timer;
 497 
 498     switch (conf.zebra_mode)
 499     {
 500         case ZEBRA_MODE_ZEBRA_1:    f = 4;          break;
 501         case ZEBRA_MODE_ZEBRA_2:    f = 8;          break;
 502         case ZEBRA_MODE_SOLID:      f = 1;          break;
 503         case ZEBRA_MODE_BLINKED_1:  f = timer&1;    break;
 504         case ZEBRA_MODE_BLINKED_3:  f = timer&4;    break;
 505         case ZEBRA_MODE_BLINKED_2:  
 506         default:                    f = timer&2;    break;
 507     }
 508 
 509     if (camera_screen.zebra_aspect_adjust)
 510         return draw_zebra_aspect_adjust(camera_info.state.mode_rec,f,cls);    // For newer cameras with 720/960 pixel wide screen
 511     else
 512         return draw_zebra_no_aspect_adjust(camera_info.state.mode_rec,f,cls); // For older cameras with 360/480 pixel wide screen
 513 }
 514 #else // THUMB_FW
 515 //digic 6 code below here
 516 
 517 typedef struct
 518 {
 519     unsigned int yuv;
 520     unsigned int op;
 521 } rawcolor_s;
 522 
 523 rawcolor_s clr[10];
 524 int shown = 0;
 525 
 526 // D6 version draws directly, no allocs
 527 static void gui_osd_zebra_free()
 528 {
 529     shown = 0;;
 530 }
 531 
 532 // prepare zebra resources, or free them
 533 // returns 1 if zebra should be drawn
 534 static int gui_osd_zebra_init(int show)
 535 {
 536     color cls[] =
 537     {
 538         COLOR_TRANSPARENT,
 539         COLOR_BLUE,
 540         COLOR_GREEN,
 541         COLOR_CYAN,
 542         COLOR_RED,
 543         COLOR_MAGENTA,
 544         COLOR_YELLOW,
 545         COLOR_BLACK
 546     };
 547 
 548     cl_under = BG_COLOR(user_color(conf.zebra_color));
 549     cl_over = FG_COLOR(user_color(conf.zebra_color));
 550 
 551     if (show)
 552     {
 553         if (!shown)
 554         {
 555             timer = 0;
 556             shown = 1;
 557             int f;
 558             for (f=0; f<8; f++)
 559             {
 560                 clr[f].yuv = color_to_rawpx(cls[f], &(clr[f].op));
 561             }
 562             clr[8].yuv = color_to_rawpx(cl_over, &(clr[8].op));
 563             clr[9].yuv = color_to_rawpx(cl_under, &(clr[9].op));
 564         }
 565     }
 566     else
 567     {
 568         if (shown) // if zebra was previously on, restore
 569         {
 570             erase_zebra();
 571         }
 572         gui_osd_zebra_free();
 573     }
 574     return (shown);
 575 }
 576 
 577 //-------------------------------------------------------------------
 578 // neither OSD nor histogram can be drawn over zebra
 579 // draw_set_draw_proc() is not respected by the current D6 drawing code anyway
 580 static void gui_osd_draw_zebra_osd() {
 581 //     switch (conf.zebra_draw_osd) {
 582 //         case ZEBRA_DRAW_NONE:
 583 //             break;
 584 //         case ZEBRA_DRAW_OSD:
 585 //             if (conf.show_osd) {
 586 //                 draw_set_draw_proc(draw_dblpixel_raw);
 587 //                 gui_draw_osd_elements(0,1);
 588 //                 draw_set_draw_proc(NULL);
 589 //             }
 590 //             /* no break here */
 591 //         case ZEBRA_DRAW_HISTO:
 592 //         default:
 593 //             draw_set_draw_proc(draw_dblpixel_raw);
 594 //             libhisto->gui_osd_draw_histo(0);
 595 //             draw_set_draw_proc(NULL);
 596 //             break;
 597 //     }
 598 }
 599 
 600 //-------------------------------------------------------------------
 601 static void disp_zebra()
 602 {
 603     // draw CHDK osd and histogram to buf[] (if enabled in config)
 604     gui_osd_draw_zebra_osd();
 605 }
 606 
 607 //-------------------------------------------------------------------
 608 // CHDK uses a virtual screen size of 360 x 240 pixels (480x240 for wide screen models)
 609 static int draw_zebra_no_aspect_adjust(unsigned int f)
 610 {
 611     int x, y, over;
 612     unsigned int v, bitmap_byte;
 613     static int need_restore=0;
 614     int viewport_height;
 615     int viewport_width; 
 616     int viewport_byte_width;
 617 
 618     int viewport_xoffset;    // used when image size != viewport size
 619     int viewport_yoffset;    // used when image size != viewport size
 620     int zebra_drawn=0;
 621     static int d_cnt =0;
 622     d_cnt++;
 623 
 624     viewport_height = vid_get_viewport_height();
 625     viewport_width = vid_get_viewport_width(); 
 626     viewport_byte_width = vid_get_viewport_byte_width();
 627     viewport_xoffset = vid_get_viewport_display_xoffset(); //columns
 628     viewport_yoffset = vid_get_viewport_display_yoffset();
 629 
 630     // if not in no-zebra phase of blink mode zebra, draw zebra  
 631     if (f)
 632     {
 633         if (viewport_yoffset > 0)
 634         {
 635             // clear top & bottom areas of buffer if image height if smaller than viewport
 636         }
 637         over = 255-conf.zebra_over;
 638 
 639         for (y=0; y<viewport_height ; ++y)
 640         {
 641 //e.g. on SX60hs LCD is 640x480
 642 // 
 643 // 16:9     f:8 vh:360 vw:640 vbw:1280 vxo:0 vyo:60
 644 //1x1        f:8 vh:480 vw:480 vbw:1280 vxo:80 vyo:0
 645             //this can be made more efficient, but for now want clarity 
 646             for (x=0; x<viewport_width; x+=2)
 647             {
 648                 v = y*(viewport_byte_width) + x + x ; //v is the byte number in img-buf  0...480,480+320...960,
 649                 bitmap_byte = (y + viewport_yoffset) * viewport_byte_width + 2*(x + viewport_xoffset);
 650 
 651                 int sel = 0;
 652                 if (!((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f))
 653                 {
 654                     register int y1, uu, vv;
 655                     unsigned int ibuf = *(unsigned int*)(&img_buf[v&0xfffffffc]);
 656                     uu = (signed char)((ibuf&0xff)-128);
 657                     vv = (signed char)(((ibuf>>16)&0xff)-128);
 658                     // for simplicity check only first pixel y1
 659                     y1 = (unsigned char)((ibuf>>8)&0xff);
 660 
 661                     if (conf.zebra_multichannel)
 662                     {
 663                         if (clip8(((y1<<12) +           vv*5743 + 2048)>>12)>over) sel  = 4; // R
 664                         if (clip8(((y1<<12) - uu*1411 - vv*2925 + 2048)>>12)>over) sel |= 2; // G
 665                         if (clip8(((y1<<12) + uu*7258           + 2048)>>12)>over) sel |= 1; // B
 666                     }
 667                     else
 668                     {
 669                         // if y1 is over or under
 670                         // set two pixels to over / under color
 671                         sel = (y1>over) ? 8 : (y1<conf.zebra_under) ? 9 : 0;
 672                     }
 673                 }
 674                 //set two pixels (4 bytes )
 675                 draw_dblpixel_raw(bitmap_byte, clr[sel].yuv, clr[sel].op);
 676                 if (sel)
 677                     zebra_drawn = 1;
 678             }
 679         }
 680         if (!zebra_drawn) f = 0;
 681     }
 682     // if blink mode is in no-zebra phase OR if there was no over/underexposed pixels to draw zebra on
 683     if (!f)
 684     {
 685         // if zebra was drawn during previous call of this function
 686         if (need_restore)
 687         {
 688             // clear buf[] of zebra
 689             erase_zebra();  //blink
 690             disp_zebra();
 691             need_restore=0;
 692         }
 693         return !(conf.zebra_restore_screen && conf.zebra_restore_osd);
 694     }
 695     else
 696     {
 697         // if zebra was drawn
 698         disp_zebra();
 699         need_restore=1;
 700         return 1;
 701     }
 702     return 0;
 703 }
 704 
 705 //-------------------------------------------------------------------
 706 int gui_osd_draw_zebra(int show)
 707 {
 708     unsigned int f;
 709 
 710     // Check that viewport dimensions do not exceed bitmap dimensions.
 711     // HDMI output uses a larger frame for the image compared to the bitmap we draw on - the code can't handle this and will crash
 712     if ((vid_get_viewport_width() > camera_screen.width) || (vid_get_viewport_height() > camera_screen.height))
 713         return 0;
 714 
 715     if (!gui_osd_zebra_init(show))
 716         return 0;
 717 
 718     img_buf = vid_get_viewport_active_buffer();
 719     if (!img_buf) return 0;
 720     // img_buf += vid_get_viewport_image_offset(); //always zero anyway
 721 
 722     if (timer==0)
 723     {
 724         timer = 1;
 725         return 0;
 726     }
 727 
 728     if (timer==1)
 729     {
 730         int ready;
 731         if (!camera_info.state.mode_rec) ready=1;
 732         else get_property_case(camera_info.props.shooting, &ready, 4);
 733         if(!ready) return 0;
 734 
 735     }
 736     ++timer;
 737 
 738     switch (conf.zebra_mode)
 739     {
 740         case ZEBRA_MODE_ZEBRA_1:    f = 4;          break;
 741         case ZEBRA_MODE_ZEBRA_2:    f = 8;          break;
 742         case ZEBRA_MODE_SOLID:      f = 1;          break;
 743         case ZEBRA_MODE_BLINKED_1:  f = timer&1;    break;
 744         case ZEBRA_MODE_BLINKED_3:  f = timer&4;    break;
 745         case ZEBRA_MODE_BLINKED_2:  
 746         default:                    f = timer&2;    break;
 747     }
 748 
 749     return draw_zebra_no_aspect_adjust(f);
 750 }
 751 
 752 #endif // THUMB_FW
 753 
 754 // =========  MODULE INIT =================
 755 
 756 /***************** BEGIN OF AUXILARY PART *********************
 757   ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
 758  **************************************************************/
 759 
 760 //---------------------------------------------------------
 761 // PURPOSE: Finalize module operations (close allocs, etc)
 762 // RETURN VALUE: 0-ok, 1-fail
 763 //---------------------------------------------------------
 764 int _module_unloader()
 765 {
 766     gui_osd_zebra_free();
 767     return 0;
 768 }
 769 
 770 int _module_can_unload()
 771 {
 772     return conf.zebra_draw == 0;
 773 }
 774 
 775 /******************** Module Information structure ******************/
 776 
 777 libzebra_sym _libzebra =
 778 {
 779     {
 780          0, _module_unloader, _module_can_unload, 0, 0
 781     },
 782 
 783     gui_osd_draw_zebra
 784 };
 785 
 786 ModuleInfo _module_info =
 787 {
 788     MODULEINFO_V1_MAGICNUM,
 789     sizeof(ModuleInfo),
 790     ZEBRA_VERSION,                              // Module version
 791 
 792     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,                       // Requirements of CHDK version
 793     ANY_PLATFORM_ALLOWED,               // Specify platform dependency
 794 
 795     (int32_t)"Zebra Overlay (dll)",
 796     MTYPE_EXTENSION,
 797 
 798     &_libzebra.base,
 799 
 800     CONF_VERSION,               // CONF version
 801     CAM_SCREEN_VERSION,         // CAM SCREEN version
 802     ANY_VERSION,                // CAM SENSOR version
 803     CAM_INFO_VERSION,           // CAM INFO version
 804 
 805     0,
 806 };
 807 
 808 /*************** END OF AUXILARY PART *******************/

/* [<][>][^][v][top][bottom][index][help] */