2012-08-30 5 views
0

최근에 나는 반경이 가변적이라는 이미지를 blur에 시도했습니다. myseft를 구현하려고했지만 너무 느리다. 이미지의 중심 감소까지의 거리가 반경이 너무 감소 할 때 : 사실fast 변수 흐림 또는 흐림 라이브러리 android

static Bitmap fastblur(Bitmap sentBitmap, int radius, int fromX, int fromY, 
     int width, int height) { 

    // Stack Blur v1.0 from 
    // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html 
    // 
    // Java Author: Mario Klingemann <mario at quasimondo.com> 
    // http://incubator.quasimondo.com 
    // created Feburary 29, 2004 
    // Android port : Yahel Bouaziz <yahel at kayenko.com> 
    // http://www.kayenko.com 
    // ported april 5th, 2012 

    // This is a compromise between Gaussian Blur and Box blur 
    // It creates much better looking blurs than Box Blur, but is 
    // 7x faster than my Gaussian Blur implementation. 
    // 
    // I called it Stack Blur because this describes best how this 
    // filter works internally: it creates a kind of moving stack 
    // of colors whilst scanning through the image. Thereby it 
    // just has to add one new block of color to the right side 
    // of the stack and remove the leftmost color. The remaining 
    // colors on the topmost layer of the stack are either added on 
    // or reduced by one, depending on if they are on the right or 
    // on the left side of the stack. 
    // 
    // If you are using this algorithm in your code please add 
    // the following line: 
    // 
    // Stack Blur Algorithm by Mario Klingemann <[email protected]> 

    Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); 

    if (radius < 1) { 
     return (null); 
    } 

    int w = width; 
    int h = height; 

    int[] pix = new int[w * h]; 

    bitmap.getPixels(pix, 0, w, fromX, fromY, w, h); 

    int wm = w - 1; 
    int hm = h - 1; 
    int wh = w * h; 
    int div = radius + radius + 1; 

    int r[] = new int[wh]; 
    int g[] = new int[wh]; 
    int b[] = new int[wh]; 
    int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; 
    int vmin[] = new int[Math.max(w, h)]; 

    int divsum = (div + 1) >> 1; 
    divsum *= divsum; 
    int dv[] = new int[256 * divsum]; 
    for (i = 0; i < 256 * divsum; i++) { 
     dv[i] = (i/divsum); 
    } 

    yw = yi = 0; 

    int[][] stack = new int[div][3]; 
    int stackpointer; 
    int stackstart; 
    int[] sir; 
    int rbs; 
    int r1 = radius + 1; 
    int routsum, goutsum, boutsum; 
    int rinsum, ginsum, binsum; 

    int originRadius = radius; 
    for (y = 0; y < h; y++) { 
     rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; 
     for (i = -radius; i <= radius; i++) { 
      p = pix[yi + Math.min(wm, Math.max(i, 0))]; 
      sir = stack[i + radius]; 
      sir[0] = (p & 0xff0000) >> 16; 
      sir[1] = (p & 0x00ff00) >> 8; 
      sir[2] = (p & 0x0000ff); 
      rbs = r1 - Math.abs(i); 
      rsum += sir[0] * rbs; 
      gsum += sir[1] * rbs; 
      bsum += sir[2] * rbs; 
      if (i > 0) { 
       rinsum += sir[0]; 
       ginsum += sir[1]; 
       binsum += sir[2]; 
      } else { 
       routsum += sir[0]; 
       goutsum += sir[1]; 
       boutsum += sir[2]; 
      } 
     } 
     stackpointer = radius; 

     for (x = 0; x < w; x++) { 

      r[yi] = dv[rsum]; 
      g[yi] = dv[gsum]; 
      b[yi] = dv[bsum]; 

      rsum -= routsum; 
      gsum -= goutsum; 
      bsum -= boutsum; 

      stackstart = stackpointer - radius + div; 
      sir = stack[stackstart % div]; 

      routsum -= sir[0]; 
      goutsum -= sir[1]; 
      boutsum -= sir[2]; 

      if (y == 0) { 
       vmin[x] = Math.min(x + radius + 1, wm); 
      } 
      p = pix[yw + vmin[x]]; 

      sir[0] = (p & 0xff0000) >> 16; 
      sir[1] = (p & 0x00ff00) >> 8; 
      sir[2] = (p & 0x0000ff); 

      rinsum += sir[0]; 
      ginsum += sir[1]; 
      binsum += sir[2]; 

      rsum += rinsum; 
      gsum += ginsum; 
      bsum += binsum; 

      stackpointer = (stackpointer + 1) % div; 
      sir = stack[(stackpointer) % div]; 

      routsum += sir[0]; 
      goutsum += sir[1]; 
      boutsum += sir[2]; 

      rinsum -= sir[0]; 
      ginsum -= sir[1]; 
      binsum -= sir[2]; 

      yi++; 
     } 
     yw += w; 
    } 

    radius = originRadius; 

    for (x = 0; x < w; x++) { 
     rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; 
     yp = -radius * w; 
     for (i = -radius; i <= radius; i++) { 
      yi = Math.max(0, yp) + x; 

      sir = stack[i + radius]; 

      sir[0] = r[yi]; 
      sir[1] = g[yi]; 
      sir[2] = b[yi]; 

      rbs = r1 - Math.abs(i); 

      rsum += r[yi] * rbs; 
      gsum += g[yi] * rbs; 
      bsum += b[yi] * rbs; 

      if (i > 0) { 
       rinsum += sir[0]; 
       ginsum += sir[1]; 
       binsum += sir[2]; 
      } else { 
       routsum += sir[0]; 
       goutsum += sir[1]; 
       boutsum += sir[2]; 
      } 

      if (i < hm) { 
       yp += w; 
      } 
     } 
     yi = x; 
     stackpointer = radius; 
     for (y = 0; y < h; y++) { 
      pix[yi] = 0xff000000 | (dv[rsum] << 16) | (dv[gsum] << 8) 
        | dv[bsum]; 

      rsum -= routsum; 
      gsum -= goutsum; 
      bsum -= boutsum; 

      stackstart = stackpointer - radius + div; 
      sir = stack[stackstart % div]; 

      routsum -= sir[0]; 
      goutsum -= sir[1]; 
      boutsum -= sir[2]; 

      if (x == 0) { 
       vmin[y] = Math.min(y + r1, hm) * w; 
      } 
      p = x + vmin[y]; 

      sir[0] = r[p]; 
      sir[1] = g[p]; 
      sir[2] = b[p]; 

      rinsum += sir[0]; 
      ginsum += sir[1]; 
      binsum += sir[2]; 

      rsum += rinsum; 
      gsum += ginsum; 
      bsum += binsum; 

      stackpointer = (stackpointer + 1) % div; 
      sir = stack[stackpointer]; 

      routsum += sir[0]; 
      goutsum += sir[1]; 
      boutsum += sir[2]; 

      rinsum -= sir[0]; 
      ginsum -= sir[1]; 
      binsum -= sir[2]; 

      yi += w; 
     } 
    } 

    bitmap.setPixels(pix, 0, w, fromX, fromY, w, h); 

    return (bitmap); 
} 

