如何并行化图像像素化?

时间:2015-08-30 22:40:41

标签: c# bitmap parallel-processing task-parallel-library

我一直在玩一些Image Pixelation算法,我遇到了这个post

private static Bitmap Pixelate(Bitmap image, Rectangle rectangle, Int32 pixelateSize)
{
    Bitmap pixelated = new System.Drawing.Bitmap(image.Width, image.Height);

    // make an exact copy of the bitmap provided
    using (Graphics graphics = System.Drawing.Graphics.FromImage(pixelated))
        graphics.DrawImage(image, new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
            new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);

    // look at every pixel in the rectangle while making sure we're within the image bounds
    for (Int32 xx = rectangle.X; xx < rectangle.X + rectangle.Width && xx < image.Width; xx += pixelateSize)
    {
        for (Int32 yy = rectangle.Y; yy < rectangle.Y + rectangle.Height && yy < image.Height; yy += pixelateSize)
        {
            Int32 offsetX = pixelateSize / 2;
            Int32 offsetY = pixelateSize / 2;

            // make sure that the offset is within the boundry of the image
            while (xx + offsetX >= image.Width) offsetX--;
            while (yy + offsetY >= image.Height) offsetY--;

            // get the pixel color in the center of the soon to be pixelated area
            Color pixel = pixelated.GetPixel(xx + offsetX, yy + offsetY);

            // for each pixel in the pixelate size, set it to the center color
            for (Int32 x = xx; x < xx + pixelateSize && x < image.Width; x++)
                for (Int32 y = yy; y < yy + pixelateSize && y < image.Height; y++)
                    pixelated.SetPixel(x, y, pixel);
        }    
    }

    return pixelated;
}

一切正常,但我很难并行化(希望它是一个单词)代码。我知道你应该使用LockBits而不是,但是我真的很难做到这一点。我确信有办法做像素块/核心。

并行代码不是我的强项。

1 个答案:

答案 0 :(得分:0)

使用找到here的LockBitmap类代码使用LockBits:

private static Bitmap PixelateLockBits(Bitmap image, Rectangle rectangle, int pixelateSize)
{
    using (LockBitmap lockBitmap = new LockBitmap(image))
    {
        var width = image.Width;
        var height = image.Height;

        for (Int32 xx = rectangle.X; xx < rectangle.X + rectangle.Width && xx < image.Width; xx += pixelateSize)
        {
            for (Int32 yy = rectangle.Y; yy < rectangle.Y + rectangle.Height && yy < image.Height; yy += pixelateSize)
            {
                Int32 offsetX = pixelateSize / 2;
                Int32 offsetY = pixelateSize / 2;

                // make sure that the offset is within the boundry of the image
                while (xx + offsetX >= image.Width) offsetX--;
                while (yy + offsetY >= image.Height) offsetY--;

                // get the pixel color in the center of the soon to be pixelated area
                Color pixel = lockBitmap.GetPixel(xx + offsetX, yy + offsetY);

                // for each pixel in the pixelate size, set it to the center color
                for (Int32 x = xx; x < xx + pixelateSize && x < image.Width; x++)
                    for (Int32 y = yy; y < yy + pixelateSize && y < image.Height; y++)
                        lockBitmap.SetPixel(x, y, pixel);
            }
        }
    }
    return image;
}

然后你可以将内部2个变换为Parallel.For:

Parallel.For(xx, xx + pixelateSize, x =>
{
    if (x < width)
    {
        Parallel.For(yy, yy + pixelateSize, y =>
        {
            if (y < height)
            {
                lockBitmap.SetPixel(x, y, pixel);
            }
        });
    }
});