Index: /trunk/include/conf.h
===================================================================
--- /trunk/include/conf.h	(revision 579)
+++ /trunk/include/conf.h	(revision 580)
@@ -245,4 +245,7 @@
     int edge_overlay_enable;
     int edge_overlay_thresh;
+    int edge_overlay_zoom; // shall zoom be set when *edg file is loaded?
+    int edge_overlay_lock; // whether edge overlay should be overwritten on each half-press or not
+    int edge_overlay_play; // whether edge overlay is switched on also for play mode
     color edge_overlay_color;
 
@@ -259,4 +262,5 @@
     
     long mem_view_addr_init;
+
 } Conf;
 
Index: /trunk/core/conf.c
===================================================================
--- /trunk/core/conf.c	(revision 579)
+++ /trunk/core/conf.c	(revision 580)
@@ -133,4 +133,5 @@
 	 shooting_video_bitrate_change(conf.video_bitrate);
  	}
+ 	conf.edge_overlay_lock = 0; // reset it because otherwise this feature cant be used at startup (when buffer is empty) - needs workaround other than this!
 }
 
@@ -370,4 +371,8 @@
     CONF_INFO(219, conf.bracketing_add_raw_suffix,         CONF_DEF_VALUE, i:0, NULL),			
     CONF_INFO(220, conf.temperature_unit,              CONF_DEF_VALUE, i:0, NULL),
+    CONF_INFO(221, conf.clear_zoom_override,         CONF_DEF_VALUE, i:1, NULL),			
+    CONF_INFO(222, conf.edge_overlay_play,    CONF_DEF_VALUE, i:0, NULL),
+    CONF_INFO(223, conf.edge_overlay_lock,              CONF_DEF_VALUE, i:0, NULL),
+    CONF_INFO(224, conf.edge_overlay_zoom,                CONF_DEF_VALUE, i:1, NULL),
     };
 #define CONF_NUM (sizeof(conf_info)/sizeof(conf_info[0]))
Index: /trunk/core/gui_lang.c
===================================================================
--- /trunk/core/gui_lang.c	(revision 579)
+++ /trunk/core/gui_lang.c	(revision 580)
@@ -536,4 +536,10 @@
 "415 \"Add raw-suffix\"\n"
 "416 \"  in Fahrenheit\"\n"
+"417 \"Load Edge Overlay\"\n"
+"418 \"Save Edge Overlay\"\n"
+"419 \"Enable in Play\"\n"
+"420 \"Free internal Memory\"\n"
+"421 \"Load+Set Zoom\"\n"
+"422 \"Lock Edge Overlay\"\n"
 
 ;
Index: /trunk/core/gui_osd.c
===================================================================
--- /trunk/core/gui_osd.c	(revision 579)
+++ /trunk/core/gui_osd.c	(revision 580)
@@ -1,2 +1,3 @@
+#include "camera.h"
 #include "stdlib.h"
 #include "keyboard.h"
@@ -282,5 +283,15 @@
     if (buf) {
         ++timer;
-        img_buf=((mode_get()&MODE_MASK) == MODE_PLAY)?vid_get_viewport_fb_d():vid_get_viewport_fb();
+	// Try to get the best viewport buffer. In playmode its the _d one, in
+	// record mode we try to get the fast live one first
+	if( (mode_get() & MODE_MASK) == MODE_PLAY ) {
+	    img_buf = vid_get_viewport_fb_d();
+	}
+	else {
+	    img_buf = vid_get_viewport_live_fb();
+	    if( !img_buf ) {
+		img_buf = vid_get_viewport_fb();
+	    }
+	}
         viewport_height = vid_get_viewport_height();
         switch (conf.zebra_mode) {
Index: /trunk/core/gui_lang.h
===================================================================
--- /trunk/core/gui_lang.h	(revision 579)
+++ /trunk/core/gui_lang.h	(revision 580)
@@ -520,5 +520,4 @@
 #define LANG_MENU_SCRIPT_PARAM_SAVE 410
 #define LANG_OSD_LAYOUT_EDITOR_EV_VIDEO 411
-
 #define	LANG_MENU_OVERRIDE_ZOOM_VALUE          412
 #define	LANG_MENU_OVERRIDE_ZOOM           413
@@ -526,7 +525,13 @@
 #define LANG_MENU_BRACKETING_ADD_RAW_SUFFIX 415
 #define LANG_MENU_OSD_TEMP_FAHRENHEIT 416
+#define LANG_MENU_EDGE_LOAD		417
+#define LANG_MENU_EDGE_SAVE		418
+#define LANG_MENU_EDGE_PLAY		419
+#define LANG_MENU_EDGE_FREE		420
+#define LANG_MENU_EDGE_ZOOM		421
+#define LANG_MENU_EDGE_LOCK		422
 //-------------------------------------------------------------------
 
-#define GUI_LANG_ITEMS                  416
+#define GUI_LANG_ITEMS                  422
 
 //-------------------------------------------------------------------
Index: /trunk/core/edgeoverlay.c
===================================================================
--- /trunk/core/edgeoverlay.c	(revision 579)
+++ /trunk/core/edgeoverlay.c	(revision 580)
@@ -6,59 +6,227 @@
 #include "gui_draw.h"
 
-// until the edge thresh is put into conf structure I have hardcoded the threshold  see "thresh" below
+// This edge overlay code has major changes to the "old" one. One major change
+// is, that it doesn cause my cam (ixus 950) to crash anymore by mistaking the
+// boundaries of the viewport buffer it can read from and write pixels to.
+// Unfortunately it still has the bug (that is also present in the original
+// version) that when you move the overlay too much you again overwrite data.
+// One might not necessarily notice it at once, or at all, but for me
+// unfortunately it overwrote vital data for the chdk menu structure.
+// 
+// Also the old version was flickering for me and wasn't playing well with the
+// chdk osd. I tried to change a bit about that, which makes it also a bit
+// faster updating, at least on my cam.
+//
+// And then of course, this can load the viewport to a seperate file 
+
+// the way we save edge overlays on their own...
+#define EDGE_FILE_PREFIX "edge_"
+#define EDGE_FILE_FORMAT EDGE_FILE_PREFIX "%04d.edg"
+
 static char * imgbuf = 0;
- 
-
+static char * imgbuf_end = 0;
+static int inmem=0;
+// whole viewport size in bytes ??
+static int viewport_size = 0;
+// width in bytes of one viewport line ??
+static int viewport_width;// screenwidth * 3
+// flag to remember if current buffer is already saved, so hitting save won't
+// save it again
+static int is_saved = 0;
+// set this to 1 when things need to be moved, so that a redraw clears "old"
+// pixels... Otherwise it just will write pixels that need edge overlay data.
+// This sometimes leaves trails when the pixel alignment isn't nice but it is
+// better than writing "transparent" to everwhere, essentially overwriting
+// important things that will cause flickering.
+static int need_redraw = 0;
+
+// debug output that waits
+void out_wait( const char* buf );
+
+void get_viewport_size( ) {
+	static int viewport_height;
+
+	// since screen_height is used in the drawing downwards, we should use it
+	// here too to calculate the buffer we need...
+	viewport_height = screen_height;//vid_get_viewport_height();
+	viewport_width = screen_width * 3;
+	viewport_size = viewport_height * screen_width * 3;
+}
+
+void ensure_allocate_imagebuffer( ) { 
+	if(imgbuf == 0)
+	{
+		imgbuf = malloc( viewport_size );
+		imgbuf_end = imgbuf + (viewport_size);
+	}
+}
+
+// scans a filename for the number of the edge detection file it contains
+int get_edge_file_num( const char* fn )
+{
+	int num = 0;
+	if( strncmp(fn,EDGE_FILE_PREFIX,sizeof(EDGE_FILE_PREFIX)-1) == 0 )
+	{ // has the correct beginning at least, now try to read as a number...
+		fn += sizeof(EDGE_FILE_PREFIX);
+		while( *fn == '0' ) // skip leading 0s
+		{
+			++fn;
+		}
+		while( isdigit(*fn) )
+		{
+			num *= 10;
+			num += *fn - '0';
+			++fn;
+		}
+		// ignore anything else after it, that is like the ending etc.
+	}
+	return num;
+}
+
+// we eat up to 300k of memory, for people needing it we have a menu point
+// where they can manually free it. makes of course only sense when the edge
+// overlay is not active.
+void free_memory_edge_overlay(void){
+	char buf[64];
+	free(imgbuf);
+	imgbuf = 0;
+	sprintf(buf,"Freed %u bytes",viewport_size);
+	draw_string(30, 10, buf, conf.osd_color);
+	viewport_size = 0;
+}
+
+// saves the actual active overlay data to a file... Well, actually the
+// viewport is saved...
+void save_edge_overlay(void){
+
+	char fn[64];
+	char msg[64];
+	FILE *fd;
+	DIR* d;
+	int fnum = 0;
+	int fr = 0;
+	int zoom = shooting_get_zoom();
+	struct dirent* de;
+
+	// nothing to save? then dont save
+	if( !imgbuf ) return;
+
+	// first figure out the most appropriate filename to use
+	d = opendir(EDGE_SAVE_DIR);
+	if( ! d )
+	{
+		return;
+	}
+
+	while( (de = readdir(d)) )
+	{
+		fr = get_edge_file_num(de->name);
+		if( fr > fnum )
+		{
+			fnum = fr;
+		}
+	}
+	++fnum; // the highest is set, we use the next one
+	get_viewport_size();
+	// open the right file
+	sprintf(fn, EDGE_SAVE_DIR "/" EDGE_FILE_FORMAT, fnum );
+	fd = fopen(fn, "wb");
+	if(fd !=NULL)
+	{
+		// write the data
+		fwrite(imgbuf,viewport_size,1,fd);
+		fwrite(&zoom,4,1,fd);
+		is_saved = 1;
+		fclose(fd);
+		sprintf(msg, "Saved as %s",fn);
+		draw_string(30, 10, msg, conf.osd_color);
+	}
+	closedir(d);
+}
+
+// load the viewport copy thats being used for edge detection (and from that
+// displaying) from a file
+void load_edge_overlay( const char* fn ) {
+	FILE *fd;
+	int ret,ret2=0;
+	int zoom;
+
+	is_saved = 1; // won't want to save it again, its already there
+	get_viewport_size();
+	ensure_allocate_imagebuffer( );
+	fd = fopen(fn,"rb");
+	if( fd != NULL )
+	{
+		ret = fread(imgbuf,viewport_size,1,fd);
+		ret2 = fread (&zoom,4,1,fd);
+		fclose(fd);
+		if( (ret == 1) && (ret2 == 1) )
+		{
+			inmem = 1; // fake having loaded stuff
+			if (conf.edge_overlay_zoom)	shooting_set_zoom(zoom);
+		}
+	}
+}
+
+// paint the edge overlay
 void edge_overlay(){
 
-	//if(!(conf.edge_overlay_thresh) || !(conf.edge_overlay_enable)) return;
-
-	static int inmem=0;
-	static int viewport_height;
-	static int viewport_width;// screenwidth * 3
-	static int viewport_size;
 	static int shotTaken = 0;
 	static int imgmem = 0;
 	static int ymin = 0;
 	static int thresh;
-    thresh = conf.edge_overlay_thresh; //40
+	thresh = conf.edge_overlay_thresh; //40
 	static int xoffset = 0;
 	static int yoffset = 0;
 	static int full_press = 0;//cure for flaky behavior. due to multiple  returns to the scrip during one full press
 	static char strbuf[7] = "Frozen";
- 	static unsigned char *img;
+	static unsigned char *img;
 	int i, hi, c;
 	int x, y, h, v, ymax, y1, x1, y2;
-	char * ptrh1;
-	char * ptrh2;
-	char * ptrv1;
-	char * ptrv2;
+	const char * ptrh1;
+	const char * ptrh2;
+	const char * ptrv1;
+	const char * ptrv2;
+	char xbuf[64];
 	char * optr;
 
-
-	img = vid_get_viewport_fb();
-    viewport_height = vid_get_viewport_height();
-	viewport_width = screen_width * 3;
-    viewport_size = viewport_height * screen_width;
-	if(imgbuf == 0) imgbuf = malloc(viewport_size * 3);
- 
-	if((mode_get()&MODE_MASK) != MODE_PLAY) {
+	is_saved = 0; // a new one, we could potentially save it
+	if((mode_get()&MODE_MASK) != MODE_PLAY)
+	{
+		img = vid_get_viewport_fb();
+	}
+	else
+	{
+		img = vid_get_viewport_fb_d();
+	}
+	get_viewport_size();
+	ensure_allocate_imagebuffer( );
+	if(imgbuf == 0) return; // ensure failed, make the best we can out of it
+
+	if(conf.edge_overlay_play || ((mode_get()&MODE_MASK) != MODE_PLAY) ) {
+		// setup offsets for moving the edge overlay around. Always set
+		// need_redraw so that we actually do a complete redraw, overwriting
+		// also old pixels
 		if (kbd_is_key_pressed(KEY_RIGHT)) {
 			xoffset -=XINC;
+			++need_redraw;
 		}
 		if (kbd_is_key_pressed(KEY_LEFT)) {
 			xoffset +=XINC;
+			++need_redraw;
 		}
 		if (kbd_is_key_pressed(KEY_DOWN)) {
 			yoffset -=YINC;
+			++need_redraw;
 		}
 		if (kbd_is_key_pressed(KEY_UP)) {
 			yoffset +=YINC;
-		}
- 
-		if (kbd_is_key_pressed(KEY_SHOOT_HALF)||kbd_is_key_pressed(KEY_SHOOT_FULL)) {
+			++need_redraw;
+		}
+
+		if ((kbd_is_key_pressed(KEY_SHOOT_HALF)||kbd_is_key_pressed(KEY_SHOOT_FULL)) && (conf.edge_overlay_lock!=1)) {
 			if (kbd_is_key_pressed(KEY_SHOOT_FULL) && !full_press) {
 				shotTaken = 1 - shotTaken;
-				memcpy(imgbuf,img,viewport_size * 3);
+				memcpy(imgbuf,img,viewport_size);
 				ymin = CALCYMARGIN;
 				inmem = 1;
@@ -71,5 +239,5 @@
 				return;
 			}
-			memcpy(imgbuf,img,viewport_size * 3);
+			memcpy(imgbuf,img,viewport_size);
 			ymin = CALCYMARGIN;
 			inmem = 1;
@@ -79,4 +247,7 @@
 		}
 		else full_press = 0;
+
+
+
 		if (inmem && (ymin < screen_height-CALCYMARGIN)) {
 			ymax = ymin + (screen_height - 2 * CALCYMARGIN) / NSTAGES;
@@ -104,41 +275,67 @@
 			return;
 		}
+
 		if(inmem &&(ymin >= screen_height-CALCYMARGIN) && 
 			((gui_get_mode() == GUI_MODE_NONE) || (gui_get_mode() == GUI_MODE_ALT))){
-				//thresh = (conf.edge_overlay_thresh - 1) * 12;
+
 				for (y=MARGIN; y<screen_height-MARGIN; y++) {
 					y1 = y + yoffset;
 					if((y1 < CALCYMARGIN) || (y1 >= screen_height - CALCYMARGIN)) {
+						/*
 						for (x=MARGIN; x < screen_width - MARGIN; x+=2) {
 							draw_pixel(x, y, 0);
 							draw_pixel(x+1, y, 0);
 						}
+						*/
 					}
 					else {
 						for (x=MARGIN; x < screen_width - MARGIN; x+=2) {
 							x1 = x + xoffset;
+							// leave a margin normally, only write to it when a
+							// full redraw is requested
 							if((x1 < 12) || (x1 >= screen_width-13)) {
-								draw_pixel(x, y, 0);
-								draw_pixel(x+1, y, 0);
+								if( need_redraw )
+								{
+									draw_pixel(x, y, 0);
+									draw_pixel(x+1, y, 0);
+								}
 							}
 							else {
-								c = 0;
+								// draw a pixel if the threshold is reached. If
+								// not, draw it transparent only if we want a
+								// complete redraw to overwrite spurious pixels
+								// or if the color of the existing pixel is the
+								// same as the overlay color
 								if(imgbuf[y1 * viewport_width + x1 * 3 + 3]  > thresh)
-									c = conf.edge_overlay_color;
-								draw_pixel(x, y, c);
-								c = 0;
+								{
+									draw_pixel(x, y, conf.edge_overlay_color );
+								}
+								else if( need_redraw || (draw_get_pixel(x,y) == conf.edge_overlay_color) )
+								{
+									draw_pixel(x, y, 0);
+								}
+
 								if(imgbuf[y1 * viewport_width + x1 * 3 + 5]  > thresh)
-									c = conf.edge_overlay_color;
-								draw_pixel(x+1, y, c);
+								{
+									draw_pixel(x+1, y, conf.edge_overlay_color );
+								}
+								else if( need_redraw || (draw_get_pixel(x,y) == conf.edge_overlay_color) )
+								{
+									draw_pixel(x+1, y, 0);
+								}
 							}
 						}
 				}
-				for (y2=MARGIN; y2<screen_height-MARGIN; y2++) {
-					draw_pixel(XGRID1,y2,0xff);
-					draw_pixel(XGRID2,y2,0xff);
-					if(y2 == YGRID1) for (x=MARGIN; x < screen_width - MARGIN; x++) draw_pixel(x,y2,0xff);
-					if(y2 == YGRID2) for (x=MARGIN; x < screen_width - MARGIN; x++) draw_pixel(x,y2,0xff);
-				}
+				// disabled drawing the grid, the new way of drawing the
+				// overlay should leave the standard grid intact, allowing the
+				// custom grid to remain intact too.
 				if(shotTaken) draw_string(30, 10, strbuf, conf.osd_color);
+			}
+			// If a complete redraw was requested, decrement the request. That
+			// way we do it as much as it was requested, also in one run. Will
+			// cause some flickering, but better than nothing.
+			if( need_redraw )
+			{
+				--need_redraw;
 			}
 			return;
@@ -155,170 +352,7 @@
 	return;
 }
+
+// there used to be some commented out version here. it was confusing, so I
+// removed it. Its still in the svn anyways.
  
-
-/*// Code to test the idea of an edge overlay
-// Put  		edge_overlay(); 		after the line histogram_process(); 
- 
- 
-// Put the following after  the line #include "motion_detector.h" in main.c
-#include "gui_draw.h"
- 
-// until the edge thresh is put into conf structure I have hardcoded the threshold  see "thresh" below
-static char * imgbuf = 0;
- 
-#define MARGIN 30
-#define CALCYMARGIN 3
-#define EDGECOLOR 0x66
-#define NSTAGES 4
-#define XINC 6
-#define YINC 2
-#define XGRID1 120
-#define XGRID2 240
-#define YGRID1 80
-#define YGRID2 160
- 
-void edge_overlay(){
-	static int inmem=0;
-	static int viewport_height;
-	static int viewport_width;// screenwidth * 3
-	static int viewport_size;
-	static int shotTaken = 0;
-	static int imgmem = 0;
-	static int ymin = 0;
-	static  int thresh = 40;
-	static int xoffset = 0;
-	static int yoffset = 0;
-	static int full_press = 0;//cure for flaky behavior. due to multiple  returns to the scrip during one full press
-	static char strbuf[7] = "Frozen";
- 	static unsigned char *img;
-	int i, hi, c;
-	int x, y, h, v, ymax, y1, x1, y2;
-	char * ptrh1;
-	char * ptrh2;
-	char * ptrv1;
-	char * ptrv2;
-	char * optr;
- 
-//	if(!conf.edge_thresh) return;
- 
-	img = vid_get_viewport_fb();
-    viewport_height = vid_get_viewport_height();
-	viewport_width = screen_width * 3;
-    viewport_size = viewport_height * screen_width;
-	if(imgbuf == 0) imgbuf = malloc(viewport_size * 3);
- 
-	if((mode_get()&MODE_MASK) != MODE_PLAY) {
-		if (kbd_is_key_pressed(KEY_RIGHT)) {
-			xoffset -=XINC;
-		}
-		if (kbd_is_key_pressed(KEY_LEFT)) {
-			xoffset +=XINC;
-		}
-		if (kbd_is_key_pressed(KEY_DOWN)) {
-			yoffset -=YINC;
-		}
-		if (kbd_is_key_pressed(KEY_UP)) {
-			yoffset +=YINC;
-		}
- 
-		if (kbd_is_key_pressed(KEY_SHOOT_HALF)||kbd_is_key_pressed(KEY_SHOOT_FULL)) {
-			if (kbd_is_key_pressed(KEY_SHOOT_FULL) && !full_press) {
-				shotTaken = 1 - shotTaken;
-				memcpy(imgbuf,img,viewport_size * 3);
-				ymin = CALCYMARGIN;
-				inmem = 1;
-				full_press = 1;
-				xoffset = 0;
-				yoffset = 0;
-				return;
-			}
-			if(shotTaken) {
-				return;
-			}
-			memcpy(imgbuf,img,viewport_size * 3);
-			ymin = CALCYMARGIN;
-			inmem = 1;
-			xoffset = 0;
-			yoffset = 0;
-			return;
-		}
-		else full_press = 0;
-		if (inmem && (ymin < screen_height-CALCYMARGIN)) {
-			ymax = ymin + (screen_height - 2 * CALCYMARGIN) / NSTAGES;
-			if(ymax > screen_height - CALCYMARGIN) ymax = screen_height - CALCYMARGIN;
-			for (y=ymin; y<ymax; y++) {
-				ptrh1 = imgbuf + y * viewport_width + 7;
-				ptrh2 = imgbuf + y * viewport_width - 5;
-				ptrv1 = imgbuf + (y + 1) * viewport_width + 1;
-				ptrv2 = imgbuf + (y - 1) * viewport_width + 1;
-				optr = imgbuf + y * viewport_width + 3;
-				for (x=12; x<(screen_width- 4) * 3; x+=6) {
-					h = ptrh1[x] - ptrh2[x];
-					if(h  < 0) h = -h;
-					v = ptrv1[x] - ptrv2[x];
-					if(v  < 0) v = -v;
-					optr[x] = h + v;
-					h = ptrh1[x + 3] - ptrh2[x + 3];
-					if(h  < 0) h = -h;
-					v = ptrv1[x + 3] - ptrv2[x + 3];
-					if(v  < 0) v = -v;
-					optr[x + 2] = h + v;
-				}
-			}
-			ymin += (screen_height - 2 * CALCYMARGIN) / NSTAGES;
-			return;
-		}
-		if(inmem &&(ymin >= screen_height-CALCYMARGIN) && 
-			((gui_get_mode() == GUI_MODE_NONE) || (gui_get_mode() == GUI_MODE_ALT))){
-//				thresh = (conf.edge_thresh - 1) * 12;
-				for (y=MARGIN; y<screen_height-MARGIN; y++) {
-					y1 = y + yoffset;
-					if((y1 < CALCYMARGIN) || (y1 >= screen_height - CALCYMARGIN)) {
-						for (x=MARGIN; x < screen_width - MARGIN; x+=2) {
-							draw_pixel(x, y, 0);
-							draw_pixel(x+1, y, 0);
-						}
-					}
-					else {
-						for (x=MARGIN; x < screen_width - MARGIN; x+=2) {
-							x1 = x + xoffset;
-							if((x1 < 12) || (x1 >= screen_width-13)) {
-								draw_pixel(x, y, 0);
-								draw_pixel(x+1, y, 0);
-							}
-							else {
-								c = 0;
-								if(imgbuf[y1 * viewport_width + x1 * 3 + 3]  > thresh)
-									c = EDGECOLOR;
-								draw_pixel(x, y, c);
-								c = 0;
-								if(imgbuf[y1 * viewport_width + x1 * 3 + 5]  > thresh)
-									c = EDGECOLOR;
-								draw_pixel(x+1, y, c);
-							}
-						}
-				}
-				for (y2=MARGIN; y2<screen_height-MARGIN; y2++) {
-					draw_pixel(XGRID1,y2,0xff);
-					draw_pixel(XGRID2,y2,0xff);
-					if(y2 == YGRID1) for (x=MARGIN; x < screen_width - MARGIN; x++) draw_pixel(x,y2,0xff);
-					if(y2 == YGRID2) for (x=MARGIN; x < screen_width - MARGIN; x++) draw_pixel(x,y2,0xff);
-				}
-				if(shotTaken) draw_string(30, 10, strbuf, conf.osd_color);
-			}
-			return;
-		}
-	}
-	else {
-		full_press = 0;
-		inmem = 0;
-		shotTaken = 0;
-		ymin = 0;
-		xoffset = 0;
-		yoffset = 0;
-	}
-	return;
-}
- 
-//End of edge detector code.  next put  		edge_overlay(); 		after the line histogram_process(); 
-*/
+// vim: tabstop=4 shiftwidth=4
Index: /trunk/core/edgeoverlay.h
===================================================================
--- /trunk/core/edgeoverlay.h	(revision 579)
+++ /trunk/core/edgeoverlay.h	(revision 580)
@@ -2,16 +2,21 @@
 #define EDGE_OVERLAY_H
 
+// margin in which around the center nothing is displayed. Good for not
+// interfering too much with the OSD
 #define MARGIN 30
+// stuff influencing the algorithm
 #define CALCYMARGIN 3
-//#define EDGECOLOR 0x66
 #define NSTAGES 4
+// steps for up/down/left/right moving the overlay in ALT mode
 #define XINC 6
 #define YINC 2
-#define XGRID1 120
-#define XGRID2 240
-#define YGRID1 80
-#define YGRID2 160
+
+// if you change this, remember to change the mkdir in main too
+#define EDGE_SAVE_DIR "A/CHDK/EDGE"
 
 void edge_overlay();
+void save_edge_overlay(void);
+void load_edge_overlay( const char* );
+void free_memory_edge_overlay(void);
 
 #endif
Index: /trunk/core/gui.c
===================================================================
--- /trunk/core/gui.c	(revision 579)
+++ /trunk/core/gui.c	(revision 580)
@@ -44,4 +44,5 @@
 	#include "gui_logo.h"
 #endif
+#include "edgeoverlay.h"
 //-------------------------------------------------------------------
 
@@ -152,4 +153,8 @@
 static void gui_draw_load_lang(int arg);
 static void gui_menuproc_mkbootdisk(int arg);
+static void gui_menuproc_edge_save(int arg);
+static void gui_menuproc_edge_load(int arg);
+static void gui_menuproc_edge_free(int arg);
+
 #ifndef OPTIONS_AUTOSAVE
 static void gui_menuproc_save(int arg);
@@ -394,8 +399,9 @@
     {0x33,LANG_MENU_DEBUG_SWAP_PART,         MENUITEM_PROC, 	    	(int*)gui_menuproc_swap_patitons },
 #endif
+    {0x2b,LANG_MENU_MAIN_RESET_OPTIONS,      MENUITEM_PROC,      (int*)gui_menuproc_reset },
 #ifdef OPT_DEBUGGING
     {0x2a,LANG_MENU_MAIN_DEBUG,              MENUITEM_SUBMENU,   (int*)&debug_submenu },
 #endif
-    {0x2b,LANG_MENU_MAIN_RESET_OPTIONS,      MENUITEM_PROC,      (int*)gui_menuproc_reset },
+    {0x86,LANG_MENU_REMOTE_PARAM,            MENUITEM_SUBMENU,   (int*)&remote_submenu },
     {0x51,LANG_MENU_BACK,                    MENUITEM_UP },
     {0},
@@ -576,8 +582,13 @@
 #ifdef OPT_EDGEOVERLAY
 static CMenuItem edge_overlay_submenu_items[] = {
-    {0x7f,LANG_MENU_EDGE_OVERLAY_ENABLE,     MENUITEM_BOOL,          &conf.edge_overlay_enable },
+    {0x5c,LANG_MENU_EDGE_OVERLAY_ENABLE,     MENUITEM_BOOL,          &conf.edge_overlay_enable },
+    {0x33,LANG_MENU_EDGE_SAVE,			MENUITEM_PROC,		(int*)gui_menuproc_edge_save },
+    {0x5c,LANG_MENU_EDGE_ZOOM,     MENUITEM_BOOL,          &conf.edge_overlay_zoom },
+    {0x5c,LANG_MENU_EDGE_LOCK,     MENUITEM_BOOL,          &conf.edge_overlay_lock },
     {0x7f,LANG_MENU_EDGE_OVERLAY_TRESH,      MENUITEM_INT|MENUITEM_F_UNSIGNED|MENUITEM_F_MINMAX, &conf.edge_overlay_thresh, MENU_MINMAX(0, 255)},
     {0x65,LANG_MENU_EDGE_OVERLAY_COLOR,      MENUITEM_COLOR_FG,      (int*)&conf.edge_overlay_color },
-
+    {0x5c,LANG_MENU_EDGE_PLAY,			MENUITEM_BOOL,		&conf.edge_overlay_play }, //does not work on cams like s-series, which dont have a real "hardware" play/rec switch, need a workaround, probably another button
+    {0x33,LANG_MENU_EDGE_FREE,			MENUITEM_PROC,		(int*)gui_menuproc_edge_free },
+    {0x33,LANG_MENU_EDGE_LOAD,			MENUITEM_PROC,		(int*)gui_menuproc_edge_load },
     {0x51,LANG_MENU_BACK,                    MENUITEM_UP },
     {0}
@@ -683,7 +694,4 @@
     {0x59,LANG_MENU_OSD_TEMP_FAHRENHEIT,      MENUITEM_BOOL,      &conf.temperature_unit},
     {0x72,LANG_MENU_OSD_LAYOUT_EDITOR,       MENUITEM_PROC,      (int*)gui_draw_osd_le },
-#ifdef OPT_EDGEOVERLAY
-    {0x7f,LANG_MENU_EDGE_OVERLAY,         MENUITEM_SUBMENU,   (int*)&edge_overlay_submenu },
-#endif
     {0x2f,LANG_MENU_OSD_GRID_PARAMS,         MENUITEM_SUBMENU,   (int*)&grid_submenu },
     {0x22,LANG_MENU_OSD_VALUES,  	    	MENUITEM_SUBMENU,   (int*)&values_submenu },
@@ -786,13 +794,15 @@
 #endif
     {0x24,LANG_MENU_MAIN_RAW_PARAM,          MENUITEM_SUBMENU,   (int*)&raw_submenu },
+#ifdef OPT_EDGEOVERLAY
+    {0x7f,LANG_MENU_EDGE_OVERLAY,         MENUITEM_SUBMENU,   (int*)&edge_overlay_submenu },
+#endif
+#ifdef OPT_CURVES
+    {0x85,LANG_MENU_CURVE_PARAM,             MENUITEM_SUBMENU,   (int*)&curve_submenu },
+#endif
+    {0x25,LANG_MENU_MAIN_HISTO_PARAM,        MENUITEM_SUBMENU,   (int*)&histo_submenu },
+    {0x26,LANG_MENU_MAIN_ZEBRA_PARAM,        MENUITEM_SUBMENU,   (int*)&zebra_submenu },
     {0x22,LANG_MENU_MAIN_OSD_PARAM,          MENUITEM_SUBMENU,   (int*)&osd_submenu },
     {0x28,LANG_MENU_MAIN_VISUAL_PARAM,       MENUITEM_SUBMENU,   (int*)&visual_submenu },
-    {0x25,LANG_MENU_MAIN_HISTO_PARAM,        MENUITEM_SUBMENU,   (int*)&histo_submenu },
-    {0x26,LANG_MENU_MAIN_ZEBRA_PARAM,        MENUITEM_SUBMENU,   (int*)&zebra_submenu },
     {0x27,LANG_MENU_MAIN_SCRIPT_PARAM,       MENUITEM_SUBMENU,   (int*)&script_submenu },
-#ifdef OPT_CURVES
-    {0x85,LANG_MENU_CURVE_PARAM,             MENUITEM_SUBMENU,   (int*)&curve_submenu },
-#endif
-    {0x86,LANG_MENU_REMOTE_PARAM,            MENUITEM_SUBMENU,   (int*)&remote_submenu },
     {0x29,LANG_MENU_MAIN_MISC,               MENUITEM_SUBMENU,   (int*)&misc_submenu },
 #ifndef OPTIONS_AUTOSAVE
@@ -1869,4 +1879,9 @@
 //		if (conf.zoom_override) shooting_set_zoom(conf.zoom_override_value);
 #endif
+}
+
+static void gui_load_edge_selected( const char* fn ) {
+    if( fn )
+	load_edge_overlay(fn);
 }
 
@@ -2903,4 +2918,28 @@
 }
 
+void gui_menuproc_edge_free(int arg) {
+    free_memory_edge_overlay();
+}
+
+void gui_menuproc_edge_save(int arg) {
+    save_edge_overlay();
+}
+
+void gui_menuproc_edge_load(int arg) {
+    DIR   *d;
+    char  *path = EDGE_SAVE_DIR;
+    const char* fn;
+
+    // if exists, go into
+    d=opendir(path);
+    if (d) {
+        closedir(d);
+    } else {
+        path="A";
+    }
+
+    gui_fselect_init(LANG_MENU_EDGE_LOAD, path, gui_load_edge_selected);
+}
+
 //-------------------------------------------------------------------
 #ifdef OPT_CALENDAR
@@ -3037,2 +3076,4 @@
 	}
 }
+
+
Index: /trunk/core/main.c
===================================================================
--- /trunk/core/main.c	(revision 579)
+++ /trunk/core/main.c	(revision 580)
@@ -104,4 +104,7 @@
     mkdir("A/CHDK/DATA");
     mkdir("A/CHDK/LOGS");
+#ifdef EDGEOVERLAY
+    mkdir("A/CHDK/EDGE");
+#endif
     auto_started = 0;
 
Index: /trunk/version.inc
===================================================================
--- /trunk/version.inc	(revision 579)
+++ /trunk/version.inc	(revision 580)
@@ -1,1 +1,1 @@
-BUILD_NUMBER := 0.7.7
+BUILD_NUMBER := 0.8.0
Index: /trunk/doc/version.txt
===================================================================
--- /trunk/doc/version.txt	(revision 579)
+++ /trunk/doc/version.txt	(revision 580)
@@ -2,4 +2,27 @@
 
 version / revision / author
+
+0.8.0 / #780 / PhyrePhoX
+
+tadaa! major pimping of an already cool feature!
+you can now SAVE and LOAD edge overlays! this was written by PlasmaHH (shy guy, only in irc :D)
+Yes, you read it right:
+- save an edge overlay: create an overlay (enable overlay and press half-press) -> go to overlay menu and press save
+- load an overlay (go to menu and choose an *.edg file)
+- create overlays from jpgs in playmode! (only works on cameras that have a "hardware" switch of play/recmode for now, because on for example s3is halfpressing the shutter activates rec mode!
+- free memory by using the item in the edge menu (also you should disable edge-overlay)
+changes / enhancements to the mod by me: 
+- together with the edge overlay the zoom setting is saved, so when you load the file after one year it zooms to the position your camera had when you shot it!
+- added the option so that an edge overlay is "locked", meaning the edgeoverlay you loaded or just created is not overwritten in the osd at half-press (this checkbox is overwritten on each camera startup... no big deal, but i dont like it like that right now)
+This is a really great feature (for example for LONG-TERM TIMELAPSES, or stop-motion movies, or vertigo-effect, or stereography... the list is endless :D)
+
+* restructured the root menu (put imo the most often used items to the top, moved edge overlay from OSD menu to the root menu, moved remote params menu to the misc menu)
+
+because of this new feature and all the new cams i upped the version to 0.8.0 already...
+P.S: had to rewrite some of PlasmaHHs stuff (e.g. write -> fwrite), i hope i did everything correctly (it's working flawlessly on s3is and a620)
+
+0.7.7 / #578-579 / php
+
+* small fixes
 
 0.7.7 / #577 / php
Index: /trunk/CHDK/LANG/english.lng
===================================================================
--- /trunk/CHDK/LANG/english.lng	(revision 579)
+++ /trunk/CHDK/LANG/english.lng	(revision 580)
@@ -556,3 +556,8 @@
 415 "add raw suffix"
 416 "  in Fahrenheit"
-
+417 "Load Edge Overlay"
+418 "Save Edge Overlay"
+419 "Enable in Play"
+420 "Free internal Memory"
+421 "Load+Set Zoom"
+422 "Lock Edge Overlay"
Index: /trunk/CHDK/LANG/german.lng
===================================================================
--- /trunk/CHDK/LANG/german.lng	(revision 579)
+++ /trunk/CHDK/LANG/german.lng	(revision 580)
@@ -586,2 +586,8 @@
 415 "Raw Suffix"
 416 "  in Fahrenheit"
+417 "Lade Edge Overlay"
+418 "Speicher Edge Overlay"
+419 "Auch im Playmode"
+420 "Gib Speicher frei"
+421 "Lade+Setze Zoom"
+422 "Sperre Odge Overlay"
