source: branches/reyalp-flt/core/edgeoverlay.c @ 1511

Revision 1511, 27.3 KB checked in by philmoz, 17 months ago (diff)

Merge recent changes from main trunk to reyalp-flt branch.

  • Property svn:eol-style set to native
Line 
1#include "platform.h"
2
3#include "edgeoverlay.h"
4#include "conf.h"
5#include "keyboard.h"
6#include "stdlib.h"
7#include "gui_draw.h"
8#include "bitvector.h"
9#include "module_exportlist.h"
10
11
12// the way we save edge overlays on their own...
13#define EDGE_FILE_PREFIX "EDG_"
14#define EDGE_FILE_FORMAT EDGE_FILE_PREFIX "%04d.edg"
15#define EDGE_SLICES     2
16
17int* conf_edge_overlay_filter;
18color* conf_osd_color;
19int* conf_edge_overlay_zoom;
20int* conf_edge_overlay_thresh;
21color* conf_edge_overlay_color;
22int* conf_edge_overlay_pano;
23int* conf_edge_overlay_pano_overlap;
24int* conf_edge_overlay_show;
25int* conf_edge_overlay_play;
26
27typedef enum _edge_fsm_state
28{
29    EDGE_LIVE = 0,
30    EDGE_FROZEN
31} edge_fsm_state_t;
32
33static edge_fsm_state_t fsm_state = EDGE_LIVE;
34static bit_vector_t* edgebuf = NULL;
35static int xoffset = 0, yoffset = 0;
36static unsigned char* smbuf = NULL;
37
38static int slice = 0;           // the current slice of the frame we are calculating/drawing
39static int slice_height;        // the height of a single slice
40
41static int viewport_byte_width; // width in bytes of one viewport line ??
42static int viewport_yscale;     // Y multiplier (for cameras with 480 pixel high viewports)
43static int viewport_height;     // height of visible / used area of viewport
44static int viewport_width;      // width of visible / used area of viewport (in 3 byte units)
45static int viewport_xoffset;    // used when image size != viewport size (e.g. wide screen image on 4:3 LCD)
46static int viewport_yoffset;    // used when image size != viewport size (e.g. wide screen image on 4:3 LCD)
47
48static void get_viewport_size()
49{
50    viewport_height = vid_get_viewport_height()-EDGE_HMARGIN*2; //don't trace bottom lines
51    viewport_width = vid_get_viewport_width();
52    viewport_byte_width = vid_get_viewport_byte_width();
53    viewport_yscale = vid_get_viewport_yscale();
54
55        viewport_xoffset = vid_get_viewport_xoffset();
56        viewport_yoffset = vid_get_viewport_yoffset();
57
58    slice_height = viewport_height / EDGE_SLICES;
59}
60
61static void ensure_allocate_imagebuffer()
62{
63    if(edgebuf == NULL)
64    {
65        edgebuf = bv_create(viewport_height * viewport_width, 1);
66        if (edgebuf != NULL)
67            memset(edgebuf->ptr, 0, edgebuf->ptrLen);
68    }
69    if (*conf_edge_overlay_filter && (smbuf == NULL))
70    {
71        smbuf = (unsigned char*)malloc(viewport_byte_width*3);
72        if (smbuf != NULL)
73            memset(smbuf, 0, viewport_byte_width*3);
74        else
75        {
76            // Disable filtering if we do not have enough memory for it
77            *conf_edge_overlay_filter = 0;
78        }
79    }
80}
81
82static void reset_edge_overlay()
83{
84    if (smbuf != NULL)
85    {
86        free(smbuf);
87        smbuf = NULL;
88    }
89
90    if (edgebuf != NULL)
91    {
92        draw_restore();     // Refresh display to restore Canon OSD
93        bv_free(edgebuf);
94        edgebuf = NULL;
95    }
96
97    fsm_state = EDGE_LIVE;
98    slice = 0;
99}
100
101static int is_buffer_ready()
102{
103    if (edgebuf == NULL) return 0;
104    if (edgebuf->ptr == NULL) return 0; // this should never happen, but it does not hurt to check
105    return 1;
106}
107
108// scans a filename for the number of the edge detection file it contains
109static int get_edge_file_num(const char* fn)
110{
111    int num = 0;
112    if( strncmp(fn,EDGE_FILE_PREFIX,sizeof(EDGE_FILE_PREFIX)-1) == 0 )
113    {
114        // has the correct beginning at least, now try to read as a number...
115        fn += sizeof(EDGE_FILE_PREFIX);
116        while( *fn == '0' ) // skip leading 0s
117        {
118            ++fn;
119        }
120        while( isdigit(*fn) )
121        {
122            num *= 10;
123            num += *fn - '0';
124            ++fn;
125        }
126        // ignore anything else after it, that is like the ending etc.
127    }
128    return num;
129}
130
131// saves the actual active overlay data to a file.
132void save_edge_overlay(void)
133{
134
135    char fn[64];
136    char msg[64];
137    FILE *fd;
138    STD_DIR* d;
139    int fnum = 0;
140    int fr = 0;
141    int zoom = 0;
142    struct STD_dirent* de;
143    static struct utimbuf t;
144    // nothing to save? then dont save
145
146    if( !is_buffer_ready() )
147    {
148        draw_string(0, 0, "No overlay to save.", *conf_osd_color);
149        return;
150    }
151
152    zoom = shooting_get_zoom();
153
154    // first figure out the most appropriate filename to use
155    d = safe_opendir(EDGE_SAVE_DIR);
156    if( ! d )
157    {
158        return;
159    }
160
161    while( (de = safe_readdir(d)) )
162    {
163        fr = get_edge_file_num(de->d_name);
164        if( fr > fnum )
165        {
166            fnum = fr;
167        }
168    }
169    ++fnum; // the highest is set, we use the next one
170    get_viewport_size();
171    // open the right file
172    sprintf(fn, EDGE_SAVE_DIR "/" EDGE_FILE_FORMAT, fnum );
173    fd = fopen(fn, "wb");
174    if(fd !=NULL)
175    {
176        // write the data
177        fwrite(edgebuf->ptr,edgebuf->ptrLen,1,fd);
178        fwrite(&zoom,sizeof(zoom),1,fd);
179        fclose(fd);
180        t.actime = t.modtime = time(NULL);
181        utime(fn, &t);
182        sprintf(msg, "Saved as %s",fn);
183        draw_string(0, 0, msg, *conf_osd_color);
184    }
185    safe_closedir(d);
186}
187
188// load the edge overlay from a file
189void load_edge_overlay(const char* fn)
190{
191    FILE *fd;
192    int zoom;
193
194    get_viewport_size();
195    ensure_allocate_imagebuffer( );
196    fd = fopen(fn,"rb");
197    if( fd != NULL )
198    {
199        int ret = fread(edgebuf->ptr,edgebuf->ptrLen,1,fd);
200        int ret2 = fread (&zoom,sizeof(zoom),1,fd);
201        fclose(fd);
202        if( (ret == 1) && (ret2 == 1) )
203        {
204            fsm_state = EDGE_FROZEN;    // switch to "edge overlay frozen"-mode
205            if (*conf_edge_overlay_zoom)
206            {
207                shooting_set_zoom(zoom);
208            }
209        }
210    }
211}
212
213static void average_filter_row(const unsigned char* ptrh1,  // previous row
214                               unsigned char* smptr,        // write results here
215                               int x, int x_max)
216{
217    const unsigned char* ptrh2 = ptrh1 + viewport_byte_width*viewport_yscale;  // current row
218    const unsigned char* ptrh3 = ptrh2 + viewport_byte_width*viewport_yscale;  // next row
219
220    for (; x<x_max; x+=6)
221    {
222        *(smptr + x + 1) = (*(ptrh1 + x - 1) +
223                            *(ptrh1 + x + 1) +
224                            *(ptrh1 + x + 3) +
225
226                            *(ptrh2 + x - 1) +
227                            *(ptrh2 + x + 1) +
228                            *(ptrh2 + x + 3) +
229
230                            *(ptrh3 + x - 1) +
231                            *(ptrh3 + x + 1) +
232                            *(ptrh3 + x + 3)) / 9u;
233
234        *(smptr + x + 3) = (*(ptrh1 + x + 1) +
235                            *(ptrh1 + x + 3) +
236                            *(ptrh1 + x + 4) +
237
238                            *(ptrh2 + x + 1) +
239                            *(ptrh2 + x + 3) +
240                            *(ptrh2 + x + 4) +
241
242                            *(ptrh3 + x + 1) +
243                            *(ptrh3 + x + 3) +
244                            *(ptrh3 + x + 4)) / 9u;
245
246        *(smptr + x + 4) = (*(ptrh1 + x + 3) +
247                            *(ptrh1 + x + 4) +
248                            *(ptrh1 + x + 5) +
249
250                            *(ptrh2 + x + 3) +
251                            *(ptrh2 + x + 4) +
252                            *(ptrh2 + x + 5) +
253
254                            *(ptrh3 + x + 3) +
255                            *(ptrh3 + x + 4) +
256                            *(ptrh3 + x + 5)) / 9u;
257
258        *(smptr + x + 5) = (*(ptrh1 + x + 4) +
259                            *(ptrh1 + x + 5) +
260                            *(ptrh1 + x + 7) +
261
262                            *(ptrh2 + x + 4) +
263                            *(ptrh2 + x + 5) +
264                            *(ptrh2 + x + 7) +
265
266                            *(ptrh3 + x + 4) +
267                            *(ptrh3 + x + 5) +
268                            *(ptrh3 + x + 7)) / 9u;
269    }
270
271    // copy 2nd last column to last column to prevent vertical stripe artifact.
272    smptr[x+1] = smptr[x-5];
273    smptr[x+3] = smptr[x-3];
274    smptr[x+4] = smptr[x-2];
275    smptr[x+5] = smptr[x-1];
276}
277
278// Sobel edge detector
279static int calc_edge_overlay()
280{
281    int shutter_fullpress = kbd_is_key_pressed(KEY_SHOOT_FULL);
282
283    const int bPlayMode = (mode_get() & MODE_MASK) == MODE_PLAY;
284    const unsigned char* img = bPlayMode ? vid_get_viewport_fb_d() :  vid_get_viewport_fb();
285    const unsigned char*  ptrh1 = NULL;    // previous pixel line
286    const unsigned char*  ptrh2 = NULL;    // current pixel line
287    const unsigned char*  ptrh3 = NULL;    // next pixel line
288    unsigned char*  smptr = NULL;    // pointer to line in smbuf
289    int x, y, xdiv3;
290    int conv1, conv2;
291
292    const int y_min = viewport_yoffset + EDGE_HMARGIN+ slice   *slice_height;
293    const int y_max = viewport_yoffset + EDGE_HMARGIN+(slice+1)*slice_height;
294    const int x_min = viewport_xoffset*3 + 6;
295    const int x_max = (viewport_width + viewport_xoffset - 2) * 3;
296
297    xoffset = 0;
298    yoffset = 0;
299
300    // Reserve buffers
301    ensure_allocate_imagebuffer();
302    if( !is_buffer_ready() ) return 0;
303
304    // In every 6 bytes the Y of four pixels are described in the
305    // viewport (UYVYYY format). For edge detection we only
306    // consider the second in the current and the first
307    // in the next pixel.
308
309    // Clear all edges in the current slice
310    int compressed_slice = edgebuf->ptrLen / EDGE_SLICES;
311    memset(edgebuf->ptr + slice*compressed_slice, 0, compressed_slice);
312
313    if (*conf_edge_overlay_filter)
314    {
315        // Prefill smbuf with three lines of avergae-filtered data.
316        // This looks much more complex then it actually is.
317        // We really are just summing up nine pixels in a 3x3 box
318        // and averaging the current pixel based on them. And
319        // we do it 4 bytes at a time because of the UYVYYY format.
320        for (y = -1; y <= 1; ++y)
321        {
322            shutter_fullpress |= kbd_is_key_pressed(KEY_SHOOT_FULL);
323
324            ptrh1 = img + (y_min+y-1) * viewport_byte_width*viewport_yscale;
325            smptr = smbuf + (y+1) * viewport_byte_width;
326
327            average_filter_row(ptrh1, smptr, x_min, x_max);
328        }
329    }
330
331    for (y = y_min; y < y_max; ++y)
332    {
333        shutter_fullpress |= kbd_is_key_pressed(KEY_SHOOT_FULL);
334
335        if (*conf_edge_overlay_filter)
336        {
337            // We need to shift up our smbuf one line,
338            // and fill in the last line (which now empty)
339            // with average-filtered data from img.
340            // By storing only three lines of smoothed picture
341            // in memory, we save memory.
342
343            // Shift
344            memcpy(smbuf, smbuf+viewport_byte_width, viewport_byte_width*2);
345
346            // Filter new line
347            ptrh1 = img + y * viewport_byte_width*viewport_yscale;
348            smptr = smbuf + 2 * viewport_byte_width;
349            average_filter_row(ptrh1, smptr, x_min, x_max);
350
351            ptrh1 = smbuf;
352        }
353        else
354        {
355            ptrh1 = img + (y-1) * viewport_byte_width*viewport_yscale;
356        }
357        ptrh2 = ptrh1 + viewport_byte_width*viewport_yscale;
358        ptrh3 = ptrh2 + viewport_byte_width*viewport_yscale;
359
360        // Now we do sobel on the current line
361
362        for (x = x_min, xdiv3 = x_min/3; x < x_max; x += 6, xdiv3 += 2)
363        {
364            // convolve vert (second Y)
365            conv1 = *(ptrh1 + x + 1) * ( 1) +
366                    *(ptrh1 + x + 4) * (-1) +
367
368                    *(ptrh2 + x + 1) * ( 2) +
369                    *(ptrh2 + x + 4) * (-2) +
370
371                    *(ptrh3 + x + 1) * ( 1) +
372                    *(ptrh3 + x + 4) * (-1);
373            if  (conv1 < 0)     // abs()
374                conv1 = -conv1;
375
376            // convolve vert (first Y of next pixel)
377            conv2 = *(ptrh1 + x + 1) * ( 1) +
378                    *(ptrh1 + x + 3) * ( 2) +
379                    *(ptrh1 + x + 4) * ( 1) +
380
381                    *(ptrh3 + x + 1) * (-1) +
382                    *(ptrh3 + x + 3) * (-2) +
383                    *(ptrh3 + x + 4) * (-1);
384            if  (conv2 < 0)     // abs()
385                conv2 = -conv2;
386
387            if (conv1 + conv2 > *conf_edge_overlay_thresh)
388            {
389                bv_set(edgebuf, (y-viewport_yoffset-EDGE_HMARGIN)*viewport_width + xdiv3, 1);
390            }
391
392            // Do it once again for the next 'pixel'
393
394            // convolve vert (second Y)
395            conv1 = *(ptrh1 + x + 5) * ( 1) +
396                    *(ptrh1 + x + 9) * (-1) +
397
398                    *(ptrh2 + x + 5) * ( 2) +
399                    *(ptrh2 + x + 9) * (-2) +
400
401                    *(ptrh3 + x + 5) * ( 1) +
402                    *(ptrh3 + x + 9) * (-1);
403            if  (conv1 < 0)     // abs()
404                conv1 = -conv1;
405
406            // convolve vert (first Y of next pixel)
407            conv2 = *(ptrh1 + x + 5) * ( 1) +
408                    *(ptrh1 + x + 7) * ( 2) +
409                    *(ptrh1 + x + 9) * ( 1) +
410
411                    *(ptrh3 + x + 5) * (-1) +
412                    *(ptrh3 + x + 7) * (-2) +
413                    *(ptrh3 + x + 9) * (-1);
414            if  (conv2 < 0)     // abs()
415                conv2 = -conv2;
416
417            if (conv1 + conv2 > *conf_edge_overlay_thresh)
418            {
419                bv_set(edgebuf, (y-viewport_yoffset-EDGE_HMARGIN)*viewport_width + xdiv3+1, 1);
420            }
421        }   // for x
422    }   // for y
423
424
425//  For an even more improved edge overlay, enabling the following lines will
426//  post-filter the results of the edge detection, removing false edge 'dots'
427//  from the display. However, the speed hit is large. In the developer's opinion
428//  this code is not needed, but if you want that additional quality and do not
429//  care so much about performance, you can enable it.
430//
431//    if (*conf_edge_overlay_filter)
432//    {
433//        // Here we do basic filtering on the detected edges.
434//        // If a pixel is marked as edge but just a few of its
435//        // neighbors are also edges, then we assume that the
436//        // current pixel is just noise and delete the mark.
437//
438//        bit_vector_t* bv_tmp = bv_create(edgebuf->nElem, edgebuf->nBits);
439//        if (bv_tmp != NULL)
440//        {
441//            memset(bv_tmp->ptr, 0, bv_tmp->ptrLen);
442//
443//            for (y = 1; y < viewport_height-1; ++y)
444//            {
445//                shutter_fullpress |= kbd_is_key_pressed(KEY_SHOOT_FULL);
446//
447//                for (x=12; x<(viewport_width - 4); ++x)
448//                {
449//                    int bEdge = bv_get(edgebuf, y*viewport_width + x);
450//                    if (bEdge)
451//                    {
452//                        // Count the number of neighbor edges
453//                        int sum =
454//                            bv_get(edgebuf, (y-1)*viewport_width + (x-1)) +
455//                            bv_get(edgebuf, (y-1)*viewport_width + (x)) +
456//                            bv_get(edgebuf, (y-1)*viewport_width + (x+1)) +
457//
458//                            bv_get(edgebuf, (y)*viewport_width + (x-1)) +
459////              bv_get(&edgebuf, (y)*viewport_width + (x)) + //  we only inspect the neighbors
460//                            bv_get(edgebuf, (y)*viewport_width + (x+1)) +
461//
462//                            bv_get(edgebuf, (y+1)*viewport_width + (x-1)) +
463//                            bv_get(edgebuf, (y+1)*viewport_width + (x)) +
464//                            bv_get(edgebuf, (y+1)*viewport_width + (x+1));
465//
466//                        if (!*conf_edge_overlay_show)
467//                        {
468//                            if (sum >= 5)    // if we have at least 5 neighboring edges
469//                                bv_set(bv_tmp, y*viewport_width + x, 1);   // keep the edge
470//                            // else
471//                            // there is no need to delete because the buffer is already zeroed
472//                        }
473//                    }
474//                }   // for x
475//            }   // for y
476//
477//            // Swap the filtered edge buffer for the real one
478//            bit_vector_t* swap_tmp = edgebuf;
479//            edgebuf = bv_tmp;
480//            bv_free(swap_tmp);
481//        }   // NULL-check
482//    }   // if filtering
483
484    return shutter_fullpress;
485}
486
487static int draw_edge_overlay()
488{
489    int shutter_fullpress = kbd_is_key_pressed(KEY_SHOOT_FULL);
490
491    int x, y;
492    int x_off, y_off;
493
494    const color cl = *conf_edge_overlay_color;
495    const int y_slice_min = viewport_yoffset+EDGE_HMARGIN+ slice   *slice_height;
496    const int y_slice_max = viewport_yoffset+EDGE_HMARGIN+(slice+1)*slice_height;
497    const int y_min = viewport_yoffset+EDGE_HMARGIN;
498    const int y_max = viewport_yoffset+EDGE_HMARGIN+viewport_height;
499    const int x_min = viewport_xoffset+2;
500    const int x_max = (viewport_width + viewport_xoffset - 2);
501
502    if( !is_buffer_ready() ) return 0;
503
504    for (y = y_slice_min; y < y_slice_max; ++y)
505    {
506        y_off = y + yoffset;
507       
508        shutter_fullpress |= kbd_is_key_pressed(KEY_SHOOT_FULL);
509
510        if ((unsigned)(y_off-y_min) < (y_max-y_min)) // is the same as ((y_off > y_min) && (y_off < y_max)) // do not draw outside of allowed area
511        {
512            const int y_edgebuf = (y-y_min) * viewport_width;
513
514            for (x = x_min; x < x_max; ++x)
515            {
516                x_off = x + xoffset;
517
518                if ((unsigned)(x_off-x_min) < (x_max-x_min)) // is the same as  ((x_off > x_min) && (x_off < x_max)) // do not draw outside of allowed area
519                {
520                    // Draw a pixel to the screen wherever we detected an edge.
521                    // If there is no edge based on the newest data, but there is one painted on the screen
522                    // from previous calls, delete it from the screen.
523                    const int aspect_correct_x_off = x_off;
524                    const int bEdge = bv_get(edgebuf, y_edgebuf + x);
525                    const int bDraw = bEdge || (draw_get_pixel(aspect_correct_x_off, y_off) == *conf_edge_overlay_color);
526                    const color cl = bEdge ? *conf_edge_overlay_color : 0;
527                    if (bEdge || bDraw)
528                        draw_pixel(aspect_correct_x_off, y_off, cl);
529                   
530                }
531            }   // for x
532        }
533    }   // for y
534
535
536    // Drawing the overlay is over.
537    // But as a finishing touch we clear up garbage on the screen
538    // by clearing those parts that the overlay has left.
539
540    if (xoffset != 0)
541    {
542        // Cleans up leftover from horizontal motion
543
544        const int x_min_c = (xoffset < 0) ? x_max + xoffset : x_min;
545        const int x_max_c = (xoffset > 0) ? x_min + xoffset : x_max;
546
547        for (y = y_min; y < y_max; ++y)
548        {
549            for (x = x_min_c; x < x_max_c; ++x)
550            {
551                const int aspect_correct_x = x;
552                if (draw_get_pixel(aspect_correct_x, y) == cl)  // if there is an edge drawn on the screen but there is no edge there based on the newest data, delete it from the screen
553                    draw_pixel(aspect_correct_x, y, 0 );
554            }
555        }
556    }
557
558    if (yoffset != 0)
559    {
560        // Cleans up leftover from vertical motion
561
562        const int y_min_c = (yoffset < 0) ? y_max + yoffset : y_min;
563        const int y_max_c = (yoffset > 0) ? y_min + yoffset : y_max;
564
565        for (y = y_min_c; y < y_max_c; ++y)
566        {
567            for (x = x_min; x < x_max; ++x)
568            {
569                const int aspect_correct_x = x;
570                if (draw_get_pixel(aspect_correct_x, y) == cl)  // if there is an edge drawn on the screen but there is no edge there based on the newest data, delete it from the screen
571                    draw_pixel(aspect_correct_x, y, 0 );
572            }
573        }
574    }
575
576    return shutter_fullpress;
577}
578
579static void set_offset_from_overlap()
580{
581    const int y_max = viewport_height;
582    const int x_max = (viewport_width - 2);
583
584    switch(*conf_edge_overlay_pano)
585    {
586    case 0:     // pano off
587        xoffset = 0;
588        yoffset = 0;
589        break;
590    case 1:     // pano from left to right
591        xoffset = -x_max*(100-*conf_edge_overlay_pano_overlap)/100;
592        break;
593    case 2:     // pano from top to bottom
594        yoffset = -y_max*(100-*conf_edge_overlay_pano_overlap)/100;
595        break;
596    case 3:     // pano from right to left
597        xoffset = x_max*(100-*conf_edge_overlay_pano_overlap)/100;
598        break;
599    case 4:     // pano from bottom to top
600        yoffset = y_max*(100-*conf_edge_overlay_pano_overlap)/100;
601        break;
602    case 5:     // free mode
603    default:
604        // free mode: change position with "ALT" and cursor
605        // nothing to do here.
606        break;
607    }
608}
609
610
611
612// Main edge overlay function.
613// It works by detecting edges using the Sobel operator
614// (calc_edgeoverlay()), the detected edges are then stored into an
615// array of 1-bit elements. A set bit indicates that there is an
616// edge and that it should be drawn onto the overlay.
617// When needed, the 1-bit edge buffer is drawn onto the screen
618// (dynamically decompressing it) using draw_edge_overlay().
619void edge_overlay()
620{
621    // Was the shutter fully pressed the last time we ran?
622    // We use this to make sure that the user has released
623    // the button before processing the next FullPress event.
624    // This prevents switching FSM states more than once
625    // per press.
626    static int bFullPress_prev = 0;
627
628    // Have we already started taking pictures in panorama mode?
629    // We use this variable to be able to detect if panorama
630    // mode has been turned off.
631    static int bPanoInProgress = 0;
632
633    // Precalculate some values to make the rest of the
634    // code easier to read.
635    int bFullPress = kbd_is_key_pressed(KEY_SHOOT_FULL);
636    const int bHalfPress = kbd_is_key_pressed(KEY_SHOOT_HALF);
637    const int bPlayMode = (mode_get() & MODE_MASK) == MODE_PLAY;
638    const int bPanoramaMode = (*conf_edge_overlay_pano != 0);
639    const int bNeedHalfPress = (*conf_edge_overlay_show != 1);
640    const int bDisplayInPlay = (*conf_edge_overlay_play == 1);
641    const int bGuiModeNone = (gui_get_mode() == GUI_MODE_NONE);
642    const int bGuiModeAlt = (gui_get_mode() == GUI_MODE_ALT);
643    const int bCanDisplay = (
644                                (!bPlayMode && (bHalfPress || !bNeedHalfPress)) ||   // we have a HalfPress in rec-mode
645                                ( bPlayMode && bDisplayInPlay)  // or we are in play-mode with the right settings
646                            );
647
648    if (bPanoInProgress && !bPanoramaMode)
649    {
650        // This means panorama mode has been recently
651        // turned off in the menu. So let's release
652        // Frozen mode for the user.
653        reset_edge_overlay();
654        bPanoInProgress = 0;
655    }
656
657    get_viewport_size();
658
659    // For just two states a state machine is not actually needed.
660    // But it is scalable in the future in case anybody
661    // wants to extend the functionality of edge overlay.
662    switch (fsm_state)
663    {
664    case EDGE_LIVE:
665    {
666        // In this state we assume no edge overlay in memory,
667        // but we are ready to create one if the user presses wishes so.
668
669        int bRealtimeUpdate = bCanDisplay && (bGuiModeAlt || bGuiModeNone);
670        if (bRealtimeUpdate)
671        {
672            // We try to detect button presses during the lengthy
673            // calculations.
674            bFullPress |= calc_edge_overlay();
675            bFullPress |= draw_edge_overlay();
676        }
677
678        int bSwitch2Frozen = bFullPress && !bFullPress_prev && bGuiModeNone;
679        if (bSwitch2Frozen)
680        {
681            // Switch to Frozen mode
682
683            // Make sure we have one whole consistent frame
684            for (slice = 0; slice < EDGE_SLICES; ++slice)
685                calc_edge_overlay();
686
687            set_offset_from_overlap();
688            fsm_state = EDGE_FROZEN;
689            bPanoInProgress = bPanoramaMode;
690        }
691
692        if (!bRealtimeUpdate && !bSwitch2Frozen)
693        {
694            // Nothing happens. So do nothing.
695            // Or rather, we could clean up if we are that bored.
696            reset_edge_overlay();
697        }
698        break;
699    }
700    case EDGE_FROZEN:
701    {
702        // We have a stored edge overlay in memory and we display
703        // it on screen in 'frozen' mode.
704
705        // Move edge overlay around.
706        if (gui_get_mode() == GUI_MODE_ALT)
707        {
708            if (kbd_is_key_pressed(KEY_RIGHT))
709                xoffset +=XINC;
710            if (kbd_is_key_pressed(KEY_LEFT))
711                xoffset -=XINC;
712            if (kbd_is_key_pressed(KEY_DOWN))
713                yoffset +=YINC;
714            if (kbd_is_key_pressed(KEY_UP))
715                yoffset -=YINC;
716        }
717
718        if (bCanDisplay && (bGuiModeAlt || bGuiModeNone))
719        {
720            // We try to detect button presses during the lengthy
721            // calculations.
722            bFullPress |= draw_edge_overlay();
723            draw_string(0, 0, "Frozen", *conf_osd_color);
724        }
725
726        // In event of a FullPress, we either capture a new
727        // overlay and stay frozen, OR we go back to live mode.
728        if (bFullPress && !bFullPress_prev && bGuiModeNone)
729        {
730            // Possible mode switch
731            if (bPanoramaMode)
732            {
733                // Make sure we have one whole consistent frame
734                for (slice = 0; slice < EDGE_SLICES; ++slice)
735                    calc_edge_overlay();
736
737                set_offset_from_overlap();
738                bPanoInProgress = 1;
739            }
740            else
741                fsm_state = EDGE_LIVE;
742        }
743
744        break;
745    }   // case
746    }   // switch
747
748
749    bFullPress_prev = bFullPress;
750
751    if (++slice >= EDGE_SLICES)
752        slice = 0;
753
754}   // function
755
756
757
758
759
760// =========  MODULE INIT =================
761
762#include "module_load.h"
763int module_idx=-1;
764
765/***************** BEGIN OF AUXILARY PART *********************
766  ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
767 **************************************************************/
768
769void* MODULE_EXPORT_LIST[] = {
770        /* 0 */ (void*)EXPORTLIST_MAGIC_NUMBER,
771        /* 1 */ (void*)5,
772
773                        edge_overlay,
774                        save_edge_overlay,
775                        load_edge_overlay
776                };
777
778
779//---------------------------------------------------------
780// PURPOSE:   Bind module symbols with chdk.
781//              Required function
782// PARAMETERS: pointer to chdk list of export
783// RETURN VALUE: 1 error, 0 ok
784//---------------------------------------------------------
785int _module_loader( void** chdk_export_list )
786{
787  if ( (unsigned int)chdk_export_list[0] != EXPORTLIST_MAGIC_NUMBER )
788     return 1;
789
790  tConfigVal configVal;
791  CONF_BIND_INT(188, conf_edge_overlay_thresh);
792  CONF_BIND_COLOR(189, conf_edge_overlay_color);
793  CONF_BIND_INT(222, conf_edge_overlay_play);
794  CONF_BIND_INT(223, conf_edge_overlay_pano);
795  CONF_BIND_INT(224, conf_edge_overlay_zoom);
796  CONF_BIND_INT(241, conf_edge_overlay_filter);
797  CONF_BIND_INT(242, conf_edge_overlay_show);
798  CONF_BIND_INT(243, conf_edge_overlay_pano_overlap);
799  CONF_BIND_COLOR( 28, conf_osd_color);
800
801  return 0;
802}
803
804
805
806//---------------------------------------------------------
807// PURPOSE: Finalize module operations (close allocs, etc)
808// RETURN VALUE: 0-ok, 1-fail
809//---------------------------------------------------------
810int _module_unloader()
811{
812        // This could be happens only if on-load mistake
813        // CHDK never unload this library (but load only if needed)
814        // Reason: edve_overlay allocate different bufs which should be kept
815        //              because even if we turn off edgeovr we could turn on back and
816        //              should get same content.
817  return 0;
818}
819
820/******************** Module Information structure ******************/
821
822struct ModuleInfo _module_info = {      MODULEINFO_V1_MAGICNUM,
823                                                                        sizeof(struct ModuleInfo),
824
825                                                                        ANY_CHDK_BRANCH, 0,                     // Requirements of CHDK version
826                                                                        ANY_PLATFORM_ALLOWED,           // Specify platform dependency
827                                                                        MODULEINFO_FLAG_SYSTEM,         // flag
828                                                                        (int32_t)"Edge Overalay (dll)",// Module name
829                                                                        1, 0,                                           // Module version
830                                                                        (int32_t)"Implementation one of core modes"
831                                                                 };
832
833
834/*************** END OF AUXILARY PART *******************/
835
Note: See TracBrowser for help on using the repository browser.