, 나는이 흐림 방법 등 (가변 흐림이 될 수 원하는 :이 사이트에서, 나는 stack blur라고 빠른 흐림 방법을 가지고). 그러나, 비트 이동을 잘하지 못합니다. 코드를 수정하기가 너무 어렵습니다. 그래서 방사형 흐림 효과와 같은 코드를 구현하는 방법을 묻고 싶습니다. 그리고 방사형 흐림, 회색 음영, 안드로이드가 포함 된 흐림 라이브러리가 있는지 궁금합니다. 아무도 나를 도울 수 있다면 정말로 감사합니다! 감사합니다!

답변

4

속도를 최적화하기 때문에이 알고리즘은 다양한 반경에 맞게 적합하지 않습니다. 다른 접근 방식을 취하면 여전히 사용할 수 있습니다.

원칙적으로 증가하는 (균일 한) 흐림 반경으로 각각 여러 개의 임시 맵을 만든 다음 해당 지점의 반경 크기에 따라 두 개의 맵을 혼합합니다 해야한다. 반경 4, 하나는 8, 하나는 16으로 3 개의 임시 맵을 준비한다고 가정 해 보겠습니다. 이제는 한 픽셀에 12의 흐림 반경이 필요합니다. 당신이하는 일은지도 2와 3을 약 50 %로 혼합하는 것입니다. 더 많은 임시 맵을 사용하면할수록 품질은 좋아 지지만, 보통 원래의 흐려지지 않은 맵을 더한 3 개이면 충분합니다.

캔버스 용 복합 흐림 효과 : http://www.quasimondo.com/CompoundBlurForCanvas/CompoundBlurDemo.html -이 기술을 사용하여 기울기 이동 효과 또는 비 네트를 사용할 수 있습니다.

카메라 줌 효과처럼 보이는 방사형 흐림 효과를 찾는 경우 다른 접근 방식을 사용해야합니다. 이 경우 먼저 비트 맵을 직교 좌표 매핑에서 극좌표 매핑으로 변환 한 다음 수평 흐림을 수행하고 마침내지도를 데카르트 공간으로 다시 변환합니다. 플래시 데모와 내 소스 코드가 있으며 자세한 설명이 있습니다. : http://www.quasimondo.com/archives/000697.php

+0

대단히 감사합니다! –

0

어떻게 슬라이더와 복합 흐림을 구현 :

/// HTML ///

// 사용 : CompoundBlur.js //

<DIV CLASS="specimenWindow"> 

    <DIV CLASS="specimenImage"> 

     <IMG ID="specImg" WIDTH="150" HEIGHT="150" /> 
     <CANVAS ID="specCanvas" WIDTH="150" HEIGHT="150"></CANVAS> 

    </DIV> 

</DIV> 

<SCRIPT TYPE="text/javascript" SRC="js/CompoundBlur.js"></SCRIPT> 
01 23,414,/// CSS ///

.specimenWindow { 
    position: absolute; 
    width: 150px; 
    height: 150px; 
    left: 37px; 
    top: 96px; 
} 

.specimenImage { 
    height: 150px; 
    width: 150px; 
} 

#specCanvas { 
    position: absolute; 
    top: 27px; 
    left: 2px; 
} 

/// JS ///

var specImg = document.getElementById("specImg"); 

_slider.ontouchend = function() { 
    compoundBlur(); 
} 

function compoundBlur() { 
    var lensRead = _slider.getPosition(0, 80); 
    var rData = getRadialGradientMap(150, 150, 75, 75, 25, 60); 
    compoundBlurImage("specImg", "specCanvas", rData, lensRead, 1.5, 2, true); 
} 

그래서, 그냥 내 슬라이더이 때 흔들림이, 부드러운 흐림 효과를 얻을 수있는 값을 조정 터치가 끝나면 이것은 모바일 장치에서보다 효율적이며 슬라이더가 바뀌면 계속 흐리게 표시됩니다. 그렇지 않으면 iPad가 따뜻해지면서 배터리 전원이 빨리 느슨해지기 시작합니다.

그러면 빠른 컴파운드 흐림 효과를 구현하려는 모든 사용자에게 도움이 되길 바랍니다.