误差扩散算法

应用用误差扩散算法进行图像半色调处理

作者: yym439 时间: 2019-10-25

半色调

目前半色调技术最普遍的分类法是按照它的处理方式分为:抖动法,误差扩散法,迭代法三大类。

半色调技术可以将一幅真彩图,处理为单色、8色、16色或者256色的图片。针式打印机只打印黑白图片,通过半色调处理的单色图片比直接用二值化处理的单色图,整体视觉效果更好。

半色调技术比较

Atkinson误差扩散算法

  1. 24位真彩色图片转换为24位的黑白图片
  2. 再进行误差扩散处理

Atkinson 算法矩阵:

         X   1   1 
     1   1   1
         1
    
       (1/8)

C语言代码实现

//扫描原始图片数据
    for (int row = 0; row < height; row++)
    {
        //3字节 = 一像素
        for (int col = 0; col < 3*width; col+=3)
        {
            int index;
            index = row * 3*width + col; //像素起始下标索引
            //原始像素值
            unsigned char r = data24[index];
            unsigned char g = data24[index+1];
            unsigned char b = data24[index+2];
            //像素转黑白数据,获取转换后的像素
            unsigned char n_r, n_g,n_b;
            int gPiex = r*0.299   +  g*0.587  + b*0.114;
            if(gPiex<nThreshold)
            {
                n_r = 0;
                n_g = 0;
                n_b = 0;
            }
            else
            {
                n_r = 255;
                n_g = 255;
                n_b = 255;
            }

            //新像素重置原始像素
            data24[index] = n_r;
            data24[index+1] = n_g;
            data24[index+2] = n_b;

            //======开始误差扩散=====
            int r_error = r-n_r;
            int g_error = g-n_g;
            int b_error = b-n_g;
            //对应算法矩阵模型
            for (int y = 0; y < 3; y++)
            {
                int offsetY;
                offsetY = row + y; //像素行索引 +  矩阵模型行
                for (int x = 0; x < 4; x++)
                {
                    int coefficient;
                    int offsetX;
                    coefficient = matrix[y][x]; //矩阵系数值
                    offsetX = col + (x - 2); //像素列索引 + (矩阵列-2)
                    //误差偏移条件判断
                    if (coefficient != 0 && offsetX > 0 && offsetX < 3*width && offsetY > 0 && offsetY < height)
                    {
                        int offsetIndex = offsetY * 3*width + offsetX; //偏移索引
                        //获取偏移像素的原始RGB值
                        unsigned char originalR = data24[offsetIndex];
                        unsigned char originalG = data24[offsetIndex+1];
                        unsigned char originalB = data24[offsetIndex+2];
                        //计算需要调整的RGB
                        int offsetR = (r_error*coefficient)>>3;
                        int offsetG = (g_error*coefficient)>>3;
                        int offsetB = (b_error*coefficient)>>3;
                        //重置调整过的原始RGB像素值
                        data24[offsetIndex] = toByte(originalR + offsetR);
                        data24[offsetIndex+1] = toByte(originalG + offsetG);
                        data24[offsetIndex+2] = toByte(originalB + offsetB);
                    }
                }
            }

        }
    }

更多扩散算法参考:

http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/