该文章是记录自己做过自拟算法的设计与研究
发送方代码片段
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;
}