Jump to content

luma blur


Recommended Posts

I was asked to make a to make a blur that would blur pixel based on it's luma value. The only source code I could find for blurring was the GaussianBlurEffect.cs built into paint.net although I wanted to use Ed Harvey's "True Blur" effect but could find it's source.

Here is what I have. I don't even know what's going on so it's all screwed up and causes paint.net to crash.

    protected override unsafe void OnRender(Rectangle[] rois, int startIndex, int length)
   {
       Surface dst = DstArgs.Surface;
       Surface src = SrcArgs.Surface;
       /*
       ColorBgra col = SrcArgs.Surface[0, 0];
       int luma = (int)(col.R * 0.3 + col.G * 0.59 + col.B * 0.11);
       int r = col.B;
       int[] w = CreateGaussianBlurRow(r);
       int wlen = w.Length;

       int localStoreSize = wlen * 6 * sizeof(long);
       byte* localStore = stackalloc byte[localStoreSize];
       byte* p = localStore;

       long* waSums = (long*)p;
       p += wlen * sizeof(long);

       long* wcSums = (long*)p;
       p += wlen * sizeof(long);

       long* aSums = (long*)p;
       p += wlen * sizeof(long);

       long* bSums = (long*)p;
       p += wlen * sizeof(long);

       long* gSums = (long*)p;
       p += wlen * sizeof(long);

       long* rSums = (long*)p;
       p += wlen * sizeof(long);

       ulong arraysLength = (ulong)(sizeof(long) * wlen);
       */
       int x = 0;

       for (int ri = startIndex; ri < startIndex + length; ++ri)
       {
           Rectangle rect = rois[ri];

           if (rect.Height >= 1 && rect.Width >= 1)
           {
               for (int y = rect.Top; y < rect.Bottom; ++y)
               {
                   ColorBgra col = SrcArgs.Surface[x, y];
                   int luma = (int)(col.R * 0.3 + col.G * 0.59 + col.B * 0.11);
                   int r = luma;
                   int[] wYL = CreateGaussianBlurRow(r);
                   int wlen = wYL.Length;

                   int localStoreSize = wlen * 6 * sizeof(long);
                   byte* localStoreYL = stackalloc byte[localStoreSize];
                   byte* pYL = localStoreYL;

                   long* waSumsYL = (long*)pYL;
                   pYL += wlen * sizeof(long);

                   long* wcSumsYL = (long*)pYL;
                   pYL += wlen * sizeof(long);

                   long* aSumsYL = (long*)pYL;
                   pYL += wlen * sizeof(long);

                   long* bSumsYL = (long*)pYL;
                   pYL += wlen * sizeof(long);

                   long* gSumsYL = (long*)pYL;
                   pYL += wlen * sizeof(long);

                   long* rSumsYL = (long*)pYL;
                   pYL += wlen * sizeof(long);

                   ulong arraysLength = (ulong)(sizeof(long) * wlen);
                  // Memory.SetToZero(localStore, (ulong)localStoreSize);

                   long waSum = 0;
                   long wcSum = 0;
                   long aSum = 0;
                   long bSum = 0;
                   long gSum = 0;
                   long rSum = 0;

                   ColorBgra* dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);

                   for (int wx = 0; wx < wlen; ++wx)
                   {
                       int srcX = rect.Left + wx - r;
                       waSumsYL[wx] = 0;
                       wcSumsYL[wx] = 0;
                       aSumsYL[wx] = 0;
                       bSumsYL[wx] = 0;
                       gSumsYL[wx] = 0;
                       rSumsYL[wx] = 0;

                       if (srcX >= 0 && srcX < src.Width)
                       {
                           for (int wy = 0; wy < wlen; ++wy)
                           {
                               int srcY = y + wy - r;

                               if (srcY >= 0 && srcY < src.Height)
                               {
                                   ColorBgra c = src.GetPointUnchecked(srcX, srcY);
                                   int wp = wYL[wy];

                                   waSumsYL[wx] += wp;
                                   wp *= c.A + (c.A >> 7);
                                   wcSumsYL[wx] += wp;
                                   wp >>= 8;

                                   aSumsYL[wx] += wp * c.A;
                                   bSumsYL[wx] += wp * c.B;
                                   gSumsYL[wx] += wp * c.G;
                                   rSumsYL[wx] += wp * c.R;
                               }
                           }

                           int wwx = wYL[wx];
                           waSum += wwx * waSumsYL[wx];
                           wcSum += wwx * wcSumsYL[wx];
                           aSum += wwx * aSumsYL[wx];
                           bSum += wwx * bSumsYL[wx];
                           gSum += wwx * gSumsYL[wx];
                           rSum += wwx * rSumsYL[wx];
                       }
                   }

                   wcSum >>= 8;

                   if (waSum == 0 || wcSum == 0)
                   {
                       dstPtr->Bgra = 0;
                   }
                   else
                   {
                       int alpha = (int)(aSum / waSum);
                       int blue = (int)(bSum / wcSum);
                       int green = (int)(gSum / wcSum);
                       int red = (int)(rSum / wcSum);

                       dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha);
                   }

                   ++dstPtr;

                   for (x = rect.Left + 1; x < rect.Right; ++x)
                   {
                       col = SrcArgs.Surface[x, y];
                       luma = (int)(col.R * 0.3 + col.G * 0.59 + col.B * 0.11);
                       r = luma;
                       int[] wXL = CreateGaussianBlurRow(r);
                       wlen = wXL.Length;

                       localStoreSize = wlen * 6 * sizeof(long);
                       byte* localStoreXL = stackalloc byte[localStoreSize];
                       byte* pXL = localStoreXL;

                       long* waSumsXL = (long*)pXL;
                       pXL += wlen * sizeof(long);

                       long* wcSumsXL = (long*)pXL;
                       pXL += wlen * sizeof(long);

                       long* aSumsXL = (long*)pXL;
                       pXL += wlen * sizeof(long);

                       long* bSumsXL = (long*)pXL;
                       pXL += wlen * sizeof(long);

                       long* gSumsXL = (long*)pXL;
                       pXL += wlen * sizeof(long);

                       long* rSumsXL = (long*)pXL;
                       pXL += wlen * sizeof(long);

                       arraysLength = (ulong)(sizeof(long) * wlen);
                       for (int i = 0; i < wlen - 1; ++i)
                       {
                           waSumsXL[i] = waSumsXL[i + 1];
                           wcSumsXL[i] = wcSumsXL[i + 1];
                           aSumsXL[i] = aSumsXL[i + 1];
                           bSumsXL[i] = bSumsXL[i + 1];
                           gSumsXL[i] = gSumsXL[i + 1];
                           rSumsXL[i] = rSumsXL[i + 1];
                       }

                       waSum = 0;
                       wcSum = 0;
                       aSum = 0;
                       bSum = 0;
                       gSum = 0;
                       rSum = 0;

                       int wx;
                       for (wx = 0; wx < wlen - 1; ++wx)
                       {
                           long wwx = (long)wXL[wx];
                           waSum += wwx * waSumsXL[wx];
                           wcSum += wwx * wcSumsXL[wx];
                           aSum += wwx * aSumsXL[wx];
                           bSum += wwx * bSumsXL[wx];
                           gSum += wwx * gSumsXL[wx];
                           rSum += wwx * rSumsXL[wx];
                       }

                       wx = wlen - 1;

                       waSumsXL[wx] = 0;
                       wcSumsXL[wx] = 0;
                       aSumsXL[wx] = 0;
                       bSumsXL[wx] = 0;
                       gSumsXL[wx] = 0;
                       rSumsXL[wx] = 0;

                       int srcX = x + wx - r;

                       if (srcX >= 0 && srcX < src.Width)
                       {
                           for (int wy = 0; wy < wlen; ++wy)
                           {
                               int srcY = y + wy - r;

                               if (srcY >= 0 && srcY < src.Height)
                               {
                                   ColorBgra c = src.GetPointUnchecked(srcX, srcY);
                                   int wp = wXL[wy];

                                   waSumsXL[wx] += wp;
                                   wp *= c.A + (c.A >> 7);
                                   wcSumsXL[wx] += wp;
                                   wp >>= 8;

                                   aSumsXL[wx] += wp * (long)c.A;
                                   bSumsXL[wx] += wp * (long)c.B;
                                   gSumsXL[wx] += wp * (long)c.G;
                                   rSumsXL[wx] += wp * (long)c.R;
                               }
                           }

                           int wr = wXL[wx];
                           waSum += (long)wr * waSumsXL[wx];
                           wcSum += (long)wr * wcSumsXL[wx];
                           aSum += (long)wr * aSumsXL[wx];
                           bSum += (long)wr * bSumsXL[wx];
                           gSum += (long)wr * gSumsXL[wx];
                           rSum += (long)wr * rSumsXL[wx];
                       }

                       wcSum >>= 8;

                       if (waSum == 0 || wcSum == 0)
                       {
                           dstPtr->Bgra = 0;
                       }
                       else
                       {
                           int alpha = (int)(aSum / waSum);
                           int blue = (int)(bSum / wcSum);
                           int green = (int)(gSum / wcSum);
                           int red = (int)(rSum / wcSum);

                           dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha);
                       }

                       ++dstPtr;
                   }
               }
           }
       }
   }
 }
}

