source: trunk/core/edgeoverlay.c @ 928

Revision 928, 22.7 KB checked in by fe50, 3 years ago (diff)

New edge overlay, rewritten zebra, SX20 stuff

Note:

  • some of this (edge overlay, zebra) affects ALL cameras !
  • since there are changes in the CHDK configuration, it's recommended to use a new config file (i.e. to rename/delete the cchdk.cfg file)

The SX20 1.02D now is enabled in the main makefile for the autobuild server

  • Property svn:eol-style set to native
Line 
1#include "edgeoverlay.h"
2#include "platform.h"
3#include "conf.h"
4#include "keyboard.h"
5#include "stdlib.h"
6#include "gui_draw.h"
7#include "bitvector.h"
8 
9// the way we save edge overlays on their own...
10#define EDGE_FILE_PREFIX "EDG_"
11#define EDGE_FILE_FORMAT EDGE_FILE_PREFIX "%04d.edg"
12 
13typedef enum _edge_fsm_state
14{
15    EDGE_LIVE = 0,
16    EDGE_FROZEN
17} edge_fsm_state_t;
18 
19static edge_fsm_state_t fsm_state = EDGE_LIVE;
20static bit_vector_t* edgebuf = NULL;
21static int xoffset = 0, yoffset = 0;
22 
23static int viewport_size;   // whole viewport size in bytes ??
24static int viewport_width;      // screenwidth * 3, width in bytes of one viewport line ??
25static int viewport_height;
26#if CAM_USES_ASPECT_CORRECTION
27static int viewportw; //nandoide , width of viewport (not necessarily equal to width of screen)
28#endif
29 
30static void get_viewport_size()
31{
32    // since screen_height is used in the drawing downwards, we should use it
33    // here too to calculate the buffer we need...
34 
35#if CAM_USES_ASPECT_CORRECTION//nandoide sept-2009 get the viewport dimensions, not the screen dimensions, on sx200is they aren't the same.
36    viewport_height = vid_get_viewport_height()-EDGE_HMARGIN*2; //don't trace bottom lines
37    viewportw = vid_get_viewport_width();
38    viewport_width = viewportw * 3;
39    viewport_size = viewport_height * viewport_width;
40#else
41    viewport_height = screen_height;//vid_get_viewport_height();
42    viewport_width = screen_width * 3;
43    viewport_size = viewport_height * screen_width * 3;
44#endif
45}
46 
47static void ensure_allocate_imagebuffer()
48{
49    if(edgebuf == NULL)
50    {
51        edgebuf = bv_create(viewport_size, 1);
52    }
53}
54 
55static void reset_edge_overlay()
56{
57    bv_free(edgebuf);
58    edgebuf = NULL;
59    fsm_state = EDGE_LIVE;
60}
61 
62static int is_buffer_ready()
63{
64    if (edgebuf == NULL) return 0;
65    if (edgebuf->ptr == NULL) return 0; // this should never happen, but it does not hurt to check
66    return 1;
67}
68 
69// scans a filename for the number of the edge detection file it contains
70static int get_edge_file_num(const char* fn)
71{
72    int num = 0;
73    if( strncmp(fn,EDGE_FILE_PREFIX,sizeof(EDGE_FILE_PREFIX)-1) == 0 )
74    {
75        // has the correct beginning at least, now try to read as a number...
76        fn += sizeof(EDGE_FILE_PREFIX);
77        while( *fn == '0' ) // skip leading 0s
78        {
79            ++fn;
80        }
81        while( isdigit(*fn) )
82        {
83            num *= 10;
84            num += *fn - '0';
85            ++fn;
86        }
87        // ignore anything else after it, that is like the ending etc.
88    }
89    return num;
90}
91 
92// saves the actual active overlay data to a file.
93void save_edge_overlay(void)
94{
95 
96    char fn[64];
97    char msg[64];
98    FILE *fd;
99    DIR* d;
100    int fnum = 0;
101    int fr = 0;
102    int zoom = 0;
103    struct dirent* de;
104    static struct utimbuf t;
105    // nothing to save? then dont save
106 
107    if( !is_buffer_ready() )
108    {
109        draw_string(0, 0, "No overlay to save.", conf.osd_color);
110        return;
111    }
112 
113    zoom = shooting_get_zoom();
114 
115    // first figure out the most appropriate filename to use
116    d = opendir(EDGE_SAVE_DIR);
117    if( ! d )
118    {
119        return;
120    }
121 
122    while( (de = readdir(d)) )
123    {
124        fr = get_edge_file_num(de->d_name);
125        if( fr > fnum )
126        {
127            fnum = fr;
128        }
129    }
130    ++fnum; // the highest is set, we use the next one
131    get_viewport_size();
132    // open the right file
133    sprintf(fn, EDGE_SAVE_DIR "/" EDGE_FILE_FORMAT, fnum );
134    fd = fopen(fn, "wb");
135    if(fd !=NULL)
136    {
137        // write the data
138        fwrite(edgebuf->ptr,edgebuf->ptrLen,1,fd);
139        fwrite(&zoom,sizeof(zoom),1,fd);
140        fclose(fd);
141        t.actime = t.modtime = time(NULL);
142        utime(fn, &t);
143        sprintf(msg, "Saved as %s",fn);
144        draw_string(0, 0, msg, conf.osd_color);
145    }
146    closedir(d);
147}
148 
149// load the edge overlay from a file
150void load_edge_overlay(const char* fn)
151{
152    FILE *fd;
153    int ret,ret2;
154    int zoom;
155 
156    get_viewport_size();
157    ensure_allocate_imagebuffer( );
158    fd = fopen(fn,"rb");
159    if( fd != NULL )
160    {
161        ret = fread(edgebuf->ptr,edgebuf->ptrLen,1,fd);
162        ret2 = fread (&zoom,sizeof(zoom),1,fd);
163        fclose(fd);
164        if( (ret == 1) && (ret2 == 1) )
165        {
166            fsm_state = EDGE_FROZEN;    // switch to "edge overlay frozen"-mode
167            if (conf.edge_overlay_zoom)
168            {
169                shooting_set_zoom(zoom);
170            }
171        }
172    }
173}
174 
175static void average_filter_row(const unsigned char* ptrh1,  // previous row
176                               const unsigned char* ptrh2,  // current row
177                               const unsigned char* ptrh3,  // next row
178                               unsigned char* smptr )       // write results here
179{
180    int x;
181#if CAM_USES_ASPECT_CORRECTION
182    for (x=12; x<(viewportw - 4) * 3; x+=6)
183#else
184    for (x=12; x<(screen_width - 4) * 3; x+=6)
185#endif
186    {
187        *(smptr + x + 1) = (*(ptrh1 + x - 1) +
188                            *(ptrh1 + x + 1) +
189                            *(ptrh1 + x + 3) +
190 
191                            *(ptrh2 + x - 1) +
192                            *(ptrh2 + x + 1) +
193                            *(ptrh2 + x + 3) +
194 
195                            *(ptrh3 + x - 1) +
196                            *(ptrh3 + x + 1) +
197                            *(ptrh3 + x + 3)) / 9;
198 
199        *(smptr + x + 3) = (*(ptrh1 + x + 1) +
200                            *(ptrh1 + x + 3) +
201                            *(ptrh1 + x + 4) +
202 
203                            *(ptrh2 + x + 1) +
204                            *(ptrh2 + x + 3) +
205                            *(ptrh2 + x + 4) +
206 
207                            *(ptrh3 + x + 1) +
208                            *(ptrh3 + x + 3) +
209                            *(ptrh3 + x + 4)) / 9;
210 
211        *(smptr + x + 4) = (*(ptrh1 + x + 3) +
212                            *(ptrh1 + x + 4) +
213                            *(ptrh1 + x + 5) +
214 
215                            *(ptrh2 + x + 3) +
216                            *(ptrh2 + x + 4) +
217                            *(ptrh2 + x + 5) +
218 
219                            *(ptrh3 + x + 3) +
220                            *(ptrh3 + x + 4) +
221                            *(ptrh3 + x + 5)) / 9;
222 
223        *(smptr + x + 5) = (*(ptrh1 + x + 4) +
224                            *(ptrh1 + x + 5) +
225                            *(ptrh1 + x + 7) +
226 
227                            *(ptrh2 + x + 4) +
228                            *(ptrh2 + x + 5) +
229                            *(ptrh2 + x + 7) +
230 
231                            *(ptrh3 + x + 4) +
232                            *(ptrh3 + x + 5) +
233                            *(ptrh3 + x + 7)) / 9;
234    }
235}
236 
237// Sobel edge detector
238static void calc_edge_overlay()
239{
240    const int bPlayMode = (mode_get() & MODE_MASK) == MODE_PLAY;
241    const unsigned char* img = bPlayMode ? vid_get_viewport_fb_d() :  vid_get_viewport_fb();
242    const unsigned char * ptrh1 = NULL;    // previous pixel line
243    const unsigned char * ptrh2 = NULL;    // current pixel line
244    const unsigned char * ptrh3 = NULL;    // next pixel line
245    unsigned char* smbuf = NULL;
246    unsigned char * smptr = NULL;    // pointer to line in smbuf
247    int x, y;
248    int conv1, conv2;
249   
250    const int y_min = EDGE_HMARGIN;
251    const int y_max = EDGE_HMARGIN + viewport_height;
252    const int x_min = 6;
253#if CAM_USES_ASPECT_CORRECTION
254    const int x_max = (viewportw - 4) * 3;
255#else
256    const int x_max = (screen_width - 4) * 3;
257#endif
258
259    xoffset =0;
260    yoffset =0;
261 
262    // Reserve buffers
263    ensure_allocate_imagebuffer();
264    if( !is_buffer_ready() ) return;
265 
266    // Clear all edges, if any
267    memset(edgebuf->ptr, 0, edgebuf->ptrLen);
268 
269    // In every 6 bytes four pixels are described in the
270    // viewport (UYVYYY format). For edge detection we only
271    // consider the second in the current and the first
272    // in the next pixel.
273 
274 
275    if (conf.edge_overlay_filter)
276    {
277        smbuf = (unsigned char*)malloc(viewport_width*3);
278        memset(smbuf, 0, viewport_width*3);
279        if (smbuf==NULL)
280            return;
281 
282        // Prefill smbuf with three lines of avergae-filtered data.
283        // This looks much more complex then it actually is.
284        // We really are just summing up nine pixels in a 3x3 box
285        // and averaging the current pixel based on them. And
286        // we do it 4 bytes at a time because of the UYVYYY format.
287        for (y = -1; y <= 1; ++y)
288        {
289            ptrh1 = img + (EDGE_HMARGIN+y-1) * viewport_width;
290            ptrh2 = img + (EDGE_HMARGIN+y  ) * viewport_width;
291            ptrh3 = img + (EDGE_HMARGIN+y+1) * viewport_width;
292            smptr = smbuf + (y+1) * viewport_width;
293 
294            average_filter_row(ptrh1, ptrh2, ptrh3, smptr);
295        }
296    }
297 
298    for (y = y_min; y < y_max; ++y)
299    {
300        if (conf.edge_overlay_filter)
301        {
302            // We need to shift up our smbuf one line,
303            // and fill in the last line (which now empty)
304            // with average-filtered data from img.
305            // By storing only three lines of smoothed picture
306            // in memory, we save memory.
307 
308            // Shift
309            memcpy(smbuf+viewport_width*0, smbuf+viewport_width*1, viewport_width);
310            memcpy(smbuf+viewport_width*1, smbuf+viewport_width*2, viewport_width);
311 
312            // Filter new line
313            ptrh1 = img +  y * viewport_width;
314            ptrh2 = img + (y+1)    * viewport_width;
315            ptrh3 = img + (y+2) * viewport_width;
316            smptr = smbuf + 2 * viewport_width;
317            average_filter_row(ptrh1, ptrh2, ptrh3, smptr);
318 
319            ptrh1 = smbuf + 0 * viewport_width;
320            ptrh2 = smbuf + 1 * viewport_width;
321            ptrh3 = smbuf + 2 * viewport_width;
322        }
323        else
324        {
325            ptrh1 = img + (y-1) * viewport_width;
326            ptrh2 = img +  y    * viewport_width;
327            ptrh3 = img + (y+1) * viewport_width;
328        }
329 
330        // Now we do sobel on the current line
331 
332        for (x = x_min; x < x_max; x += 6)
333        {
334            // convolve vert (second Y)
335            conv1 = *(ptrh1 + x + 1) * ( 1) +
336                    *(ptrh1 + x + 4) * (-1) +
337 
338                    *(ptrh2 + x + 1) * ( 2) +
339                    *(ptrh2 + x + 4) * (-2) +
340 
341                    *(ptrh3 + x + 1) * ( 1) +
342                    *(ptrh3 + x + 4) * (-1);
343            if  (conv1 < 0)     // abs()
344                conv1 = -conv1;
345 
346            // convolve vert (first Y of next pixel)
347            conv2 = *(ptrh1 + x + 1) * ( 1) +
348                    *(ptrh1 + x + 3) * ( 2) +
349                    *(ptrh1 + x + 4) * ( 1) +
350 
351                    *(ptrh3 + x + 1) * (-1) +
352                    *(ptrh3 + x + 3) * (-2) +
353                    *(ptrh3 + x + 4) * (-1);
354            if  (conv2 < 0)     // abs()
355                conv2 = -conv2;
356 
357            if (conv1 + conv2 > conf.edge_overlay_thresh)
358            {
359                bv_set(edgebuf, (y-EDGE_HMARGIN)*viewport_width + x/3, 1);
360            }
361 
362            // Do it once again for the next 'pixel'
363 
364            // convolve vert (second Y)
365            conv1 = *(ptrh1 + x + 5) * ( 1) +
366                    *(ptrh1 + x + 9) * (-1) +
367 
368                    *(ptrh2 + x + 5) * ( 2) +
369                    *(ptrh2 + x + 9) * (-2) +
370 
371                    *(ptrh3 + x + 5) * ( 1) +
372                    *(ptrh3 + x + 9) * (-1);
373            if  (conv1 < 0)     // abs()
374                conv1 = -conv1;
375 
376            // convolve vert (first Y of next pixel)
377            conv2 = *(ptrh1 + x + 5) * ( 1) +
378                    *(ptrh1 + x + 7) * ( 2) +
379                    *(ptrh1 + x + 9) * ( 1) +
380 
381                    *(ptrh3 + x + 5) * (-1) +
382                    *(ptrh3 + x + 7) * (-2) +
383                    *(ptrh3 + x + 9) * (-1);
384            if  (conv2 < 0)     // abs()
385                conv2 = -conv2;
386 
387            if (conv1 + conv2 > conf.edge_overlay_thresh)
388            {
389                bv_set(edgebuf, (y-EDGE_HMARGIN)*viewport_width + x/3+1, 1);
390            }
391        }   // for x
392    }   // for y
393 
394    if (smbuf != NULL)
395    {
396        free(smbuf);
397        smbuf = NULL;
398    }
399 
400//  For an even more improved edge overlay, enabling the following lines will
401//  post-filter the results of the edge detection, removing false edge 'dots'
402//  from the display. However, the speed hit is large. In the developer's opinion
403//  this code is not needed, but if you want that additional quality and do not
404//  care so much about performance, you can enable it.
405//
406//    if (conf.edge_overlay_filter)
407//    {
408//        // Here we do basic filtering on the detected edges.
409//        // If a pixel is marked as edge but just a few of its
410//        // neighbors are also edges, then we assume that the
411//        // current pixel is just noise and delete the mark.
412//
413//        bit_vector_t* bv_tmp = bv_create(edgebuf->nElem, edgebuf->nBits);
414//        if (bv_tmp != NULL)
415//        {
416//            memset(bv_tmp->ptr, 0, bv_tmp->ptrLen);
417//
418//            for (y = 1; y < viewport_height-1; ++y)
419//            {
420//#if CAM_USES_ASPECT_CORRECTION
421//                for (x=12; x<(viewportw - 4); ++x)
422//#else
423//                for (x=12; x<(screen_width - 4); ++x)
424//#endif
425//                {
426//                    int bEdge = bv_get(edgebuf, y*viewport_width + x);
427//                    if (bEdge)
428//                    {
429//                        // Count the number of neighbor edges
430//                        int sum =
431//                            bv_get(edgebuf, (y-1)*viewport_width + (x-1)) +
432//                            bv_get(edgebuf, (y-1)*viewport_width + (x)) +
433//                            bv_get(edgebuf, (y-1)*viewport_width + (x+1)) +
434//
435//                            bv_get(edgebuf, (y)*viewport_width + (x-1)) +
436////              bv_get(&edgebuf, (y)*viewport_width + (x)) + //  we only inspect the neighbors
437//                            bv_get(edgebuf, (y)*viewport_width + (x+1)) +
438//
439//                            bv_get(edgebuf, (y+1)*viewport_width + (x-1)) +
440//                            bv_get(edgebuf, (y+1)*viewport_width + (x)) +
441//                            bv_get(edgebuf, (y+1)*viewport_width + (x+1));
442//
443//                        if (!conf.edge_overlay_show)
444//                        {
445//                            if (sum >= 5)    // if we have at least 5 neighboring edges
446//                                bv_set(bv_tmp, y*viewport_width + x, 1);   // keep the edge
447//                            // else
448//                            // there is no need to delete because the buffer is already zeroed
449//                        }
450//                    }
451//                }   // for x
452//            }   // for y
453//
454//            // Swap the filtered edge buffer for the real one
455//            bit_vector_t* swap_tmp = edgebuf;
456//            edgebuf = bv_tmp;
457//            bv_free(swap_tmp);
458//        }   // NULL-check
459//    }   // if filtering
460 
461}
462 
463static void draw_edge_overlay()
464{
465    int x, y;
466    int x_off, y_off;
467 
468    const int y_min = EDGE_HMARGIN;
469    const int y_max = EDGE_HMARGIN+viewport_height;
470    const int x_min = 6;
471#if CAM_USES_ASPECT_CORRECTION
472    const int x_max = (viewportw - 4);
473#else
474    const int x_max = (screen_width - 4);
475#endif
476
477    if( !is_buffer_ready() ) return;
478 
479    for (y = y_min; y < y_max; ++y)
480    {
481        y_off = y + yoffset;
482 
483        if ((y_off > y_min) && (y_off < y_max)) // do not draw outside of allowed area
484        {
485            for (x = x_min; x < x_max; ++x)
486            {
487                x_off = x + xoffset;
488 
489                if ((x_off > x_min) && (x_off < x_max)) // do not draw outside of allowed area
490                {
491                    // Draw a pixel to the screen wherever we detected an edge.
492                    // If there is no edge based on the newest data, but there is one painted on the screen
493                    // from previous calls, delete it from the screen.
494                    if (bv_get(edgebuf, (y-y_min)*viewport_width + x))
495                        draw_pixel(ASPECT_VIEWPORT_XCORRECTION(x_off), y_off, conf.edge_overlay_color );
496                    else if (draw_get_pixel(ASPECT_VIEWPORT_XCORRECTION(x_off), y_off) == conf.edge_overlay_color)
497                        draw_pixel(ASPECT_VIEWPORT_XCORRECTION(x_off), y_off, 0 );
498                }
499            }   // for x
500        }
501    }   // for y
502 
503 
504    // Drawing the overlay is over.
505    // But as a finishing touch we clear up garbage on the screen
506    // by clearing those parts that the overlay has left.
507 
508    if (xoffset != 0)
509    {
510        // Cleans up leftover from horizontal motion
511 
512        const int x_min_c = (xoffset < 0) ? x_max + xoffset : x_min;
513        const int x_max_c = (xoffset > 0) ? x_min + xoffset : x_max;
514 
515        for (y = y_min; y < y_max; ++y)
516        {
517            for (x = x_min_c; x < x_max_c; ++x)
518            {
519                if (draw_get_pixel(ASPECT_VIEWPORT_XCORRECTION(x), y) == conf.edge_overlay_color)  // 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
520                    draw_pixel(ASPECT_VIEWPORT_XCORRECTION(x), y, 0 );
521            }
522        }
523    }
524 
525    if (yoffset != 0)
526    {
527        // Cleans up leftover from vertical motion
528 
529        const int y_min_c = (yoffset < 0) ? y_max + yoffset : y_min;
530        const int y_max_c = (yoffset > 0) ? y_min + yoffset : y_max;
531 
532        for (y = y_min_c; y < y_max_c; ++y)
533        {
534            for (x = x_min; x < x_max; ++x)
535            {
536                if (draw_get_pixel(ASPECT_VIEWPORT_XCORRECTION(x), y) == conf.edge_overlay_color)  // 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
537                    draw_pixel(ASPECT_VIEWPORT_XCORRECTION(x), y, 0 );
538            }
539        }
540    }
541}
542
543static void set_offset_from_overlap()
544{
545    const int y_max = viewport_height;
546#if CAM_USES_ASPECT_CORRECTION
547    const int x_max = (viewportw - 4);
548#else
549    const int x_max = (screen_width - 4);
550#endif
551
552    switch(conf.edge_overlay_pano)
553    {
554    case 0:     // pano off
555        xoffset = 0;
556        yoffset = 0;
557        break;
558    case 1:     // pano from left to right
559        xoffset = -x_max*(100-conf.edge_overlay_pano_overlap)/100;
560        break;
561    case 2:     // pano from top to bottom
562        yoffset = -y_max*(100-conf.edge_overlay_pano_overlap)/100;
563        break;
564    case 3:     // pano from right to left
565        xoffset = x_max*(100-conf.edge_overlay_pano_overlap)/100;
566        break;
567    case 4:     // pano from bottom to top
568        yoffset = y_max*(100-conf.edge_overlay_pano_overlap)/100;
569        break;
570    case 5:     // free mode
571    default:
572        // free mode: change position with "ALT" and cursor
573        // nothing to do here.
574        break;
575    }
576}
577 
578 
579// Main edge overlay function.
580// It works by detecting edges using the Sobel operator
581// (calc_edgeoverlay()), the detected edges are then stored into an
582// array of 1-bit elements. A set bit indicates that there is an
583// edge and that it should be drawn onto the overlay.
584// When needed, the 1-bit edge buffer is drawn onto the screen
585// (dynamically decompressing it) using draw_edge_overlay().
586void edge_overlay()
587{
588    // Was the shutter fully pressed the last time we ran?
589    // We use this to make sure that the user has released
590    // the button before processing the next FullPress event.
591    // This prevents switching FSM states more than once
592    // per press.
593    static int bFullPress_prev = 0;
594 
595    // Have we already started taking pictures in panorama mode?
596    // We use this variable to be able to detect if panorama
597    // mode has been turned off.
598    static int bPanoInProgress = 0;
599 
600    // Precalculate some values to make the rest of the
601    // code easier to read.
602    const int bHalfPress = kbd_is_key_pressed(KEY_SHOOT_HALF);
603    const int bFullPress = kbd_is_key_pressed(KEY_SHOOT_FULL);
604    const int bPlayMode = (mode_get() & MODE_MASK) == MODE_PLAY;
605    const int bPanoramaMode = (conf.edge_overlay_pano != 0);
606    const int bNeedHalfPress = (conf.edge_overlay_show != 1);
607    const int bDisplayInPlay = (conf.edge_overlay_play == 1);
608    const int bGuiModeNone = (gui_get_mode() == GUI_MODE_NONE);
609    const int bGuiModeAlt = (gui_get_mode() == GUI_MODE_ALT);
610    const int bCanDisplay = (
611                                (!bPlayMode && (bHalfPress || !bNeedHalfPress)) ||   // we have a HalfPress in rec-mode
612                                ( bPlayMode && bDisplayInPlay)  // or we are in play-mode with the right settings
613                            );
614 
615    if (bPanoInProgress && !bPanoramaMode)
616    {
617        // This means panorama mode has been recently
618        // turned off in the menu. So let's release
619        // Frozen mode for the user.
620        reset_edge_overlay();
621        bPanoInProgress = 0;
622    }
623 
624    get_viewport_size();
625
626    // For just two states a state machine is not actually needed.
627    // But it is scalable in the future in case anybody
628    // wants to extend the functionality of edge overlay.
629    switch (fsm_state)
630    {
631    case EDGE_LIVE:
632    {
633        // In this state we assume no edge overlay in memory,
634        // but we are ready to create one if the user presses wishes so.
635 
636        if (bFullPress && !bFullPress_prev && bGuiModeNone)
637        {
638            calc_edge_overlay();
639            set_offset_from_overlap();
640            fsm_state = EDGE_FROZEN;
641           
642            bPanoInProgress = bPanoramaMode;
643        }
644        else if (bCanDisplay && (bGuiModeAlt || bGuiModeNone))
645        {
646            calc_edge_overlay();
647            draw_edge_overlay();
648        }
649        else
650        {
651            // Nothing happens. So do nothing.
652            // Or rather, we could clean up if we are that bored.
653            bv_free(edgebuf);
654            edgebuf = NULL;
655        }
656 
657        break;
658    }
659    case EDGE_FROZEN:
660    {
661        // We have a stored edge overlay in memory and we display
662        // it on screen in 'frozen' mode.
663 
664        // Move edge overlay around.
665        if (gui_get_mode() == GUI_MODE_ALT)
666        {
667            if (kbd_is_key_pressed(KEY_RIGHT))
668                xoffset +=XINC;
669            if (kbd_is_key_pressed(KEY_LEFT))
670                xoffset -=XINC;
671            if (kbd_is_key_pressed(KEY_DOWN))
672                yoffset +=YINC;
673            if (kbd_is_key_pressed(KEY_UP))
674                yoffset -=YINC;
675        }
676 
677        // In event of a FullPress, we either capture a new
678        // overlay and stay frozen, OR we go back to live mode.
679        if (bFullPress && !bFullPress_prev && bGuiModeNone)
680        {
681            if (bPanoramaMode)
682            {
683                calc_edge_overlay();
684                set_offset_from_overlap();
685                bPanoInProgress = 1;
686            }
687            else
688                fsm_state = EDGE_LIVE;
689        }
690        else if (bCanDisplay && (bGuiModeAlt || bGuiModeNone))
691        {
692            draw_edge_overlay();
693            draw_string(0, 0, "Frozen", conf.osd_color);
694        }
695 
696        break;
697    }   // case
698    }   // switch
699 
700    bFullPress_prev = bFullPress;
701}   // function
702 
703 
704 
705 
Note: See TracBrowser for help on using the repository browser.