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

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