我在C ++中使用服务器应用程序制作屏幕截图,必须将其传输到用C#编写的客户端。我遇到了一些问题:
问题在于我不知道实现这一目标的正确算法。将图像保存到服务器端的文件并传输文件然后将文件保存在客户端上,然后将其读取到图片框也不是解决方案。因此,总结我的任务:如何将位图转换为轻量级格式并将其传输到客户端?
感谢您的时间!
答案 0 :(得分:2)
如果您可以使用c ++应用程序中的.Net托管代码,那么您可以使用本机库(请参阅https://stackoverflow.com/a/3517974/149818)。
如果您仅受明确的c ++限制,请参阅LodePNG
答案 1 :(得分:1)
您可以在c ++端使用libpng转换为.png。 在C#端,Bitmap类.png可以通过以下方式加载:
new Bitmap(png);
请记住:我对C#方面可能不对。
答案 2 :(得分:0)
非常感谢回答这个问题!经过对堆栈的一些研究后,我发现了类似的问题,并且有一个代码可以将jpg图像转换为可以通过套接字传输的字节数组。这是(某些变量可能未使用)
#include <objidl.h>
#include <Gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
int GetEncoderClsid(WCHAR *format, CLSID *pClsid)
{
unsigned int num = 0, size = 0;
GetImageEncodersSize(&num, &size);
if (size == 0) return -1;
ImageCodecInfo *pImageCodecInfo = (ImageCodecInfo *)(malloc(size));
if (pImageCodecInfo == NULL) return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for (unsigned int j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0){
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
BYTE *GetScreeny(LPWSTR lpszFilename, ULONG uQuality, int *buff_size) // by Napalm
{
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HWND hMyWnd = GetDesktopWindow(); // get my own window
RECT r; // the area we are going to capture
int w, h; // the width and height of the area
HDC dc; // the container for the area
int nBPP;
HDC hdcCapture;
LPBYTE lpCapture;
int nCapture;
int iRes;
CLSID imageCLSID;
Bitmap *pScreenShot;
HGLOBAL hMem;
int result;
// get the area of my application's window
//GetClientRect(hMyWnd, &r);
GetWindowRect(hMyWnd, &r);
dc = GetWindowDC(hMyWnd);// GetDC(hMyWnd) ;
w = r.right - r.left;
h = r.bottom - r.top;
nBPP = GetDeviceCaps(dc, BITSPIXEL);
hdcCapture = CreateCompatibleDC(dc);
// create the buffer for the screenshot
BITMAPINFO bmiCapture = {
sizeof(BITMAPINFOHEADER), w, -h, 1, nBPP, BI_RGB, 0, 0, 0, 0, 0,
};
// create a container and take the screenshot
HBITMAP hbmCapture = CreateDIBSection(dc, &bmiCapture,
DIB_PAL_COLORS, (LPVOID *)&lpCapture, NULL, 0);
// failed to take it
if (!hbmCapture)
{
DeleteDC(hdcCapture);
DeleteDC(dc);
GdiplusShutdown(gdiplusToken);
printf("failed to take the screenshot. err: %d\n", GetLastError());
return 0;
}
// copy the screenshot buffer
nCapture = SaveDC(hdcCapture);
SelectObject(hdcCapture, hbmCapture);
BitBlt(hdcCapture, 0, 0, w, h, dc, 0, 0, SRCCOPY);
RestoreDC(hdcCapture, nCapture);
DeleteDC(hdcCapture);
DeleteDC(dc);
GpImage *bob;
IStream *ssStr;
// save the buffer to a file
pScreenShot = new Bitmap(hbmCapture, (HPALETTE)NULL);
EncoderParameters encoderParams;
encoderParams.Count = 1;
encoderParams.Parameter[0].NumberOfValues = 1;
encoderParams.Parameter[0].Guid = EncoderQuality;
encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParams.Parameter[0].Value = &uQuality;
GetEncoderClsid(L"image/jpeg", &imageCLSID);
IStream *pStream = NULL;
LARGE_INTEGER liZero = {};
ULARGE_INTEGER pos = {};
STATSTG stg = {};
ULONG bytesRead = 0;
HRESULT hrRet = S_OK;
//BYTE* buffer = NULL; // this is your buffer that will hold the jpeg bytes
DWORD dwBufferSize = 0; // this is the size of that buffer;
hrRet = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
hrRet = pScreenShot->Save(pStream, &imageCLSID, &encoderParams) == 0 ? S_OK : E_FAIL;
hrRet = pStream->Seek(liZero, STREAM_SEEK_SET, &pos);
hrRet = pStream->Stat(&stg, STATFLAG_NONAME);
// allocate a byte buffer big enough to hold the jpeg stream in memory
BYTE *buffer = new BYTE[stg.cbSize.LowPart];
//buffer = (BYTE *)malloc(stg.cbSize.LowPart);
hrRet = (buffer == NULL) ? E_OUTOFMEMORY : S_OK;
dwBufferSize = stg.cbSize.LowPart;
//wchar_t message[512];
//wsprintf(message, L"%d", stg.cbSize.LowPart);
//MessageBox(NULL, message, NULL, MB_OK);
// copy the stream into memory
hrRet = pStream->Read(buffer, stg.cbSize.LowPart, &bytesRead);
// now go save "buffer" and "dwBufferSize" off somewhere. This is the jpeg buffer
// don't forget to free it when you are done
// After success or if any of the above calls fail, don't forget to release the stream
if (pStream)
{
pStream->Release();
}
delete pScreenShot;
DeleteObject(hbmCapture);
GdiplusShutdown(gdiplusToken);
*buff_size = (int)dwBufferSize;
//return iRes;
return buffer;
}