[MFC / C ++] Отправка битов CBitmap через сокет и восстановление его на стороне получателя

Я новичок в MFC и пытаюсь изучить его с проектом диалоговой базы MFC на VS2008. Вот архивы, которые я сделал:

Во-первых, мне удалось отобразить список изображений из папки в элемент управления Listbox. После этого я также обработал событие click в каждой строке списка, чтобы загрузить и показать изображение в Picture Control (тип Bitmap) с правой стороны. Вы можете увидеть изображение ниже для легкого понимания: Пожалуйста, нажмите здесь для изображения моего диалога MFC

Вот код Заметка m_ListCtrl а также static_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);
}

}

Теперь я хотел бы продвинуться еще на один шаг и попытаться работать с сокетом … и да, я успешно отправил и получил простой символ * или CString поверх сокета.

То, что я хочу сделать: вместо того, чтобы показывать изображение в этом диалоговом окне, оно показывает изображение в другом диалоговом окне (на сервере).

Каким-то образом я узнал, что есть две функции, которые хорошо работают 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;

И это просто не работает … Скажите, пожалуйста, где я все испортил? И извините за длинный пост …..

2

Решение

Я думаю, что наиболее вероятной причиной является то, что ваш приемник не получает все данные изображения. Я предлагаю вам при отправке указать размер растрового изображения в пакет, чтобы получатель получил правильный размер.

Вот пример кода. Имейте в виду, что они просто для демонстрации идеи, вам может понадобиться отладка, чтобы убедиться, что они работают.

Шаг 1: Упакуйте размер растрового изображения. Я предполагаю, что здесь размер меньше 64 КБ, поэтому используется int. Если размер может быть больше, чем 64 КБ, вы можете использовать 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.

шаг 2: отправить его
Имейте в виду, я использую здесь 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.

Опять же, этот код просто для демонстрации идеи.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector