[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [54096] trunk/blender/source/blender/ compositor/operations/COM_DilateErodeOperation.cpp: committed patch [#33972 ] dilate/erode optimization

Monique Dewanchand m.dewanchand at atmind.nl
Fri Jan 25 10:47:32 CET 2013


Revision: 54096
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=54096
Author:   mdewanchand
Date:     2013-01-25 09:47:28 +0000 (Fri, 25 Jan 2013)
Log Message:
-----------
committed patch [#33972] dilate/erode optimization

this patch optimizes the dilate/erode step method (hopefully without any functional change),
making its speed not depend on the distance anymore.

Couldn't detect funtional changes so committing. Haven't tested for speed gain.

 * credits to erwin94 David M

Modified Paths:
--------------
    trunk/blender/source/blender/compositor/operations/COM_DilateErodeOperation.cpp

Modified: trunk/blender/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
===================================================================
--- trunk/blender/source/blender/compositor/operations/COM_DilateErodeOperation.cpp	2013-01-25 07:31:29 UTC (rev 54095)
+++ trunk/blender/source/blender/compositor/operations/COM_DilateErodeOperation.cpp	2013-01-25 09:47:28 UTC (rev 54096)
@@ -337,38 +337,73 @@
 		MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL);
 		float *rectf = buffer->convertToValueBuffer();
 		int x, y, i;
-		float *p;
 		int bwidth = buffer->getWidth();
 		int bheight = buffer->getHeight();
-		for (i = 0; i < this->m_iterations; i++) {
-			for (y = 0; y < bheight; y++) {
-				for (x = 0; x < bwidth - 1; x++) {
-					p = rectf + (bwidth * y + x);
-					*p = max(*p, *(p + 1));
+
+		/*
+		  The following is based on the van Herk/Gil-Werman algorithm for morphology operations.
+		 */
+		int half_window = this->m_iterations;
+		int window = half_window * 2 + 1;
+		float *temp = (float *)MEM_mallocN((2*window - 1) * sizeof(float), "dilate erode temp");
+		float *buf = (float *)MEM_mallocN((max(bwidth, bheight) + 5*half_window) * sizeof(float), "dilate erode buf");
+
+		for (y = 0; y < bheight; y++) {
+			for (x = 0; x < window - 1; x++) {
+				buf[x] = -MAXFLOAT;
+			}
+			for (x = 0; x < bwidth; x++) {
+				buf[x + window - 1] = rectf[bwidth * y + x];
+			}
+			for (x = bwidth + window - 1; x < bwidth + 5*half_window; x++) {
+				buf[x] = -MAXFLOAT;
+			}
+
+			for(i = 0; i < (bwidth + 3*half_window) / window; i++) {
+				int start = (i + 1) * window - 1;
+
+				temp[window - 1] = buf[start];
+				for (x = 1; x < window; x++) {
+					temp[window - 1 - x] = max(temp[window - x], buf[start - x]);
+					temp[window - 1 + x] = max(temp[window + x - 2], buf[start + x]);
 				}
+
+				start = half_window + (i-1) * window + 1;
+				for (x = -min(0, start); x < window - max(0, start+window - bwidth); x++) {
+					rectf[bwidth * y + (start + x)] = max(temp[x], temp[x + window - 1]);
+				}
 			}
-		
+		}
+
+		for (x = 0; x < bwidth; x++) {
+			for (y = 0; y < window - 1; y++) {
+				buf[y] = -MAXFLOAT;
+			}
 			for (y = 0; y < bheight; y++) {
-				for (x = bwidth - 1; x >= 1; x--) {
-					p = rectf + (bwidth * y + x);
-					*p = max(*p, *(p - 1));
-				}
+				buf[y + window - 1] = rectf[bwidth * y + x];
 			}
-		
-			for (x = 0; x < bwidth; x++) {
-				for (y = 0; y < bheight - 1; y++) {
-					p = rectf + (bwidth * y + x);
-					*p = max(*p, *(p + bwidth));
-				}
+			for (y = bheight + window - 1; y < bheight + 5*half_window; y++) {
+				buf[y] = -MAXFLOAT;
 			}
-		
-			for (x = 0; x < bwidth; x++) {
-				for (y = bheight - 1; y >= 1; y--) {
-					p = rectf + (bwidth * y + x);
-					*p = max(*p, *(p - bwidth));
+
+			for(i = 0; i < (bheight + 3*half_window) / window; i++) {
+				int start = (i + 1) * window - 1;
+
+				temp[window - 1] = buf[start];
+				for (y = 1; y < window; y++) {
+					temp[window - 1 - y] = max(temp[window - y], buf[start - y]);
+					temp[window - 1 + y] = max(temp[window + y - 2], buf[start + y]);
 				}
+
+				start = half_window + (i-1) * window + 1;
+				for (y = -min(0, start); y < window - max(0, start+window - bheight); y++) {
+					rectf[bwidth * (y + start) + x] = max(temp[y], temp[y + window - 1]);
+				}
 			}
 		}
+
+		MEM_freeN(temp);
+		MEM_freeN(buf);
 		this->m_cached_buffer = rectf;
 	}
 	unlockMutex();
@@ -424,38 +459,70 @@
 		MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL);
 		float *rectf = buffer->convertToValueBuffer();
 		int x, y, i;
-		float *p;
 		int bwidth = buffer->getWidth();
 		int bheight = buffer->getHeight();
-		for (i = 0; i < this->m_iterations; i++) {
-			for (y = 0; y < bheight; y++) {
-				for (x = 0; x < bwidth - 1; x++) {
-					p = rectf + (bwidth * y + x);
-					*p = MIN2(*p, *(p + 1));
+
+		int half_window = this->m_iterations;
+		int window = half_window * 2 + 1;
+		float *temp = (float *)MEM_mallocN((2*window - 1) * sizeof(float), "dilate erode temp");
+		float *buf = (float *)MEM_mallocN((max(bwidth, bheight) + 5*half_window) * sizeof(float), "dilate erode buf");
+
+		for (y = 0; y < bheight; y++) {
+			for (x = 0; x < window - 1; x++) {
+				buf[x] = MAXFLOAT;
+			}
+			for (x = 0; x < bwidth; x++) {
+				buf[x + window - 1] = rectf[bwidth * y + x];
+			}
+			for (x = bwidth + window - 1; x < bwidth + 5*half_window; x++) {
+				buf[x] = MAXFLOAT;
+			}
+
+			for(i = 0; i < (bwidth + 3*half_window) / window; i++) {
+				int start = (i + 1) * window - 1;
+
+				temp[window - 1] = buf[start];
+				for (x = 1; x < window; x++) {
+					temp[window - 1 - x] = min(temp[window - x], buf[start - x]);
+					temp[window - 1 + x] = min(temp[window + x - 2], buf[start + x]);
 				}
+
+				start = half_window + (i-1) * window + 1;
+				for (x = -min(0, start); x < window - max(0, start+window - bwidth); x++) {
+					rectf[bwidth * y + (start + x)] = min(temp[x], temp[x + window - 1]);
+				}
 			}
-		
+		}
+
+		for (x = 0; x < bwidth; x++) {
+			for (y = 0; y < window - 1; y++) {
+				buf[y] = MAXFLOAT;
+			}
 			for (y = 0; y < bheight; y++) {
-				for (x = bwidth - 1; x >= 1; x--) {
-					p = rectf + (bwidth * y + x);
-					*p = MIN2(*p, *(p - 1));
-				}
+				buf[y + window - 1] = rectf[bwidth * y + x];
 			}
-		
-			for (x = 0; x < bwidth; x++) {
-				for (y = 0; y < bheight - 1; y++) {
-					p = rectf + (bwidth * y + x);
-					*p = MIN2(*p, *(p + bwidth));
-				}
+			for (y = bheight + window - 1; y < bheight + 5*half_window; y++) {
+				buf[y] = MAXFLOAT;
 			}
-		
-			for (x = 0; x < bwidth; x++) {
-				for (y = bheight - 1; y >= 1; y--) {
-					p = rectf + (bwidth * y + x);
-					*p = MIN2(*p, *(p - bwidth));
+
+			for(i = 0; i < (bheight + 3*half_window) / window; i++) {
+				int start = (i + 1) * window - 1;
+
+				temp[window - 1] = buf[start];
+				for (y = 1; y < window; y++) {
+					temp[window - 1 - y] = min(temp[window - y], buf[start - y]);
+					temp[window - 1 + y] = min(temp[window + y - 2], buf[start + y]);
 				}
+
+				start = half_window + (i-1) * window + 1;
+				for (y = -min(0, start); y < window - max(0, start+window - bheight); y++) {
+					rectf[bwidth * (y + start) + x] = min(temp[y], temp[y + window - 1]);
+				}
 			}
 		}
+
+		MEM_freeN(temp);
+		MEM_freeN(buf);
 		this->m_cached_buffer = rectf;
 	}
 	unlockMutex();




More information about the Bf-blender-cvs mailing list