[个人笔记][C++]自拟的将屏幕图像分割成色块后,同色像素合并压缩传输的图像传输算法

该文章是记录自己做过自拟算法的设计与研究

发送方代码片段

void sendImageRun() {
		const int SCEEN_WIDTH = 1600;
		const int SCEEN_HEIGHT = 700;
		const int SCEEN_SIZE = SCEEN_WIDTH * SCEEN_HEIGHT;
		//色块的宽高
		const int BLOCK_WH = 90;
		//当前图像
		IMAGE img{ SCEEN_WIDTH,SCEEN_HEIGHT };
		//历史图像
		IMAGE imgHistory{ SCEEN_WIDTH,SCEEN_HEIGHT };
		// 获取桌面 DC
		HDC srcDC = GetDC(NULL);	
		// 获取 IMAGE 对象的 DC
		HDC imgDC = GetImageHDC(&img);	
		DWORD* imgBufPtr = GetImageBuffer(&img);
		DWORD* imgHistoryBufPtr = GetImageBuffer(&imgHistory);
		//一行中完整的色块数量
		const int BLOCK_NUM_ROW = SCEEN_WIDTH / BLOCK_WH;
		//一行中额外的色块所占据的像素
		const int BLOCK_PIX_ROW_EXT = SCEEN_WIDTH % BLOCK_WH;
		//一行中所有的色块数量
		const int BLOCK_NUM_ROW_VIR = (BLOCK_PIX_ROW_EXT == 0) ? BLOCK_NUM_ROW : BLOCK_NUM_ROW + 1;
		//一列中完整的色块数量
		const int BLOCK_NUM_COL = SCEEN_HEIGHT / BLOCK_WH;
		//一列中额外的色块所占据的像素
		const int BLOCK_PIX_COL_EXT = SCEEN_HEIGHT % BLOCK_WH;
		//一列中所有的色块数量
		const int BLOCK_NUM_COL_VIR = (BLOCK_PIX_COL_EXT == 0) ? BLOCK_NUM_COL : BLOCK_NUM_COL + 1;
		//设置包结构
		size_t sendBufSize = 4 + sizeof(int) * 5 + 2 * BLOCK_WH * BLOCK_WH * sizeof(DWORD);
		char* sendBuf = new char[sendBufSize];
		int i, j, k;
		sockaddr addrUdpSend;
		int len = sizeof(sockaddr);
		memset(sendBuf, 0, sendBufSize);
		while (true) {
			recvfrom(_socketUdp, sendBuf, sendBufSize, 0, &addrUdpSend, &len);//等待反馈
			if (sendBuf[0]) {
				cout << "UDP链接打通" << endl;
				break;
			}
			memset(sendBuf, 0, sendBufSize);
		}
		strcpy_s(sendBuf, 4 + 1, "0001");
		while (isCon) {
			BitBlt(imgDC, 0, 0, SCEEN_WIDTH, SCEEN_HEIGHT, srcDC, 0, 0, SRCCOPY);
			//计算应该更新第几块色块
			for (i = 0; i < SCEEN_SIZE; ++i) {
				//如果发现像素颜色有所更改,则更新色块
				if (imgBufPtr[i] != imgHistoryBufPtr[i]) {
					//像素所在行列
					int row = i / SCEEN_WIDTH;
					int col = i % SCEEN_WIDTH;
					//计算出在色块的第几行
					row /= BLOCK_WH;
					//计算出在色块的第几列
					col /= BLOCK_WH;
					//计算出是第几个色块:[0,n)
					int num = row * BLOCK_NUM_COL_VIR + col;
					int blockWidth = BLOCK_WH;
					int blockHeight = BLOCK_WH;
					//如果是额外方块
					if (row + 1 == BLOCK_NUM_COL_VIR && BLOCK_PIX_ROW_EXT > 0) {
						blockHeight = BLOCK_PIX_COL_EXT;
					}
					//如果是额外方块
					if (col + 1 == BLOCK_NUM_ROW_VIR && BLOCK_PIX_COL_EXT > 0) {
						blockWidth = BLOCK_PIX_ROW_EXT;
					}
					//更新色块
					//获取要更新的色块的起始坐标
					j = row * BLOCK_WH;//第几行
					k = col * BLOCK_WH;//第几列
					((int*)(&sendBuf[4]))[0] = k;
					((int*)(&sendBuf[4]))[1] = j;
					int jMax = j + blockHeight;
					int kMax = k + blockWidth;
					//辅助sendBuf进行色块填写的变量
					int sendBufNum = 0;
					DWORD color = imgBufPtr[j * SCEEN_WIDTH + k];
					vector<pair<int, DWORD>> colorGroup;
					colorGroup.push_back(pair<int, DWORD>(0, color));
					for (; j < jMax; ++j) {
						for (k = col * BLOCK_WH; k < kMax; ++k) {
							imgHistoryBufPtr[j * SCEEN_WIDTH + k] = imgBufPtr[j * SCEEN_WIDTH + k];
							//进行压缩处理后再传送
							if (color == imgBufPtr[j * SCEEN_WIDTH + k]) {
								colorGroup[colorGroup.size() - 1] =
									pair<int, DWORD>(colorGroup[colorGroup.size() - 1].first + 1, color);
							}
							else {
								color = imgBufPtr[j * SCEEN_WIDTH + k];
								colorGroup.push_back(pair<int, DWORD>(1, color));
							}
						}
					}
					int spaceNum = colorGroup.size();
					for (j = 0; j < spaceNum; ++j) {
						((int*)(&sendBuf[4 + 5 * sizeof(int)]))[j]
							= colorGroup[j].first;
						((DWORD*)(&sendBuf[4 + 5 * sizeof(int) + spaceNum * sizeof(int)]))[j]
							= colorGroup[j].second;
					}
					((int*)(&sendBuf[4]))[4] = spaceNum;
					//发送色块
					((int*)(&sendBuf[4]))[2] = blockWidth;
					((int*)(&sendBuf[4]))[3] = blockHeight;
					sendto(_socketUdp, sendBuf, 4 + 5 * sizeof(int) + colorGroup.size() * (sizeof(int) + sizeof(DWORD)), 0, &addrUdpSend, sizeof(sockaddr));//发送图像信息
					//send(cliSockets._socket, sendBuf, sendBufSize, 0);//发送图像信息
					//重设i,将其放入下一个方块
					++col;
					//超过了最后一列?
					if (col == BLOCK_NUM_ROW_VIR) {
						col = 0;
						++row;
						//换行后超过了最后一行?
						if (row == BLOCK_NUM_COL_VIR)
							i = 0;
						else {
							i = row * BLOCK_WH * SCEEN_WIDTH;
						}
					}
					else {
						i = row * BLOCK_WH * SCEEN_WIDTH + col * BLOCK_WH;
					}
					//重设i完毕
				}
			}
			//((int*)(&sendBuf[4]))[0] = start;
			//((int*)(&sendBuf[4]))[1] = num;
			//for (i = 0; i < num; ++i) {
			//	((DWORD*)(&sendBuf[4 + 2 * sizeof(int)]))[i] = 
			//		imgBufPtr[(start + i) % (SCEEN_HEIGHT * SCEEN_WIDTH)];
			//}
			//start += num;
			//start = start % (SCEEN_HEIGHT * SCEEN_WIDTH);
			//sendto(_socketUdp, sendBuf, sendBufSize, 0, (sockaddr*)&addrUdpSend, sizeof(sockaddr));//发送图像信息

			//for (j = 0; j < SCEEN_HEIGHT; ++j) {
			//	((int*)(&sendBuf[4]))[0] = j;
			//	for (i = 0; i < SCEEN_WIDTH; ++i) {
			//		((DWORD*)(&sendBuf[4 + sizeof(int)]))[i] = imgBufPtr[j * SCEEN_WIDTH + i];
			//	}
			//	sendto(_socketUdp, sendBuf, sendBufSize, 0, (sockaddr*)&addrUdpSend, sizeof(sockaddr));//发送图像信息
			//}
			Sleep(30);
		}
		delete[] sendBuf;
	}

