图像处理加强版

/*
像素是指由图像的小方格组成的,是图像的最小单位,以一个单一颜色的小格存在。
*/
#include <graphics.h>
#include <conio.h>   
#include <stdio.h>


//将图片转换为马赛克效果
//算法:求出每个小方块内所有像素的颜色平均值,然后用来设置为该小方块的颜色。
//依次处理每个小方块,即可实现马赛克效果。
//pimg:图片地址  tilesize:方块尺寸  startx,starty:起始坐标
void Mosaic(IMAGE *pimg, int tilesize, int startx, int starty)
{
    int width = pimg->getwidth();      // 获取图像的宽   640
    int height = pimg->getheight(); // 获取图像的高      480
    int redsum;         // 红色值的和
    int greensum;       // 绿色值的和
    int bluesum;        // 蓝色值的和
    int count;          // 每个小方块内的像素数量
    int color;          // 每个像素的颜色
    int x, y, tx, ty;   // 循环变量

    // 获取指向显存的指针
    DWORD* pMem = GetImageBuffer(pimg);

    // 求出左上角第一个方块的坐标
    startx = (startx % tilesize == 0 ? 0 : startx % tilesize - tilesize);//0
    starty = (starty % tilesize == 0 ? 0 : starty % tilesize - tilesize);//0

    // 处理每一个小方块
    for (y = starty; y < height; y += tilesize)//0-10-20...480
    for (x = startx; x < width; x += tilesize)//0-10-20...640
    {
        // 清空累加值
        redsum = greensum = bluesum = count = 0;

        // 求小方块的红、绿、蓝颜色值的和
        //遍历小方块每一个像素点
        for (ty = min(y + tilesize, height) - 1; ty >= max(y, 0); ty--)//9-8-7...0
        for (tx = min(x + tilesize, width) - 1; tx >= max(x, 0); tx--)//9-8-7...0
        {
            color = pMem[ty * width + tx];//9*640+9 给每一个像素点赋值
            redsum += GetRValue(color);//求出三原色的值
            greensum += GetGValue(color);
            bluesum += GetBValue(color);
            count++;//像素点的数量
        }

        // 求红、绿、蓝颜色的平均值
        redsum /= count;
        greensum /= count;
        bluesum /= count;

        // 设置小方块内的每个像素为平均颜色值
        color = RGB(redsum, greensum, bluesum);
        //遍历每一个小方块
        for (ty = min(y + tilesize, height) - 1; ty >= max(y, 0); ty--)
        for (tx = min(x + tilesize, width) - 1; tx >= max(x, 0); tx--)
            pMem[ty * width + tx] = color;//讲求出的整个方块像素的平均值赋给方块
    }
}

// 将图片进行模糊处理
//算法:遍历图片像素,将每个像素颜色值与其周围像素颜色值求和,取平均值对其赋值
void Blur(IMAGE *pimg)
{
    DWORD*  pMem = GetImageBuffer(pimg);// 获取指向显存的指针

    COLORREF color;
    int r, g, b;
    int num = 0;//像素点位置
    int width = pimg->getwidth();//获取图像的宽度
    int height = pimg->getheight();//获取图像的高度
    int m, n, i;//循环变量

    // 计算 9 格方向系数 -641      -640     -639        -1  0  1     639     640      641
    int cell[9] = { -(width + 1), -width, -(width - 1), -1, 0, 1, width - 1, width, width + 1 };

    // 逐个像素点读取计算 640*480-1 0 
    for (i = width * height - 1; i >= 0; i--)
    {
        // 累加周围 9 格颜色值
        for (n = 0, m = 0; n < 9; n++)
        {
            // 位置定位
            num = i + cell[n];//640*480-1-641  640*480-1-640 640

            // 判断位置值是否越界
            if (num < 0 || num >= width * height)
            {
                color = RGB(0, 0, 0);       // 将越界像素赋值为0
                m++;                        // 统计越界像素数
            }
            else
                color = pMem[num];//讲当前像素点的颜色值赋给color

            // 累加颜色值
            r += GetRValue(color);
            g += GetGValue(color);
            b += GetBValue(color);
        }
        // 将平均值赋值该像素
        pMem[i] = RGB(r / (9 - m), g / (9 - m), b / (9 - m));
        r = g = b = 0;
    }
}