Link to comment
Share on other sites

You might want to make that adjustable.

OK, here's what you can do...

Calculate the luma of a pixel and call the gaussian blur function for that pixel.

Not gonna be very fast, but it would work. Once you get it working, you can see if it is worth optimizing.

You see all that code in your first post? Throw it all away except for this line:

int luma = (int)(col.R * 0.3 + col.G * 0.59 + col.B * 0.11);

Make this a "complex effect"--that is, an effect that calls other effects.

Go from there. ;)

Link to comment
Share on other sites

I can call upon other effects? I didn't know that. Can I call upon any effect or just the ones that come with PDN; for example could I call "True Blur"? Also how do I do it, could you give an example.

thank you, thank you, thank you,

Bleek II

Link to comment
Share on other sites

Ok I know this is somewhat old by now, but..

... wanted to use Ed Harvey's "True Blur" effect but could find it's source ...

The source is staring you right in the face (so to speak) - it's a .NET assembly, so easily decompilable (with, for example, Lutz' .NET Reflector)

The description of this effect reminds me of Bloom a bit..

I would write plugins, if I knew what kind of plugins were needed.. :(

Link to comment
Share on other sites

Thanks for trying Bleek, and thanks for helping BB :)

[Edit] W-w-w-w-wait, you're blurring the canvas image according to its own luminosity, or according to a mask's?

Which do you want?

I'm going to play with it just using the canvas but the final plugin will use masks.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...