The guy in this forum has a pretty good algorithm. It works by taking the average of all colors in each “block”.
#/GDI + :
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Linq;
using System.Text;
[SuppressMessage(
"Microsoft.Naming",
"CA1704",
Justification = "'Pixelate' is a word in my book.")]
public class PixelateEffect : EffectBase
{
private int blockSize = 10;
public int BlockSize
{
get
{
return this.blockSize;
}
set
{
if (value <= 1)
{
throw new ArgumentOutOfRangeException("value");
}
this.blockSize = value;
}
}
public override void DrawImage(Bitmap source, Bitmap target)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (target == null)
{
throw new ArgumentNullException("target");
}
if (source.Size != target.Size)
{
throw new ArgumentException("The source bitmap and the target bitmap must be the same size.");
}
using (var graphics = Graphics.FromImage(target))
{
graphics.PageUnit = GraphicsUnit.Pixel;
for (int x = 0; x < source.Width; x += this.BlockSize)
{
for (int y = 0; y < source.Height; y += this.BlockSize)
{
var sums = new Sums();
for (int xx = 0; xx < this.BlockSize; ++xx)
{
for (int yy = 0; yy < this.BlockSize; ++yy)
{
if (x + xx >= source.Width || y + yy >= source.Height)
{
continue;
}
var color = source.GetPixel(x + xx, y + yy);
sums.A += color.A;
sums.R += color.R;
sums.G += color.G;
sums.B += color.B;
sums.T++;
}
}
var average = Color.FromArgb(
sums.A / sums.T,
sums.R / sums.T,
sums.G / sums.T,
sums.B / sums.T);
using (var brush = new SolidBrush(average))
{
graphics.FillRectangle(brush, x, y, (x + this.BlockSize), (y + this.BlockSize));
}
}
}
}
}
private struct Sums
{
public int A
{
get;
set;
}
public int R
{
get;
set;
}
public int B
{
get;
set;
}
public int G
{
get;
set;
}
public int T
{
get;
set;
}
}
}
emptor, ..