// 底片效果
/*
底片效果使用如下公式:

pMem[i] = (~pMem[i]) & 0x00FFFFFF
*/
void ColorInvert(IMAGE *pimg)
{
    // 获取指向显存的指针
    DWORD* pMem = GetImageBuffer(pimg);

    // 直接对显存赋值,遍历每一个像素点
    for (int i = pimg->getwidth() * pimg->getheight() - 1; i >= 0; i--)
        pMem[i] = (~pMem[i]) & 0x00FFFFFF;//111111111111 000011111111
    /*
    分析操作数0x00ffffff的二进制值为32位,最高8位为0,其余为1,综合按位与的运算规则,
    可以知道结果的最高8位为0,剩余24位与左边操作数的低24位值相同。
    于是a&0x00ffffff就是取a的低24位,即低3字节的值。
    比如0x12345678 & 0x00ffffff = 0x00345678。
    */
}

// 彩色图像转换为灰度图像
/*
灰度图是指只含亮度信息,不含色彩信息的图象
彩色转换为灰度使用如下公式:

Gray = R * 0.299 + G * 0.587 + B * 0.114
为了提高运算速度,将这个公式转换为整数运算:

Gray = (R * 229 + G * 587 + B * 114 + 500) / 1000


*/
void  ColorToGray(IMAGE *pimg)
{
    DWORD *p = GetImageBuffer(pimg);
    COLORREF c;

    // 逐个像素点读取计算
    for (int i = pimg->getwidth() * pimg->getheight() - 1; i >= 0; i--)
    {
        c = BGR(p[i]);//用于交换颜色中的蓝色和红色
        c = (GetRValue(c) * 299 + GetGValue(c) * 587 + GetBValue(c) * 114 + 500) / 1000;
        p[i] = RGB(c, c, c);    // 由于是灰度值,无需再执行 BGR 转换
    }
}

// 主函数
void main()
{
    // 初始化绘图环境
    initgraph(640, 480);

    // 获取图像
    IMAGE img;
    loadimage(&img, _T("1.jpg"));

    // 显示原始图像
    putimage(0, 0, &img);

    // 任意键执行11111
    //_getch();
    setbkmode(0);
    settextcolor(BLACK);
    outtextxy(200, 150, "请选择要对图片进行的处理:");
    outtextxy(250, 200, "a.马赛克效果");
    outtextxy(250, 250, "b.模糊效果");
    outtextxy(250, 300, "c.底片效果");
    outtextxy(250, 350, "d.灰度效果");

    switch (_getch())
    {
    case 'a':
        // 将图片转换为马赛克效果
        Mosaic(&img, 10, 0, 0);
        // 显示处理后的图像
        putimage(0, 0, &img);
        break;
    case 'b':
        // 模糊处理 10 次
        for (int m = 0; m < 10; m++)
            Blur(&img);
        // 显示处理后的图像
        putimage(0, 0, &img);
        break;
    case 'c':
        // 底片效果
        ColorInvert(&img);
        // 显示处理后的图像
        putimage(0, 0, &img);
        break;
    case 'd':
        // 处理图像为灰度
        ColorToGray(&img);
        // 显示处理后的图像
        putimage(0, 0, &img);
        break;
    default:
        loadimage(&img, _T("1.jpg"));

        // 显示原始图像
        putimage(0, 0, &img);
        break;

    }

    // 任意键关闭绘图环境
    _getch();
    closegraph();
}

 

posted on 2018-10-30 23:03  lfylcj  阅读(310)  评论(0编辑  收藏  举报

导航