|
-
Really Cold Shark
Fast Blurring Algorithms in Managed Code?
Someone on another forum suggested an image host (to be used for certain types of images where content may be... suggestive) in which the image is hosted in both a normal form and a blurred version which could be used as a link.
I thought this sounded like a funny idea, so I wrote a quick page to do it and hosted on an unused domain I have. The page is here: http://aaron.doomray.com/blurhost
The problem is that I don't know much about Image Processing and my blurring algorithm is far too slow. For a large picture with a high "blur amount", it can take over a minute for the page to return. Now, part of the problem is the site hosting, which is a shared server, so I'm not getting all the CPU time I could. More importantly, the host does not allow me to use compiled DLL's or unmanaged code. That means I can't use a library blur function, and I can't use pointers to access the pixels in the bitmap (this is the real problem).
Since I can't use pointers, accessing each pixel takes far too long, so I'm looking for a way to blur an image without having to loop through each pixel multiple times (taking averages of the colors).
Here's my current blur method:
Code:
public Bitmap Blur(Bitmap image, int amount)
{
Int32 horz = amount;
Int32 vert = amount;
Single weightsum;
Single[] weights;
Bitmap t = image;
weights = new Single[horz * 2 + 1];
for (Int32 i = 0; i < horz * 2 + 1; i++)
{
Single y = Gauss(-horz + i, 0, horz);
weights[i] = y;
}
for (Int32 row = 0; row < image.Height; row++)
{
for (Int32 col = 0; col < image.Width; col++)
{
Double r = 0;
Double g = 0;
Double b = 0;
Double a = 0;
weightsum = 0;
for (Int32 i = 0; i < horz * 2 + 1; i++)
{
Int32 x = col - horz + i;
if (x < 0)
{
i += -x;
x = 0;
}
if (x > image.Width - 1)
break;
Color c = image.GetPixel(x, row);
r += c.R * weights[i] / 255.0 * c.A;
g += c.G * weights[i] / 255.0 * c.A;
b += c.B * weights[i] / 255.0 * c.A;
a += c.A * weights[i];
weightsum += weights[i];
}
r /= weightsum;
g /= weightsum;
b /= weightsum;
a /= weightsum;
Byte br = (Byte)Math.Round(r);
Byte bg = (Byte)Math.Round(g);
Byte bb = (Byte)Math.Round(b);
Byte ba = (Byte)Math.Round(a);
if (br > 255) br = 255;
if (bg > 255) bg = 255;
if (bb > 255) bb = 255;
if (ba > 255) ba = 255;
t.SetPixel(col, row, Color.FromArgb(ba, br, bg, bb));
}
}
// vertical blur
weights = new Single[vert * 2 + 1];
for (Int32 i = 0; i < vert * 2 + 1; i++)
{
Single y = Gauss(-vert + i, 0, vert);
weights[i] = y;
}
for (Int32 col = 0; col < image.Width; col++)
{
for (Int32 row = 0; row < image.Height; row++)
{
Double r = 0;
Double g = 0;
Double b = 0;
Double a = 0;
weightsum = 0;
for (Int32 i = 0; i < vert * 2 + 1; i++)
{
Int32 y = row - vert + i;
if (y < 0)
{
i += -y;
y = 0;
}
if (y > image.Height - 1)
break;
Color c = t.GetPixel(col, y);
r += c.R * weights[i] / 255.0 * c.A;
g += c.G * weights[i] / 255.0 * c.A;
b += c.B * weights[i] / 255.0 * c.A;
a += c.A * weights[i];
weightsum += weights[i];
}
r /= weightsum;
g /= weightsum;
b /= weightsum;
a /= weightsum;
Byte br = (Byte)Math.Round(r);
Byte bg = (Byte)Math.Round(g);
Byte bb = (Byte)Math.Round(b);
Byte ba = (Byte)Math.Round(a);
if (br > 255) br = 255;
if (bg > 255) bg = 255;
if (bb > 255) bb = 255;
if (ba > 255) ba = 255;
image.SetPixel(col, row, Color.FromArgb(ba, br, bg, bb));
}
}
return image;
}
If anyone can think of a faster way to do this that will work in ASP.NET, please let me know. There might be some way to do it using GDI+, but I'm not sure.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
|