C# 实现图片马赛克

如何使用 C# 实现图片的马赛克算法呢?本文带你来一探究竟……

原文同步发布在简书 本图片马赛克问题来自于 WHUMSC2015 年招新

说到马赛克,大家一定不陌生。但是该如何利用编程语言实现呢? 使用工具:

  • C#
  • Visual Studio 2015 Community 
  • Windows 10

原理: 大家都知道,一张图片是由一个一个像素组成。这些像素呢逐次排列,就好像方格纸一样。(密集恐惧症慎入) 每个格子都是一个特定的颜色。 那么怎么实现马赛克呢?说白了呢,就是实现下面的一个转换(每个字母代表一个像素,假设马赛克的范围为 2): 间隔选取像素点(如 ACE...),接着填充至周围的格子中。 实战: 首先要用到 System.Drawing 一般创建 Win 窗口程序时都已经引用了。我们要用到里面的 Bitmap 库 类来进行图片的读取和写入操作。 构造一个函数  

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// img为输入的图像,a为马赛克的范围
public static Bitmap imgMosaic(Bitmap img, int a)
{
    // 两层循环,遍历每一个间隔的像素点
    for (int h = 0; h < img.Height; h += a)
    {
        for (int w = 0; w < img.Width; w += a)
        {
            // 获取颜色
            Color xxx = img.GetPixel(w, h);

            // 另一层循环,填充颜色
            for (int x = w; (x < w + a && x < img.Width); x++)
            {
                for (int y = h; (y < h + a && y < img.Height); y++)
                {
                    img.SetPixel(x, y, xxx);
                }
            }
        }
    }
    return img;
}

  至于效果么。。你们自己感受一下: 其实挺好了,已经有马赛克的效果了。 我又想:怎么让马赛克的效果更好呢?问题是 ACE 这样的像素可能不能代表周围的一圈像素。 于是,我们可以取 ABGH 的 RGB 平均值再填入这些像素中。代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static Bitmap imgMosaic2(Bitmap img, int a)
{
    for (int h = 0; h < img.Height; h += a)
    {
        for (int w = 0; w < img.Width; w += a)
        {
            int avgR = 0, avgG = 0, avgB = 0;
            int count = 0;
            for (int x = w; (x < w + a && x < img.Width); x++)
            {
                for (int y = h; (y < h + a && y < img.Height); y++)
                {
                    Color pix = img.GetPixel(x, y);
                    avgR += pix.R;
                    avgG += pix.G;
                    avgB += pix.B;
                    count++;
                }
            }
            avgR = avgR / count;
            avgG = avgG / count;
            avgB = avgB / count;
            for (int x = w; (x < w + a && x < img.Width); x++)
            {
                for (int y = h; (y < h + a && y < img.Height); y++)
                {
                    Color newColor = Color.FromArgb(avgR, avgG, avgB);
                    img.SetPixel(x, y, newColor);
                }
            }
        }
    }
    return img;
}

  

再来感受一下效果: 瞬间感觉好多了。

至于导入图片:

1
image1 = new Bitmap(@"C:\img.jpg", true); // @后换成自己想要的路径就可以了

 

加载评论