C++基础 -- 位运算 + 图像像素

一.计算器图片信息

图形传入 IMAGE 图像类型

 图形由大量 像素点 构成
每一个像素点 包含四个信息 a r g b
    a(air)-透明度   r(ed)- 红色通道  g(reen)-绿色通道 b(lue)-蓝色通道  每个0~255

而他们存储 为32位数字信息 每八位存储一个信息 以二进制存储 
 00000000 00000000 00000000 00000000
   a        r        g        b


 1.黑白图片 (灰色) 
  rgb三色相同,可以将每个像素点的 r g b 分别取出,相加求均值 可以得到灰色图片
 2.负片 
在黑白的基础上,将黑白颠倒 ,取其rgb 的补值
3.马赛克处理 
将图片分为众多小块,每一块区域的r g b 都取相同

二.C++中提取像素的函数

unsigned  C= getpixel(X,Y);

X,Y 为图像在窗口的坐标  (坐标原点在屏幕左上角,向右为X正半轴,向下为Y正半轴)

返回值C 为 该像素点的ARGB信息加和

如何分别提取 a r g b  用getpixel  函数返回argb的和值

三.位运算


再通过内存溢出 32/64 位 只要向左或向右移动(位运算) 移动到32/64 位之外,便会溢出,损失溢出数据,而前后由0补齐
 ----位运算-----
但只有最前面8个信息 也就是 a 可以直接位移得到,因为前面都补位为0 余下的则是 00000000  11111111 1010101010 之类
如何只保留后八位呢 可以通过位运算 &  |  ! ^  四种运算操作二进制数
 和运算--- 有0就是0
 1 & 1 = 1
/* 1 & 0 = 0
*  0 & 0 = 0
* ……………………
* 或运算 --- 有 1 就是1
* 1 | 1 = 1
* 1 | 0 = 1
* 0 | 0 = 0
* 非运算 --- !1=0;!0=1
*/ 

所以,就以 00000000 11111111 10101010  01010101 为例 ,要保留后四位,前面全部变为零,可以将这个值 
       &  00000000 00000000 00000000  11111111  即16进制下  0xff
      =  00000000 00000000 00000000  01010101

理论完备,逐一实现

四.代码实现

#include<iostream>
#include<easyx.h>
#include<string>
using namespace std;

// 一.黑白图片 (灰色) 
//  rgb三色相同,可以将每个像素点的 r g b 分别取出,相加求均值 可以得到灰色图片

class PS
{
public:
	PS()
	{
		X = 1000;
		Y = 1000;
		cout << "请输入图片名: " << endl;
		cin >> FileName;
		loadimage(&photo, FileName);
		A = 0; R = 0; G = 0; B = 0;
		
	}
	IMAGE photo;
	void P_BLACK();
	void P_FP();
	void P_MSK();
	char FileName[20];
	//string FileName;
	unsigned A, R, G, B;
	int X, Y;
};

void PS::P_BLACK()
{	
	initgraph(1000, 1000);
	
	putimage(0, 0, &photo);

	//SetWorkingImage(&photo);//指定设置此图
	 unsigned c = 0;
	for(int x=0;x<X;x++)
		for (int y = 0; y < Y; y++)
		{	
			c = getpixel(x, y);
			R = (c >> 16) & 0xff; 
			G = (c >> 8) & 0xff;
			B = c & 0xff;
			R = G = B = (R + G + B) / 3;
			//new c
			c = (R << 16) + (G << 8) + B;
			//c = 0;
			putpixel(x, y, c);//再将新的显示回去
		}
	  

	//system("pause");
	// SetWorkingImage(NULL);//结束指定
}

// 二.负片 
// 在黑白的基础上,将黑白颠倒 ,取其rgb 的补值
void PS::P_FP()
{
	initgraph(1000, 1000);

	putimage(0, 0, &photo);

	//SetWorkingImage(&photo);//指定设置此图
	unsigned c = 0;
	for (int x = 0; x < X; x++)
		for (int y = 0; y < Y; y++)
		{
			c = getpixel(x, y);
			R = (c >> 16) & 0xff;
			G = (c >> 8) & 0xff;
			B = c & 0xff;
			R = G = B = (255-(R + G + B) / 3);

			//new c
			c = (R << 16) + (G << 8) + B;
			//c = 0;
			putpixel(x, y, c);//再将新的显示回去
		}


	//system("pause");

}
// 三.马赛克处理 
// 将图片分为众多小块,每一块区域的r g b 都取相同
void PS::P_MSK()
{
	initgraph(1000, 1000);
	putimage(0, 0, &photo);
	int size = 20;
	unsigned c = 0;
int S_R, S_G, S_B;
		int n = 1;
	for (int FX = 0; FX < min(FX+size,X); FX += min(size,X-FX) )
	{
		for(int FY=0;FY<min(FY+size,Y); FY += min(size, Y - FY))
		{ 
		S_R = S_G = S_B = 0;
		for (int x = FX; x < min(FX+size, X); ++x)
		{
			for (int y = FY; y < min(FY + size, Y); ++y)
			{
				c = getpixel(x, y);
				S_R +=((c >> 16) & 0xff);
				S_G += (c >> 8) & 0xff;
				S_B += c & 0xff;
				
				++n;
				
			}
		}
		R = S_R / n;
		G = S_G / n;
		B = S_B / n;
		for (int x = FX; x < min(FX + size, X); ++x)
		{
			for (int y = FY; y < min(FY + size, Y); ++y)
			{
				c = (R << 16) + (G << 8) + B;
				//c = 0;
				putpixel(x, y, c);//再将新的显示回去

			}
		}

		
		
		n = 1;
		}
		
	}
	//system("pause");
}

int main()
{
	PS a;
	a.P_BLACK();
	a.P_FP();
	a.P_MSK();
}

黑白

负片


 

 

                                                                          马赛克

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值