接收方代码片段

void recvImageRun() {
		const int SCEEN_WIDTH = 1600;
		const int SCEEN_HEIGHT = 700;
		//色块的宽高
		const int BLOCK_WH = 90;
		initgraph(SCEEN_WIDTH, SCEEN_HEIGHT);
		BeginBatchDraw();
		DWORD* pp = GetImageBuffer();
		size_t recvBufSize = 4 + sizeof(int) * 5 + 2 * BLOCK_WH * BLOCK_WH * sizeof(DWORD);
		char* recvBuf = new char[recvBufSize];
		memset(recvBuf, 0, recvBufSize);//初始化地址结构为0
		int i, j;
		int len = sizeof(sockaddr);
		sendto(_socketUdp, "sendTry", sizeof("sendTry"), 0, (sockaddr*)&addrUdp, sizeof(sockaddr));//建立通道
		while (isCon) {
			recvfrom(_socketUdp, recvBuf, recvBufSize, 0, (sockaddr*)&addrUdp, &len);//等待反馈
			//recv(_socket, recvBuf, recvBufSize, 0);
			if (recvBuf[0]) {
				char codeCh[5]{};
				for (i = 0; i < 4; ++i)
					codeCh[i] = recvBuf[i];
				//if(codeCh[0]=='0'&& codeCh[1] == '0'&& codeCh[2] == '0'&& codeCh[3] == '1')
				switch (atoi(codeCh)) {
				case 1: {
					//更新图像
					int blockX = ((int*)(&recvBuf[4]))[0];
					int blockY = ((int*)(&recvBuf[4]))[1];
					int blockWidth = ((int*)(&recvBuf[4]))[2];
					int blockHeight = ((int*)(&recvBuf[4]))[3];
					int spaceNum = ((int*)(&recvBuf[4]))[4];
					int jMax = blockY + blockHeight;
					int kMax = blockX + blockWidth;
					int recvNum = 0;
					int colorNum = 0;
					DWORD color;
					for (; blockY < jMax; ++blockY) {
						for (blockX = ((int*)(&recvBuf[4]))[0]; blockX < kMax; ++blockX) {
							if (colorNum == 0) {
								colorNum = ((int*)(&recvBuf[4 + sizeof(int) * 5]))[recvNum];
								color = ((DWORD*)(&recvBuf[4 + sizeof(int) * 5 + sizeof(int) * spaceNum]))[recvNum];
								++recvNum;
							}
							--colorNum;
							pp[blockY * SCEEN_WIDTH + blockX] = color;
						}
					}
					FlushBatchDraw();

					//int start = ((int*)(&recvBuf[4]))[0];
					//int num = ((int*)(&recvBuf[4]))[1];
					//for (i = 0; i < num; ++i) {
					//	if (start + i > SCEEN_WIDTH * SCEEN_HEIGHT) {
					//		start = -i;
					//		tmp = i;
					//	}
					//	pp[(start + i) % (SCEEN_HEIGHT * SCEEN_WIDTH)] = ((DWORD*)(&recvBuf[4 + 2 * sizeof(int)]))[i];
					//}

					//int row = ((int*)(&recvBuf[4]))[0];
					//for (i = 0; i < SCEEN_WIDTH; ++i) {
					//	pp[i + row * SCEEN_WIDTH] = ((DWORD*)(&recvBuf[4 + sizeof(int)]))[i];
					//}
					break;
				}
				}
				memset(recvBuf, 0, recvBufSize);//初始化地址结构为0
			}
		}
		EndBatchDraw();
		closegraph();
		delete[] recvBuf;
	}

你可能感兴趣的:(算法,算法,c++,开发语言)