Index: source/blender/compositor/operations/COM_DilateErodeOperation.cpp =================================================================== --- source/blender/compositor/operations/COM_DilateErodeOperation.cpp (revision 49166) +++ source/blender/compositor/operations/COM_DilateErodeOperation.cpp (working copy) @@ -334,39 +334,75 @@ if (this->m_cached_buffer == NULL) { MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); float *rectf = buffer->convertToValueBuffer(); - int x, y, i; + int x, y; float *p; int bwidth = buffer->getWidth(); int bheight = buffer->getHeight(); - for (i = 0; i < this->m_iterations; i++) { + int bsize = MAX2(bwidth, bheight); + int distance = this->m_iterations; + if (distance != 0) { + // maxleft[i] := maximum of p[i - i%distance] ... p[i], inclusively + float *maxleft = new float[bsize]; + // maxright[i] := maximum of p[i] ... p[i - i%distance + distance - 1], inclusively + // That means, maxright[i - i%distance] := maximum of the whole distance-wide block + float *maxright = new float[bsize]; + float v; + for (y = 0; y < bheight; y++) { - for (x = 0; x < bwidth - 1; x++) { - p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p + 1)); + p = rectf + bwidth * y; + maxleft[0] = maxright[0] = p[0]; + for (x = 1; x < bwidth; x++) { + v = p[x]; + maxright[x] = v; + if (x % distance && maxleft[x-1] > v) + maxleft[x] = maxleft[x-1]; + else + maxleft[x] = v; } - } - - for (y = 0; y < bheight; y++) { - for (x = bwidth - 1; x >= 1; x--) { - p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p - 1)); + + for (x = bwidth-2; x >= 0; x--) { + if ((x+1) % distance && maxright[x+1] > maxright[x]) + maxright[x] = maxright[x+1]; } + + // Get the actual maximum as maximum of the current distance-wide block and adequate parts of the neighbors + for (x = 0; x < distance; x++) + p[x] = MAX2(maxright[0], maxleft[x+distance]); + for (; x < bwidth-distance; x++) + p[x] = MAX3(maxright[x - x%distance], maxright[x-distance], maxleft[x+distance]); + for (; x < bwidth; x++) + p[x] = MAX2(maxright[x - x%distance], maxright[x-distance]); } - + + // Process all columns in the same manner for (x = 0; x < bwidth; x++) { - for (y = 0; y < bheight - 1; y++) { - p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p + bwidth)); + p = rectf + x; + maxleft[0] = maxright[0] = p[0]; + for (y = 1; y < bheight; y++) { + v = p[y*bwidth]; + maxright[y] = v; + if (y % distance && maxleft[y-1] > v) + maxleft[y] = maxleft[y-1]; + else + maxleft[y] = v; } - } - - for (x = 0; x < bwidth; x++) { - for (y = bheight - 1; y >= 1; y--) { - p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p - bwidth)); + + for (y = bheight-2; y >= 0; y--) { + if ((y+1) % distance && maxright[y+1] > maxright[y]) + maxright[y] = maxright[y+1]; } + + for (y = 0; y < distance; y++) + p[y*bwidth] = MAX2(maxleft[y+distance], maxright[0]); + for (; y < bheight-distance; y++) + p[y*bwidth] = MAX3(maxleft[y+distance], maxright[y - y%distance], maxright[y-distance]); + for (; y < bheight; y++) + p[y*bwidth] = MAX2(maxright[y - y%distance], maxright[y-distance]); } + delete maxleft; + delete maxright; } + this->m_cached_buffer = rectf; } unlockMutex(); @@ -421,39 +457,76 @@ if (this->m_cached_buffer == NULL) { MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); float *rectf = buffer->convertToValueBuffer(); - int x, y, i; + int x, y; float *p; int bwidth = buffer->getWidth(); int bheight = buffer->getHeight(); - for (i = 0; i < this->m_iterations; i++) { + + int bsize = MAX2(bwidth, bheight); + int distance = this->m_iterations; + if (distance != 0) { + // minleft[i] := minimum of p[i - i%distance] ... p[i], inclusively + float *minleft = new float[bsize]; + // minright[i] := minimum of p[i] ... p[i - i%distance + distance - 1], inclusively + // That means, minright[i - i%distance] := minimum of the whole distance-wide block + float *minright = new float[bsize]; + float v; + for (y = 0; y < bheight; y++) { - for (x = 0; x < bwidth - 1; x++) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p + 1)); + p = rectf + bwidth * y; + minleft[0] = minright[0] = p[0]; + for (x = 1; x < bwidth; x++) { + v = p[x]; + minright[x] = v; + if (x % distance && minleft[x-1] < v) + minleft[x] = minleft[x-1]; + else + minleft[x] = v; } - } - - for (y = 0; y < bheight; y++) { - for (x = bwidth - 1; x >= 1; x--) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p - 1)); + + for (x = bwidth-2; x >= 0; x--) { + if ((x+1) % distance && minright[x+1] < minright[x]) + minright[x] = minright[x+1]; } + + // Get the actual minimum as minimum of the current distance-wide block and adequate parts of the neighbors + for (x = 0; x < distance; x++) + p[x] = MIN2(minleft[x+distance], minright[0]); + for (; x < bwidth-distance; x++) + p[x] = MIN3(minleft[x+distance], minright[x - x%distance], minright[x-distance]); + for (; x < bwidth; x++) + p[x] = MIN2(minright[x - x%distance], minright[x-distance]); } - + + // Process all columns in the same manner for (x = 0; x < bwidth; x++) { - for (y = 0; y < bheight - 1; y++) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p + bwidth)); + p = rectf + x; + minleft[0] = minright[0] = p[0]; + for (y = 1; y < bheight; y++) { + v = p[y*bwidth]; + minright[y] = v; + if (y % distance && minleft[y-1] < v) + minleft[y] = minleft[y-1]; + else + minleft[y] = v; } - } - - for (x = 0; x < bwidth; x++) { - for (y = bheight - 1; y >= 1; y--) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p - bwidth)); + + for (y = bheight-2; y >= 0; y--) { + if ((y+1) % distance && minright[y+1] < minright[y]) + minright[y] = minright[y+1]; } + + for (y = 0; y < distance; y++) + p[y*bwidth] = MIN2(minleft[y+distance], minright[0]); + for (; y < bheight-distance; y++) + p[y*bwidth] = MIN3(minleft[y+distance], minright[y - y%distance], minright[y-distance]); + for (; y < bheight; y++) + p[y*bwidth] = MIN2(minright[y - y%distance], minright[y-distance]); } + delete minleft; + delete minright; } + this->m_cached_buffer = rectf; } unlockMutex();