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. draw_guard_pixel
  15. gui_osd_draw_zebra_osd
  16. disp_zebra
  17. draw_zebra_no_aspect_adjust
  18. gui_osd_draw_zebra
  19. _module_unloader
  20. _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, *scr_buf;
 106 #ifndef THUMB_FW
 107 static unsigned char *cur_buf_top, *cur_buf_bot;
 108 #endif
 109 static int timer = 0;
 110 static unsigned char *buf = NULL;
 111 static int buffer_size;
 112 static color cl_under, cl_over;
 113 
 114 unsigned char clip8(signed short x){ if (x<0) x=0; else if (x>255) x=255; return x; }
 115 
 116 #ifndef THUMB_FW
 117 //-------------------------------------------------------------------
 118 // free and NULL zebra buffers. free(NULL) is always OK.
 119 static void gui_osd_zebra_free()
 120 {
 121     if (buf != scr_buf) free(buf);
 122     buf = NULL;
 123 
 124     free(cur_buf_top);
 125     cur_buf_top = NULL;
 126 
 127     free(cur_buf_bot);
 128     cur_buf_bot = NULL;
 129 }
 130 // prepare zebra resources, or free them
 131 // returns 1 if zebra should be drawn
 132 static int gui_osd_zebra_init(int show)
 133 {
 134     cl_under = BG_COLOR(user_color(conf.zebra_color));
 135     cl_over = FG_COLOR(user_color(conf.zebra_color));
 136 
 137     if (show)
 138     {
 139         if (!buf)
 140         {
 141             timer = 0;
 142             // Determine bitmap buffer size. If physical buffer is taller than displayed height then ignore bottom strip - (used to be ZEBRA_HMARGIN0).
 143             buffer_size = camera_screen.buffer_size - (camera_screen.buffer_height - camera_screen.height) * camera_screen.buffer_width;
 144             scr_buf = vid_get_bitmap_fb();
 145             if (camera_screen.zebra_nobuf == 0)
 146             {
 147                 buf = malloc(buffer_size);
 148                 //gui_mbox_init(LANG_WARNING, (int)"No space to allocate zebra buffer: restart camera", MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
 149             }
 150             if (!buf)
 151             {
 152                 buf = scr_buf;  //without new buffer: directly into screen buffer: we got some flickering in OSD and histogram but it's usable
 153             }
 154             if (camera_screen.zebra_aspect_adjust)
 155             {
 156                 cur_buf_top = cur_buf_bot = 0;
 157             }
 158             else
 159             {
 160                 cur_buf_top = malloc(camera_screen.buffer_width * ZFIX_TOP); 
 161                 cur_buf_bot = malloc(camera_screen.buffer_width * ZFIX_BOTTOM); 
 162                 // cleanup and disable zebra if any mallocs failed
 163                 if (!cur_buf_top || !cur_buf_bot)
 164                     gui_osd_zebra_free();
 165                 if (cur_buf_top) memset(cur_buf_top,0,camera_screen.buffer_width * ZFIX_TOP);
 166                 if (cur_buf_bot) memset(cur_buf_bot,0,camera_screen.buffer_width * ZFIX_BOTTOM);
 167             }
 168             // in variable aspect, the borders would never be cleared
 169             if (camera_screen.has_variable_aspect)
 170                 memset(buf,0,buffer_size);
 171         }
 172     }
 173     else {
 174         if (buf) // if zebra was previously on, restore
 175             gui_set_need_restore();
 176 
 177         gui_osd_zebra_free();
 178     }
 179     return (buf != NULL);
 180 }
 181 
 182 //-------------------------------------------------------------------
 183 // Override for standard drawing function to draw OSD elements
 184 // into the zebra memory buffer instead of the camera screen.
 185 static void draw_pixel_buffered(unsigned int offset, color cl)
 186 {
 187     buf[offset] = cl;
 188 }
 189 
 190 //-------------------------------------------------------------------
 191 int draw_guard_pixel() {
 192     unsigned char* buffer1 = vid_get_bitmap_fb()+camera_screen.buffer_size/2;
 193     unsigned char* buffer2 = buffer1+camera_screen.buffer_size;
 194     int has_disappeared=0;
 195 
 196     if(*buffer1!=COLOR_GREEN) has_disappeared=1;
 197     if(*buffer2!=COLOR_GREEN) has_disappeared=2;
 198     *buffer1 = *buffer2 = COLOR_GREEN;
 199     return has_disappeared;
 200 }
 201 
 202 //-------------------------------------------------------------------
 203 static void gui_osd_draw_zebra_osd() {
 204     switch (conf.zebra_draw_osd) {
 205         case ZEBRA_DRAW_NONE:
 206             break;
 207         case ZEBRA_DRAW_OSD:
 208             if (conf.show_osd) {
 209                 draw_set_draw_proc(draw_pixel_buffered);
 210                 gui_draw_osd_elements(0,1);
 211                 draw_set_draw_proc(NULL);
 212             }
 213             /* no break here */
 214         case ZEBRA_DRAW_HISTO:
 215         default:
 216             draw_set_draw_proc(draw_pixel_buffered);
 217             libhisto->gui_osd_draw_histo(0);
 218             draw_set_draw_proc(NULL);
 219             break;
 220     }
 221 }
 222 
 223 //-------------------------------------------------------------------
 224 static void disp_zebra()
 225 {
 226     // draw CHDK osd and histogram to buf[] (if enabled in config)
 227     gui_osd_draw_zebra_osd();
 228 
 229     // copy buf[] to both display buffers
 230     if (buf != scr_buf)
 231         memcpy(scr_buf, buf, buffer_size);
 232     memcpy(scr_buf+camera_screen.buffer_size, buf, buffer_size);
 233 }
 234 
 235 //-------------------------------------------------------------------
 236 // CHDK uses a virtual screen size of 360 x 240 pixels (480x240 for wide screen models)
 237 // This function calculates the Zebra overlay for cameras where the screen buffer width
 238 // is not equivalent to the CHDK virtual screen width. Newer cameras have a 720
 239 // pixel wide screen (960 for wide screen models).
 240 static int draw_zebra_aspect_adjust(int mrec, unsigned int f, color *cls)
 241 {
 242     int v, s, x, y, over;
 243     static int need_restore=0;
 244     int viewport_height;
 245     int viewport_width; 
 246     int viewport_image_offset;  // for when viewport memory buffer is wider than viewport
 247     int viewport_row_offset;    // for when viewport memory buffer is wider than viewport
 248     int viewport_xoffset;           // used when image size != viewport size
 249     int viewport_yoffset;           // used when image size != viewport size
 250     int zebra_drawn=0;
 251 
 252     viewport_height = vid_get_viewport_height();
 253     viewport_width = vid_get_viewport_width(); 
 254     viewport_image_offset = vid_get_viewport_image_offset(); 
 255     viewport_row_offset = vid_get_viewport_row_offset(); 
 256     viewport_xoffset = vid_get_viewport_display_xoffset();
 257     viewport_yoffset = vid_get_viewport_display_yoffset();
 258 
 259     // if not in no-zebra phase of blink mode zebra, draw zebra to buf[]
 260     if (f) {
 261         if (viewport_yoffset > 0) { // clear top & bottom areas of buffer if image height if smaller than viewport
 262             memset(buf, COLOR_TRANSPARENT, viewport_yoffset*camera_screen.buffer_width);
 263             memset(buf+(viewport_yoffset+viewport_height)*camera_screen.buffer_width, COLOR_TRANSPARENT, viewport_yoffset*camera_screen.buffer_width);
 264         }
 265         int step_x, step_v, sy, sx;
 266         over = 255-conf.zebra_over;
 267         if (conf.zebra_multichannel) {step_x=2; step_v=6;} else {step_x=1; step_v=3;}
 268         for (y=viewport_yoffset, v=viewport_image_offset; y<viewport_yoffset+viewport_height; ++y) {
 269             sy = y*camera_screen.buffer_width;
 270             sx = viewport_xoffset;
 271             if (viewport_xoffset > 0) { // clear left & right areas of buffer if image width if smaller than viewport
 272                 memset(buf+sy, COLOR_TRANSPARENT, sx*2);
 273                 memset(buf+sy+(sx+viewport_width)*2, COLOR_TRANSPARENT, sx*2);
 274             }
 275             for (x=viewport_xoffset; x<viewport_xoffset+viewport_width; x+=step_x, sx+=step_x, v+=step_v) {
 276                 register int yy;
 277                 yy = img_buf[v+1];
 278                 s = sy + sx*2;
 279 
 280                 if (conf.zebra_multichannel) {
 281                     register int uu, vv;
 282                     int sel;
 283                     uu = (signed char)img_buf[v];
 284                     vv = (signed char)img_buf[v+2];
 285                     sel=0;
 286                     if (!((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f)) {
 287                         if (clip8(((yy<<12) +           vv*5743 + 2048)>>12)>over) sel  = 4; // R
 288                         if (clip8(((yy<<12) - uu*1411 - vv*2925 + 2048)>>12)>over) sel |= 2; // G
 289                         if (clip8(((yy<<12) + uu*7258           + 2048)>>12)>over) sel |= 1; // B
 290                     }
 291                     buf[s] = buf[s+1] = cls[sel];
 292                     buf[s+2] = buf[s+3] = cls[sel];
 293                 }
 294                 else if (((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f))
 295                     buf[s] = buf[s+1] = COLOR_TRANSPARENT;
 296                 else 
 297                     buf[s] = buf[s+1] = (yy>over)?cl_over:(yy<conf.zebra_under)?cl_under:COLOR_TRANSPARENT;
 298 
 299                 if (buf[s] != COLOR_TRANSPARENT && !zebra_drawn) 
 300                     zebra_drawn = 1;
 301             }
 302             // adjust for cases where buffer is wider than viewport (e.g. on G12)
 303             v += viewport_row_offset;
 304         }
 305         if (!zebra_drawn) f=0;
 306     }
 307     // if blink mode is in no-zebra phase OR if there was no over/underexposed pixels to draw zebra on
 308     if (!f) {
 309         // if zebra was drawn during previous call of this function
 310         if (need_restore) {
 311             if (conf.zebra_restore_screen || conf.zebra_restore_osd) {
 312                 gui_set_need_restore();
 313             } else {  // clear buf[] of zebra, only leave Canon OSD
 314                 if (!mrec) { // Not REC mode
 315                     // No Canon OSD restore, fill buf[] with transparent color:
 316                     memset(buf, COLOR_TRANSPARENT, buffer_size);
 317                 }
 318                 disp_zebra();
 319             }
 320             need_restore=0;
 321         }
 322         return !(conf.zebra_restore_screen && conf.zebra_restore_osd);
 323         // if zebra was drawn
 324     } else {
 325         disp_zebra();
 326 
 327         need_restore=1;
 328         return 1;
 329     }
 330     return 0;
 331 }
 332 
 333 //-------------------------------------------------------------------
 334 // Get the current Canon OSD pixel value for the top or bottom strip
 335 static unsigned char get_cur_buf(unsigned int idx) {
 336     unsigned int a;
 337 
 338     a=camera_screen.buffer_size - camera_screen.buffer_width * ZFIX_BOTTOM;
 339 
 340     if (idx < (unsigned)camera_screen.buffer_width * ZFIX_TOP) return(cur_buf_top[idx]);
 341     if (idx >= a && idx < (unsigned)camera_screen.buffer_size) return(cur_buf_bot[idx - a]);
 342     return (COLOR_TRANSPARENT);
 343 }
 344 
 345 //-------------------------------------------------------------------
 346 // This function calculates the Zebra overlay for cameras where the screen buffer width
 347 // is equivalent to the CHDK virtual screen width. For older cameras where the screen
 348 // width is 360 pixels (or 480 for wide screen).
 349 static int draw_zebra_no_aspect_adjust(int mrec, unsigned int f, color *cls) {
 350     int v, s, x, y, over;
 351     static int need_restore=0;
 352     int viewport_height;
 353     int zebra_drawn=0;
 354 
 355     unsigned bWide = 1; // if wide (16:9) or standard (4:3) aspect ratio (but 1 in cameras that only have 4:3)
 356     unsigned aspOffset = 0; // offset to add to x-coord (or buffer address) when drawing zebra
 357 
 358     if (camera_screen.has_variable_aspect && camera_info.props.aspect_ratio)
 359     {
 360         if (shooting_get_prop(camera_info.props.aspect_ratio) == 0) // standard requires x-shift to overlay drawing
 361         {
 362             bWide = 0;
 363             //aspOffset = (camera_screen.width - (camera_screen.width * 12 / 16)) / 2; // = actual calculation, simplified below
 364             aspOffset = camera_screen.width / 8; // half of the difference in width between equal height 16:9 and 4:3 screens, = black bar width
 365         }
 366     }
 367 
 368     viewport_height = vid_get_viewport_height();
 369 
 370     // if not in no-zebra phase of blink mode zebra, draw zebra to buf[]
 371     if (f) {
 372         int step_x, step_v;
 373         over = 255-conf.zebra_over;
 374         if (conf.zebra_multichannel) {step_x=2; step_v=6;} else {step_x=1; step_v=3;}
 375         s = aspOffset;
 376         for (y=1, v=0; y<=viewport_height; ++y) {
 377             for (x=0; x<camera_screen.width; x+=step_x, s+=step_x, v+=step_v) {
 378                 register int yy, uu, vv;
 379                 int sel;
 380 
 381                 if (!bWide && (x + aspOffset >= camera_screen.width - aspOffset)) continue; // do not draw "outside screen" 
 382 
 383                 yy = img_buf[v+1];
 384                 if (conf.zebra_multichannel) {
 385                     uu = (signed char)img_buf[v];
 386                     vv = (signed char)img_buf[v+2];
 387                     sel=0;
 388                     if (!((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f)) {
 389                         if (clip8(((yy<<12) +           vv*5743 + 2048)>>12)>over) sel  = 4; // R
 390                         if (clip8(((yy<<12) - uu*1411 - vv*2925 + 2048)>>12)>over) sel |= 2; // G
 391                         if (clip8(((yy<<12) + uu*7258           + 2048)>>12)>over) sel |= 1; // B
 392                     }
 393                     buf[s]=buf[s+1]=cls[sel];
 394                 }
 395                 else if (((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f)) buf[s]=COLOR_TRANSPARENT;
 396                 else buf[s]=(yy>over)?cl_over:(yy<conf.zebra_under)?cl_under:COLOR_TRANSPARENT;
 397                 if (buf[s] != COLOR_TRANSPARENT && !zebra_drawn) zebra_drawn = 1;
 398                 if (mrec) {
 399                     // draw Canon OSD to buf[] if in REC mode
 400                     if(get_cur_buf(s)!=COLOR_TRANSPARENT) buf[s]=get_cur_buf(s); 
 401                     if(conf.zebra_multichannel && get_cur_buf(s+1)!=COLOR_TRANSPARENT) buf[s+1]=get_cur_buf(s+1); 
 402                 }
 403             }
 404             s+=camera_screen.buffer_width-camera_screen.width;
 405             if (y*camera_screen.height/viewport_height == (s+camera_screen.buffer_width)/camera_screen.buffer_width) {
 406                 memcpy(buf+s, buf+s-camera_screen.buffer_width, camera_screen.buffer_width);
 407                 s+=camera_screen.buffer_width;
 408             }
 409         }
 410         if (!zebra_drawn) f=0;
 411     }
 412     // if blink mode is in no-zebra phase OR if there was no over/underexposed pixels to draw zebra on
 413     if (!f) {
 414         // if zebra was drawn during previous call of this function
 415         if (need_restore) {
 416             if (conf.zebra_restore_screen || conf.zebra_restore_osd) {
 417                 gui_set_need_restore();
 418             } else {  // clear buf[] of zebra, only leave Canon OSD
 419                 if (mrec) { // REC mode
 420                     // copy rescued Canon OSD to buf[] top/bottom parts and fill center with transparent color:
 421                     memcpy(buf, cur_buf_top, camera_screen.buffer_width * ZFIX_TOP);
 422                     memcpy(buf + buffer_size - camera_screen.buffer_width * ZFIX_BOTTOM, cur_buf_bot, camera_screen.buffer_width * ZFIX_BOTTOM);
 423                     for (s = camera_screen.buffer_width*ZFIX_TOP; s < buffer_size-camera_screen.buffer_width*ZFIX_BOTTOM; s++) {
 424                         buf[s]=COLOR_TRANSPARENT;
 425                     }
 426                 } else { // Not REC mode
 427                     // No Canon OSD restore, fill buf[] with transparent color:
 428                     memset(buf, COLOR_TRANSPARENT, buffer_size);
 429                 }
 430                 disp_zebra();
 431             }
 432             need_restore=0;
 433         }
 434         return !(conf.zebra_restore_screen && conf.zebra_restore_osd);
 435         // if zebra was drawn
 436     } else {
 437         disp_zebra();
 438 
 439         need_restore=1;
 440         return 1;
 441     }
 442     return 0;
 443 }
 444 
 445 //-------------------------------------------------------------------
 446 int gui_osd_draw_zebra(int show)
 447 {
 448     unsigned int f;
 449 
 450     if (!gui_osd_zebra_init(show))
 451         return 0;
 452 
 453     color cls[] = {
 454         COLOR_TRANSPARENT,
 455         COLOR_BLUE,
 456         COLOR_GREEN,
 457         COLOR_CYAN,
 458         COLOR_RED,
 459         COLOR_MAGENTA,
 460         COLOR_YELLOW,
 461         COLOR_BLACK
 462     };
 463 
 464     img_buf = vid_get_viewport_active_buffer();
 465     if (!img_buf) return 0;
 466 
 467     if (timer==0)
 468     {
 469         draw_guard_pixel();
 470         timer = 1;
 471         return 0;
 472     }
 473 
 474     if (timer==1)
 475     {
 476         int ready;
 477         static int n=0;
 478         if (!camera_info.state.mode_rec) ready=1;
 479         else get_property_case(camera_info.props.shooting, &ready, 4);
 480         n=draw_guard_pixel(); // will be 0 in PLAY mode, should be 1 or 2 in REC mode.
 481         if(!ready) return 0;
 482         if (cur_buf_top)
 483         {
 484             // rescue Canon OSD from scr_buf to cur_buf_top and _bot:
 485             if (n==1) {
 486                 memcpy(cur_buf_top, scr_buf, camera_screen.buffer_width*ZFIX_TOP);
 487                 memcpy(cur_buf_bot, scr_buf + camera_screen.buffer_size - camera_screen.buffer_width*ZFIX_BOTTOM, camera_screen.buffer_width*ZFIX_BOTTOM);
 488             }
 489             else {
 490                 memcpy(cur_buf_top, scr_buf + camera_screen.buffer_size, camera_screen.buffer_width*ZFIX_TOP);
 491                 memcpy(cur_buf_bot, scr_buf + 2*camera_screen.buffer_size - camera_screen.buffer_width*ZFIX_BOTTOM, camera_screen.buffer_width*ZFIX_BOTTOM);
 492             }
 493         }
 494     }
 495     ++timer;
 496 
 497     switch (conf.zebra_mode)
 498     {
 499         case ZEBRA_MODE_ZEBRA_1:    f = 4;          break;
 500         case ZEBRA_MODE_ZEBRA_2:    f = 8;          break;
 501         case ZEBRA_MODE_SOLID:      f = 1;          break;
 502         case ZEBRA_MODE_BLINKED_1:  f = timer&1;    break;
 503         case ZEBRA_MODE_BLINKED_3:  f = timer&4;    break;
 504         case ZEBRA_MODE_BLINKED_2:  
 505         default:                    f = timer&2;    break;
 506     }
 507 
 508     if (camera_screen.zebra_aspect_adjust)
 509         return draw_zebra_aspect_adjust(camera_info.state.mode_rec,f,cls);    // For newer cameras with 720/960 pixel wide screen
 510     else
 511         return draw_zebra_no_aspect_adjust(camera_info.state.mode_rec,f,cls); // For older cameras with 360/480 pixel wide screen
 512 }
 513 #else // THUMB_FW
 514 //digic 6 code below here
 515 
 516 typedef struct
 517 {
 518     unsigned int yuv;
 519     unsigned int op;
 520 } rawcolor_s;
 521 
 522 rawcolor_s clr[8];
 523 
 524 rawcolor_s rawcl_overunder[3];
 525 
 526 // D6 version draws directly, no allocs
 527 static void gui_osd_zebra_free()
 528 {
 529     buf = NULL;
 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 (!buf)
 554         {
 555             timer = 0;
 556             scr_buf = vid_get_bitmap_fb();
 557             buf = scr_buf;
 558         }
 559         int f;
 560         for (f=0; f<8; f++)
 561         {
 562             clr[f].yuv = color_to_rawpx(cls[f], &(clr[f].op));
 563         }
 564         rawcl_overunder[1].yuv = color_to_rawpx(cl_under, &(rawcl_overunder[1].op));
 565         rawcl_overunder[0].yuv = color_to_rawpx(cl_over, &(rawcl_overunder[0].op));
 566         rawcl_overunder[2].yuv = color_to_rawpx(COLOR_TRANSPARENT, &(rawcl_overunder[2].op));
 567     }
 568     else
 569     {
 570         if (buf) // if zebra was previously on, restore
 571         {
 572             gui_set_need_restore();
 573         }
 574         gui_osd_zebra_free();
 575     }
 576     return (buf != NULL);
 577 }
 578 
 579  
 580 
 581 //-------------------------------------------------------------------
 582 int draw_guard_pixel() {
 583     unsigned char* buffer1 = vid_get_bitmap_fb()+camera_screen.buffer_size/2;
 584     unsigned char* buffer2 = buffer1+camera_screen.buffer_size;
 585     int has_disappeared=0;
 586 
 587     if (*buffer1!=COLOR_GREEN) has_disappeared=1;
 588     if (*buffer2!=COLOR_GREEN) has_disappeared=2;
 589     *buffer1 = *buffer2 = COLOR_GREEN;
 590     return has_disappeared;
 591 }
 592 
 593 //-------------------------------------------------------------------
 594 // neither OSD nor histogram can be drawn over zebra
 595 // draw_set_draw_proc() is not respected by the current D6 drawing code anyway
 596 static void gui_osd_draw_zebra_osd() {
 597     switch (conf.zebra_draw_osd) {
 598         case ZEBRA_DRAW_NONE:
 599             break;
 600         case ZEBRA_DRAW_OSD:
 601             if (conf.show_osd) {
 602                 //draw_set_draw_proc(draw_dblpixel_raw);
 603                // gui_draw_osd_elements(0,1);
 604                 //draw_set_draw_proc(NULL);
 605             }
 606             /* no break here */
 607         case ZEBRA_DRAW_HISTO:
 608         default:
 609             //draw_set_draw_proc(draw_dblpixel_raw);
 610             //libhisto->gui_osd_draw_histo(0);
 611             //draw_set_draw_proc(NULL);
 612             break;
 613     }
 614 }
 615 
 616 //-------------------------------------------------------------------
 617 static void disp_zebra()
 618 {
 619     // draw CHDK osd and histogram to buf[] (if enabled in config)
 620 
 621     gui_osd_draw_zebra_osd();
 622 }
 623 
 624 //-------------------------------------------------------------------
 625 // CHDK uses a virtual screen size of 360 x 240 pixels (480x240 for wide screen models)
 626 static int draw_zebra_no_aspect_adjust(int mrec, unsigned int f)
 627 {
 628     int x, y, over;
 629     unsigned int v, bitmap_byte;
 630     static int need_restore=0;
 631     int viewport_height;
 632     int viewport_width; 
 633     int viewport_byte_width;
 634 
 635     int viewport_xoffset;    // used when image size != viewport size
 636     int viewport_yoffset;    // used when image size != viewport size
 637     int zebra_drawn=0;
 638     static int d_cnt =0;
 639     d_cnt++;
 640 
 641     viewport_height = vid_get_viewport_height();
 642     viewport_width = vid_get_viewport_width(); 
 643     viewport_byte_width = vid_get_viewport_byte_width();
 644     viewport_xoffset = vid_get_viewport_display_xoffset(); //columns
 645     viewport_yoffset = vid_get_viewport_display_yoffset();
 646 
 647     // if not in no-zebra phase of blink mode zebra, draw zebra  
 648     if (f)
 649     {
 650 
 651         if (viewport_yoffset > 0)
 652         {
 653             // clear top & bottom areas of buffer if image height if smaller than viewport
 654         }
 655         int step_x;
 656         over = 255-conf.zebra_over;
 657     // start with all transparent, set the whole LCD causes too much blink
 658     //    set_transparent(0,buffer_size/2); 
 659         step_x = 2; //anything larger makes solid consist of alternating columns...
 660 
 661         for (y=0; y<viewport_height ; ++y)
 662         {
 663 //e.g. on SX60hs LCD is 640x480
 664 // 
 665 // 16:9     f:8 vh:360 vw:640 vbw:1280 vxo:0 vyo:60
 666 //1x1        f:8 vh:480 vw:480 vbw:1280 vxo:80 vyo:0
 667             //this can be made more efficient, but for now want clarity 
 668             for (x=0; x<viewport_width; x+=step_x)
 669             {
 670                 register int y1, uu, vv;
 671                 v = y*(viewport_byte_width)  + x + x ; //v is the byte number in img-buf  0...480,480+320...960,
 672                 bitmap_byte = (y + viewport_yoffset) * viewport_byte_width + 2*(x + viewport_xoffset);
 673                 unsigned int ibuf = *(unsigned int*)(&img_buf[v&0xfffffffc]);
 674                 vv =(signed char)((ibuf&0xff)-128);
 675                 uu =(signed char)(((ibuf>>16)&0xff)-128);
 676                 y1 = (unsigned char)((ibuf>>8)&0xff);
 677 
 678                 int sel = 0;
 679                 if (conf.zebra_multichannel)
 680                 {
 681                     // for simplicity check only first pixel y1
 682                     sel = 0;
 683                     if (!((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f))
 684                     {
 685                         if (clip8(((y1<<12) +           vv*5743 + 2048)>>12)>over) sel  = 4; // R
 686                         if (clip8(((y1<<12) - uu*1411 - vv*2925 + 2048)>>12)>over) sel |= 2; // G
 687                         if (clip8(((y1<<12) + uu*7258           + 2048)>>12)>over) sel |= 1; // B
 688                     }
 689                     //set two pixels (4 bytes ) to color sel
 690                     if (sel > 0 )
 691                     {
 692                         draw_dblpixel_raw(bitmap_byte,  clr[sel].yuv, clr[sel].op);
 693                         zebra_drawn = 1;
 694                     }
 695                     else
 696                     {
 697                         draw_dblpixel_raw(bitmap_byte, 0x800080, 0);
 698                     }
 699                 }
 700                 else if (((conf.zebra_mode == ZEBRA_MODE_ZEBRA_1 || conf.zebra_mode == ZEBRA_MODE_ZEBRA_2) && (y-x-timer)&f))
 701                 {
 702                     // set two pixels transparent 
 703                     draw_dblpixel_raw(bitmap_byte, 0x800080, 0); 
 704                 }
 705                 else
 706                 {
 707                     // if y1 is over or under
 708                     // set two pixels to under color
 709                     sel = (y1>over)?0:(y1<conf.zebra_under)?1:2;
 710                      //set two pixels (4 bytes ) to either overexposed, underexposed or transparent color
 711                     draw_dblpixel_raw(bitmap_byte, rawcl_overunder[sel].yuv, rawcl_overunder[sel].op);
 712                     if (sel < 2) {
 713                         zebra_drawn = 1;
 714                     }
 715                 }
 716             }
 717         }
 718         if (!zebra_drawn) f=0;
 719     }
 720     // if blink mode is in no-zebra phase OR if there was no over/underexposed pixels to draw zebra on
 721     if (!f)
 722     {
 723         // if zebra was drawn during previous call of this function
 724         if (need_restore)
 725         {
 726             if (conf.zebra_restore_screen || conf.zebra_restore_osd)
 727             {
 728                 gui_set_need_restore();
 729             }
 730             else
 731             {
 732                 // clear buf[] of zebra, only leave Canon OSD
 733                 if (!mrec)
 734                 {
 735                     // Not REC mode
 736                     set_transparent(0, buffer_size/2);  //blink
 737                 }
 738                 disp_zebra();
 739             }
 740             need_restore=0;
 741         }
 742         return !(conf.zebra_restore_screen && conf.zebra_restore_osd);
 743         // if zebra was drawn
 744     }
 745     else
 746     {
 747         disp_zebra();
 748         need_restore=1;
 749         return 1;
 750     }
 751     return 0;
 752 }
 753 
 754 //-------------------------------------------------------------------
 755 int gui_osd_draw_zebra(int show)
 756 {
 757     unsigned int f;
 758 
 759     if (!gui_osd_zebra_init(show))
 760         return 0;
 761 
 762     img_buf = vid_get_viewport_active_buffer();
 763     if (!img_buf) return 0;
 764     // img_buf += vid_get_viewport_image_offset(); //always zero anyway
 765 
 766     if (timer==0)
 767     {
 768         draw_guard_pixel();
 769         timer = 1;
 770         return 0;
 771     }
 772 
 773     if (timer==1)
 774     {
 775         int ready;
 776         if (!camera_info.state.mode_rec) ready=1;
 777         else get_property_case(camera_info.props.shooting, &ready, 4);
 778         draw_guard_pixel(); // will be 0 in PLAY mode, should be 1 or 2 in REC mode.
 779         if(!ready) return 0;
 780 
 781     }
 782     ++timer;
 783 
 784     switch (conf.zebra_mode)
 785     {
 786         case ZEBRA_MODE_ZEBRA_1:    f = 4;          break;
 787         case ZEBRA_MODE_ZEBRA_2:    f = 8;          break;
 788         case ZEBRA_MODE_SOLID:      f = 1;          break;
 789         case ZEBRA_MODE_BLINKED_1:  f = timer&1;    break;
 790         case ZEBRA_MODE_BLINKED_3:  f = timer&4;    break;
 791         case ZEBRA_MODE_BLINKED_2:  
 792         default:                    f = timer&2;    break;
 793     }
 794 
 795     return draw_zebra_no_aspect_adjust(camera_info.state.mode_rec,f);
 796 }
 797 
 798 #endif // THUMB_FW
 799 
 800 // =========  MODULE INIT =================
 801 
 802 /***************** BEGIN OF AUXILARY PART *********************
 803   ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
 804  **************************************************************/
 805 
 806 //---------------------------------------------------------
 807 // PURPOSE: Finalize module operations (close allocs, etc)
 808 // RETURN VALUE: 0-ok, 1-fail
 809 //---------------------------------------------------------
 810 int _module_unloader()
 811 {
 812     gui_osd_zebra_free();
 813     return 0;
 814 }
 815 
 816 int _module_can_unload()
 817 {
 818     return conf.zebra_draw == 0;
 819 }
 820 
 821 /******************** Module Information structure ******************/
 822 
 823 libzebra_sym _libzebra =
 824 {
 825     {
 826          0, _module_unloader, _module_can_unload, 0, 0
 827     },
 828 
 829     gui_osd_draw_zebra
 830 };
 831 
 832 ModuleInfo _module_info =
 833 {
 834     MODULEINFO_V1_MAGICNUM,
 835     sizeof(ModuleInfo),
 836     ZEBRA_VERSION,                              // Module version
 837 
 838     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,                       // Requirements of CHDK version
 839     ANY_PLATFORM_ALLOWED,               // Specify platform dependency
 840 
 841     (int32_t)"Zebra Overlay (dll)",
 842     MTYPE_EXTENSION,
 843 
 844     &_libzebra.base,
 845 
 846     CONF_VERSION,               // CONF version
 847     CAM_SCREEN_VERSION,         // CAM SCREEN version
 848     ANY_VERSION,                // CAM SENSOR version
 849     CAM_INFO_VERSION,           // CAM INFO version
 850 
 851     0,
 852 };
 853 
 854 /*************** END OF AUXILARY PART *******************/

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