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.