jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=c7616dd73835cd3918e65a4c105745461e6c312d

commit c7616dd73835cd3918e65a4c105745461e6c312d
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Thu Mar 20 18:26:04 2014 +0900

    Evas filters: Fix blur corner cases with small images
    
    If the buffer size is smaller than the blurring kernel, then
    special precautions must be taken to properly read the source
    pixels. Also, fix the corner cases near the left & right edges
    (or top & bottom).
---
 src/lib/evas/filters/blur/blur_box_alpha_.c | 94 +++++++++++++--------------
 src/lib/evas/filters/blur/blur_box_rgba_.c  | 98 ++++++++++++++++-------------
 src/lib/evas/filters/evas_filter_blur.c     |  8 ---
 3 files changed, 102 insertions(+), 98 deletions(-)

diff --git a/src/lib/evas/filters/blur/blur_box_alpha_.c 
b/src/lib/evas/filters/blur/blur_box_alpha_.c
index 71ac943..4257a5e 100644
--- a/src/lib/evas/filters/blur/blur_box_alpha_.c
+++ b/src/lib/evas/filters/blur/blur_box_alpha_.c
@@ -32,6 +32,8 @@ _box_blur_alpha_horiz_step(const DATA8* restrict const 
srcdata,
 
    span1 = alloca(len);
    span2 = alloca(len);
+   memset(span1, 0, len);
+   memset(span2, 0, len);
 
    // For each line, apply as many blurs as requested
    for (int l = 0; l < loops; l++)
@@ -50,8 +52,6 @@ _box_blur_alpha_horiz_step(const DATA8* restrict const 
srcdata,
           {
              const int radius = radii[run];
              const int left = MIN(radius, len);
-             const int right = MIN(radius, (len - radius));
-             int acc = 0;
 
 #if DIV_USING_BITSHIFT
              const int pow2 = pow2_shifts[run];
@@ -60,44 +60,46 @@ _box_blur_alpha_horiz_step(const DATA8* restrict const 
srcdata,
              const int divider = 2 * radius + 1;
 #endif
 
-             const DATA8* restrict sr = src;
              const DATA8* restrict sl = src;
+             const DATA8* restrict sr = src;
+             const DATA8* restrict sre = src + len;
+             const DATA8* restrict sle = src + len - radius;
              DATA8* restrict d = dst;
+             int acc = 0, count = 0;
 
              // Read-ahead & accumulate
-             for (int k = left; k; k--)
+             for (int x = left; x > 0; x--)
                {
-                  acc += *sr;
-                  sr += 1;
+                  acc += *sr++;
+                  count++;
                }
 
              // Left edge
-             for (int k = 0; k < left; k++)
+             for (int x = left; x > 0; x--)
                {
-                  acc += *sr;
-                  *d = acc / (k + left + 1);
-                  sr += 1;
-                  d += 1;
+                  if (sr < sre)
+                    {
+                       acc += *sr++;
+                       count++;
+                    }
+
+                  *d++ = acc / count;
                }
 
              // Middle part, normal blur
-             for (int k = len - (2 * radius); k; k--)
+             while (sr < sre)
                {
-                  acc += *sr;
-                  *d = DIVIDE(acc);
-                  acc -= *sl;
-                  sl += 1;
-                  sr += 1;
-                  d += 1;
+                  acc += *sr++;
+                  *d++ = DIVIDE(acc);
+                  acc -= *sl++;
                }
 
              // Right edge
-             for (int k = right; k; k--)
+             count = 2 * radius + 1;
+             while (sl < sle)
                {
-                  *d = acc / (k + right);
-                  acc -= *sl;
-                  d += 1;
-                  sl += 1;
+                  *d++ = acc / (--count);
+                  acc -= *sl++;
                }
 
              // More runs to go: swap spans
@@ -177,8 +179,6 @@ _box_blur_alpha_vert_step(const DATA8* restrict const 
srcdata,
           {
              const int radius = radii[run];
              const int left = MIN(radius, len);
-             const int right = MIN(radius, (len - radius));
-             int acc = 0;
 
 #if DIV_USING_BITSHIFT
              const int pow2 = pow2_shifts[run];
@@ -187,44 +187,46 @@ _box_blur_alpha_vert_step(const DATA8* restrict const 
srcdata,
              const int divider = 2 * radius + 1;
 #endif
 
-             const DATA8* restrict sr = src;
              const DATA8* restrict sl = src;
+             const DATA8* restrict sr = src;
+             const DATA8* restrict sre = src + len;
+             const DATA8* restrict sle = src + len - radius;
              DATA8* restrict d = dst;
+             int acc = 0, count = 0;
 
              // Read-ahead & accumulate
-             for (int k = left; k; k--)
+             for (int x = left; x > 0; x--)
                {
-                  acc += *sr;
-                  sr += 1;
+                  acc += *sr++;
+                  count++;
                }
 
              // Left edge
-             for (int k = 0; k < left; k++)
+             for (int x = left; x > 0; x--)
                {
-                  acc += *sr;
-                  *d = acc / (k + left + 1);
-                  sr += 1;
-                  d += 1;
+                  if (sr < sre)
+                    {
+                       acc += *sr++;
+                       count++;
+                    }
+
+                  *d++ = acc / count;
                }
 
              // Middle part, normal blur
-             for (int k = len - (2 * radius); k; k--)
+             while (sr < sre)
                {
-                  acc += *sr;
-                  *d = DIVIDE(acc);
-                  acc -= *sl;
-                  sl += 1;
-                  sr += 1;
-                  d += 1;
+                  acc += *sr++;
+                  *d++ = DIVIDE(acc);
+                  acc -= *sl++;
                }
 
              // Right edge
-             for (int k = right; k; k--)
+             count = 2 * radius + 1;
+             while (sl < sle)
                {
-                  *d = acc / (k + right);
-                  acc -= *sl;
-                  d += 1;
-                  sl += 1;
+                  *d++ = acc / (--count);
+                  acc -= *sl++;
                }
 
              // More runs to go: swap spans
diff --git a/src/lib/evas/filters/blur/blur_box_rgba_.c 
b/src/lib/evas/filters/blur/blur_box_rgba_.c
index 95d381a..7c22c65 100644
--- a/src/lib/evas/filters/blur/blur_box_rgba_.c
+++ b/src/lib/evas/filters/blur/blur_box_rgba_.c
@@ -32,6 +32,8 @@ _box_blur_horiz_rgba_step(const DATA32* restrict const 
srcdata,
 
    span1 = alloca(len * sizeof(DATA32));
    span2 = alloca(len * sizeof(DATA32));
+   memset(span1, 0, len * sizeof(DATA32));
+   memset(span2, 0, len * sizeof(DATA32));
 
    // For each line, apply as many blurs as requested
    for (int l = 0; l < loops; l++)
@@ -50,7 +52,6 @@ _box_blur_horiz_rgba_step(const DATA32* restrict const 
srcdata,
           {
              const int radius = radii[run];
              const int left = MIN(radius, len);
-             const int right = MIN(radius, (len - radius));
 
 #if DIV_USING_BITSHIFT
              const int pow2 = pow2_shifts[run];
@@ -61,39 +62,44 @@ _box_blur_horiz_rgba_step(const DATA32* restrict const 
srcdata,
 
              const DATA8* restrict sl = (DATA8 *) src;
              const DATA8* restrict sr = (DATA8 *) src;
+             const DATA8* restrict sre = (DATA8 *) (src + len);
+             const DATA8* restrict sle = (DATA8 *) (src + len - radius);
              DATA8* restrict d = (DATA8 *) dst;
              int acc[4] = {0};
-             int x, k;
+             int count = 0;
 
              // Read-ahead
-             for (x = left; x; x--)
+             for (int x = left; x > 0; x--)
                {
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] += sr[k];
                   sr += sizeof(DATA32);
+                  count++;
                }
 
              // Left
-             for (x = 0; x < left; x++)
+             for (int x = left; x > 0; x--)
                {
-                  for (k = 0; k < 4; k++)
-                    acc[k] += sr[k];
-                  sr += sizeof(DATA32);
+                  if (sr < sre)
+                    {
+                       for (int k = 0; k < 4; k++)
+                         acc[k] += sr[k];
+                       sr += sizeof(DATA32);
+                       count++;
+                    }
 
-                  const int divider = x + left + 1;
-                  d[ALPHA] = acc[ALPHA] / divider;
-                  d[RED]   = acc[RED]   / divider;
-                  d[GREEN] = acc[GREEN] / divider;
-                  d[BLUE]  = acc[BLUE]  / divider;
+                  d[ALPHA] = acc[ALPHA] / count;
+                  d[RED]   = acc[RED]   / count;
+                  d[GREEN] = acc[GREEN] / count;
+                  d[BLUE]  = acc[BLUE]  / count;
                   d += sizeof(DATA32);
                }
 
              // Main part
-             for (x = len - (2 * radius); x > 0; x--)
+             for (; sr < sre; sr += sizeof(DATA32), sl += sizeof(DATA32))
                {
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] += sr[k];
-                  sr += sizeof(DATA32);
 
                   d[ALPHA] = DIVIDE(acc[ALPHA]);
                   d[RED]   = DIVIDE(acc[RED]);
@@ -101,24 +107,23 @@ _box_blur_horiz_rgba_step(const DATA32* restrict const 
srcdata,
                   d[BLUE]  = DIVIDE(acc[BLUE]);
                   d += sizeof(DATA32);
 
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] -= sl[k];
-                  sl += sizeof(DATA32);
                }
 
              // Right part
-             for (x = right; x; x--)
+             count = 2 * radius + 1;
+             for (; sl < sle; sl += sizeof(DATA32))
                {
-                  const int divider = x + right;
+                  const int divider = --count;
                   d[ALPHA] = acc[ALPHA] / divider;
                   d[RED]   = acc[RED]   / divider;
                   d[GREEN] = acc[GREEN] / divider;
                   d[BLUE]  = acc[BLUE]  / divider;
                   d += sizeof(DATA32);
 
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] -= sl[k];
-                  sl += sizeof(DATA32);
                }
 
              // More runs to go: swap spans
@@ -173,6 +178,8 @@ _box_blur_vert_rgba_step(const DATA32* restrict const 
srcdata,
 
    span1 = alloca(len * sizeof(DATA32));
    span2 = alloca(len * sizeof(DATA32));
+   memset(span1, 0, len * sizeof(DATA32));
+   memset(span2, 0, len * sizeof(DATA32));
 
    // For each line, apply as many blurs as requested
    for (int l = 0; l < loops; l++)
@@ -196,7 +203,6 @@ _box_blur_vert_rgba_step(const DATA32* restrict const 
srcdata,
           {
              const int radius = radii[run];
              const int left = MIN(radius, len);
-             const int right = MIN(radius, (len - radius));
 
 #if DIV_USING_BITSHIFT
              const int pow2 = pow2_shifts[run];
@@ -207,39 +213,44 @@ _box_blur_vert_rgba_step(const DATA32* restrict const 
srcdata,
 
              const DATA8* restrict sl = (DATA8 *) src;
              const DATA8* restrict sr = (DATA8 *) src;
+             const DATA8* restrict sre = (DATA8 *) (src + len);
+             const DATA8* restrict sle = (DATA8 *) (src + len - radius);
              DATA8* restrict d = (DATA8 *) dst;
              int acc[4] = {0};
-             int x, k;
+             int count = 0;
 
              // Read-ahead
-             for (x = left; x; x--)
+             for (int x = left; x > 0; x--)
                {
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] += sr[k];
                   sr += sizeof(DATA32);
+                  count++;
                }
 
              // Left
-             for (x = 0; x < left; x++)
+             for (int x = left; x > 0; x--)
                {
-                  for (k = 0; k < 4; k++)
-                    acc[k] += sr[k];
-                  sr += sizeof(DATA32);
+                  if (sr < sre)
+                    {
+                       for (int k = 0; k < 4; k++)
+                         acc[k] += sr[k];
+                       sr += sizeof(DATA32);
+                       count++;
+                    }
 
-                  const int divider = x + left + 1;
-                  d[ALPHA] = acc[ALPHA] / divider;
-                  d[RED]   = acc[RED]   / divider;
-                  d[GREEN] = acc[GREEN] / divider;
-                  d[BLUE]  = acc[BLUE]  / divider;
+                  d[ALPHA] = acc[ALPHA] / count;
+                  d[RED]   = acc[RED]   / count;
+                  d[GREEN] = acc[GREEN] / count;
+                  d[BLUE]  = acc[BLUE]  / count;
                   d += sizeof(DATA32);
                }
 
              // Main part
-             for (x = len - (2 * radius); x > 0; x--)
+             for (; sr < sre; sr += sizeof(DATA32), sl += sizeof(DATA32))
                {
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] += sr[k];
-                  sr += sizeof(DATA32);
 
                   d[ALPHA] = DIVIDE(acc[ALPHA]);
                   d[RED]   = DIVIDE(acc[RED]);
@@ -247,24 +258,23 @@ _box_blur_vert_rgba_step(const DATA32* restrict const 
srcdata,
                   d[BLUE]  = DIVIDE(acc[BLUE]);
                   d += sizeof(DATA32);
 
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] -= sl[k];
-                  sl += sizeof(DATA32);
                }
 
              // Right part
-             for (x = right; x; x--)
+             count = 2 * radius + 1;
+             for (; sl < sle; sl += sizeof(DATA32))
                {
-                  const int divider = x + right;
+                  const int divider = --count;
                   d[ALPHA] = acc[ALPHA] / divider;
                   d[RED]   = acc[RED]   / divider;
                   d[GREEN] = acc[GREEN] / divider;
                   d[BLUE]  = acc[BLUE]  / divider;
                   d += sizeof(DATA32);
 
-                  for (k = 0; k < 4; k++)
+                  for (int k = 0; k < 4; k++)
                     acc[k] -= sl[k];
-                  sl += sizeof(DATA32);
                }
 
              // More runs to go: swap spans
diff --git a/src/lib/evas/filters/evas_filter_blur.c 
b/src/lib/evas/filters/evas_filter_blur.c
index 36a06e1..955fc64 100644
--- a/src/lib/evas/filters/evas_filter_blur.c
+++ b/src/lib/evas/filters/evas_filter_blur.c
@@ -73,7 +73,6 @@ _box_blur_horiz_apply_rgba(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.w >= (2*r + 1), 
EINA_FALSE);
 
    _box_blur_horiz_rgba(in->image.data, out->image.data, radii,
                         in->cache_entry.w, in->cache_entry.h);
@@ -103,7 +102,6 @@ _box_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.h >= (2*r + 1), 
EINA_FALSE);
 
    _box_blur_vert_rgba(in->image.data, out->image.data, radii,
                        in->cache_entry.w, in->cache_entry.h);
@@ -151,7 +149,6 @@ _box_blur_horiz_apply_alpha(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.w >= (2*r + 1), 
EINA_FALSE);
 
    _box_blur_horiz_alpha(in->image.data8, out->image.data8, radii,
                          in->cache_entry.w, in->cache_entry.h);
@@ -181,7 +178,6 @@ _box_blur_vert_apply_alpha(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.h >= (2*r + 1), 
EINA_FALSE);
 
    _box_blur_vert_alpha(in->image.data8, out->image.data8, radii,
                         in->cache_entry.w, in->cache_entry.h);
@@ -317,7 +313,6 @@ _gaussian_blur_horiz_apply_alpha(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.w >= (2*r + 1), 
EINA_FALSE);
 
    _gaussian_blur_horiz_alpha(in->image.data8, out->image.data8, r,
                               in->cache_entry.w, in->cache_entry.h);
@@ -341,7 +336,6 @@ _gaussian_blur_vert_apply_alpha(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data8, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data8, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.h >= (2*r + 1), 
EINA_FALSE);
 
    _gaussian_blur_vert_alpha(in->image.data8, out->image.data8, r,
                              in->cache_entry.w, in->cache_entry.h);
@@ -365,7 +359,6 @@ _gaussian_blur_horiz_apply_rgba(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.w >= (2*r + 1), 
EINA_FALSE);
 
    _gaussian_blur_horiz_rgba(in->image.data, out->image.data, r,
                              in->cache_entry.w, in->cache_entry.h);
@@ -389,7 +382,6 @@ _gaussian_blur_vert_apply_rgba(Evas_Filter_Command *cmd)
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(in->image.data, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(out->image.data, EINA_FALSE);
-   EINA_SAFETY_ON_FALSE_RETURN_VAL(out->cache_entry.h >= (2*r + 1), 
EINA_FALSE);
 
    _gaussian_blur_vert_rgba(in->image.data, out->image.data, r,
                             in->cache_entry.w, in->cache_entry.h);

-- 


Reply via email to