c++ - [MFC/C++]通过套接字发送CBitmap的位,并在接收方重新构造它

标签 c++ mfc asyncsocket

刚接触MFC,尝试通过一个基于VS2008的MFC对话框项目来学习。以下是我所做的存档:

首先,我设法将文件夹中的图片列表显示到列表框控件中。之后,我还处理了列表框每一行的点击事件,以将图片加载并显示到右侧的图片控件(位图类型)。您可以查看下图以便于理解:Please click here for the image of my MFC dialog

这是代码。注意 m_ListCtrlstatic_picture 是列表框和图片控件的变量:

void CMyClientDlg::OnLbnSelchangeList1(){

CString imagePath;
m_ListCtrl.GetText(m_ListCtrl.GetCurSel(),imagePath);

CImage picture;
picture.Load(imagePath);

if (!picture.IsNull())
{
    float screenWidth = 200, screenHeight = 200;
    float imageWidth = picture.GetWidth();
    float imageHeight = picture.GetHeight();

    //scaling:
    float pictureRatio = imageWidth/ imageHeight;
    float newImageWidth;
    float newImageHeight;
    int aligmentX = 0;
    int aligmentY = 0;
    if (pictureRatio <= 1)
    {
        newImageWidth = imageWidth*(screenHeight/imageHeight);
        newImageHeight = screenHeight;
        aligmentX = (screenWidth-newImageWidth)/2;
    }
    else
    {
        newImageWidth = screenWidth;
        newImageHeight = imageHeight*(screenWidth/imageWidth);
        aligmentY = (screenHeight - newImageHeight)/2;
    }
    //end scaling.
    CDC *screenDC = GetDC();
    CDC mDC;
    mDC.CreateCompatibleDC(screenDC);

    CBitmap bitMap;
    bitMap.CreateCompatibleBitmap(screenDC, screenWidth, screenHeight);
    CBitmap *pob = mDC.SelectObject(&bitMap);
    mDC.SetStretchBltMode(HALFTONE);
    picture.StretchBlt(mDC.m_hDC, aligmentX, aligmentY, newImageWidth, newImageHeight, 0, 0, imageWidth, imageHeight, SRCCOPY);
    mDC.SelectObject(pob);

    /*.......code to convert bitmap to BYTE* ........*/
    /*.......code to send BYTE* over socket........*/       

    //display the bit map
    static_picture.SetBitmap((HBITMAP)bitMap.Detach());

    //clean up
    ReleaseDC(screenDC);
}   



所以现在我想更进一步,并尝试使用套接字...是的,我成功地通过套接字发送和接收了简单的 char* 或 CString。
我想要做的是:而不是在这个对话框上显示图片,而是在另一个对话框(服务器)上显示图像。
不知何故,我了解到有 2 个函数听起来很有效:SetBitmapBits()GetBitmapBits()(老实说,我只是在一些来源上阅读它,并不知道如果他们适合我的目标)。

因此,我添加了这段代码,将上面的位图转换为 BYTE bmpBuffer 数组:

BITMAP bmpProperties;
bitMap.GetBitmap(&bmpProperties);
int bmpDemension = bmpProperties.bmWidthBytes*bmpProperties.bmHeight;
BYTE* bmpBuffer=(BYTE*)GlobalAlloc(GPTR, bmpDemension);
bitMap.GetBitmapBits(bmpDemension,bmpBuffer);

然后通过套接字发送该数组:

UpdateData(TRUE);
char *socketBuffer = reinterpret_cast<char*>(bmpBuffer);
send(m_ClientSocket, socketBuffer, sizeof(socketBuffer), 0);
//clean up after send
GlobalFree((HGLOBAL)bmpBuffer);

在另一个对话框中。注意:我已经将位图的维度硬编码为 160000,只是为了简化问题:

void CMyServer2Dlg::OnReceive(){    
char *socketBuffer = new char [1025];
int iLen; 
iLen = recv(m_sConnected, socketBuffer, 1025, NULL);
if(iLen==SOCKET_ERROR)
{
    AfxMessageBox("Could not Receive");
}
else
{
    BYTE* bmpBuffer = reinterpret_cast<BYTE*>(socketBuffer);

    //re-construct the bitmap
    CBitmap clone;
    CDC *screenDC = GetDC();
    CDC mDC;
    mDC.CreateCompatibleDC(screenDC);

    clone.CreateCompatibleBitmap(screenDC, 200, 200);
    clone.SetBitmapBits(160000,bmpBuffer);

    //Picture control(type bitmap) has variable "static_picture"
    static_picture.SetBitmap((HBITMAP)clone.Detach());

    UpdateData(FALSE);
    ReleaseDC(screenDC);
    GlobalFree((HGLOBAL)bmpBuffer);
}
delete socketBuffer;

而且,它根本不起作用...请告诉我我在哪里搞砸了?抱歉发了这么长的帖子......

最佳答案

我觉得最可能的原因是你的接收端没有获取到图片的所有数据。我建议您在发送时将位图的大小放入包中,以便接收方获得正确的大小。

这里有一些示例代码。请注意,它们只是为了展示想法,您可能需要进行一些调试以确保它们有效。

第一步:打包位图大小。我想这里的大小小于 64K,所以使用了 int。如果大小可能大于 64k,您可能需要使用 INT64。

int bmpDemension = bmpProperties.bmWidthBytes*bmpProperties.bmHeight;
int bufferSize = bmpDemension + sizeof(int);
BYTE* bmpBuffer=(BYTE*)GlobalAlloc(GPTR, bufferSize );
bitMap.GetBitmapBits(bmpDemension,bmpBuffer + sizeof(int));
memcpy(bmpBuffer, &bmpDemension, sizeof(int)); // put the size into the head of package.

第二步:发送出去 请注意,我在这里使用 bufferSize,因为 sizeof(bmpBuffer) 返回指针大小,即 4,而不是空间大小。

UpdateData(TRUE);
char *socketBuffer = reinterpret_cast<char*>(bmpBuffer);
send(m_ClientSocket, socketBuffer, bufferSize , 0);
 //clean up after send
GlobalFree((HGLOBAL)bmpBuffer);

在接收端: 首先读取位图的大小,然后根据数据的大小进行接收。

void CMyServer2Dlg::OnReceive(){    
char socketBuffer[1025];
int iLen; 
iLen = recv(m_sConnected, socketBuffer, sizeof(int), NULL); //read the bigmap size
if(iLen==SOCKET_ERROR)
{
AfxMessageBox("Could not Receive");
}
else
{
int dimension = *((int *) socketBuffer);
char * bitmapBuffer = new char[dimension];
int readSize = dimension;
char * pBuffer = bitmapBuffer;
while (readSize > 0)
{
    int sizeToRead = readSize > sizeof(socketBuffer) ? sizeof(socketBuffer) : readSize;
    iLen = recv(m_sConnected, socketBuffer, sizeToRead , NULL);
    memcpy(pBuffer, socketBuffer, iLen);
    pBuffer += iLen;
    readSize -= iLen;
}
// when the loop done, you shall have all data in bitmapBuffer.
....    
// I leave the remaining code to you.

同样,这些代码只是为了演示这个想法。

关于c++ - [MFC/C++]通过套接字发送CBitmap的位,并在接收方重新构造它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37018349/

相关文章:

c++ - mfc 程序使用了错误的小数分隔符/语言

c++ - Release 和 Debug 的依赖区别

c# - 在 Monotouch 中增加 ThreadPool 线程数?

C# 异步对象传输(套接字?)

c++ - 跨平台换行混淆

c++ - 适用于 Windows (UWP) 而不是 iOS 的通用运行时组件 #ifdef 是什么?

c++ - 使用 3D 声音时,我听不出前后位置的区别

c++ - MFC 自定义 - 添加新的工具栏?

python - 断言isinstance(地址,(元组,列表,str)), "tuple or str expected"AssertionError : tuple or str expected

c++ -::(范围解析运算符) 前面没有任何内容