urif
asked on
Saving a screenshot to a buffer
using the function posted below I can take a screenshot and save it to a file (in this case a JPEG).
Is there any way to save the data from the screenshot to a buffer (an array of bytes, or chars or whatever) instead of saving it to disk?
Code is appreciated, in C please. Thanks.
Is there any way to save the data from the screenshot to a buffer (an array of bytes, or chars or whatever) instead of saving it to disk?
Code is appreciated, in C please. Thanks.
int GetScreeny(LPWSTR lpszFilename, ULONG uQuality)
{
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
HDC hdcCapture = CreateCompatibleDC(hdcScreen);
int nWidth = GetDeviceCaps(hdcScreen, HORZRES),
nHeight = GetDeviceCaps(hdcScreen, VERTRES),
nBPP = GetDeviceCaps(hdcScreen, BITSPIXEL);
LPBYTE lpCapture;
BITMAPINFO bmiCapture = { {
sizeof(BITMAPINFOHEADER), nWidth, -nHeight, 1, nBPP, BI_RGB, 0, 0, 0, 0, 0,
} };
HBITMAP hbmCapture = CreateDIBSection(hdcScreen, &bmiCapture,
DIB_PAL_COLORS, (LPVOID *)&lpCapture, NULL, 0);
if(!hbmCapture){
DeleteDC(hdcCapture);
DeleteDC(hdcScreen);
GdiplusShutdown(gdiplusToken);
return 1;
}
int nCapture = SaveDC(hdcCapture);
SelectObject(hdcCapture, hbmCapture);
BitBlt(hdcCapture, 0, 0, nWidth, nHeight, hdcScreen, 0, 0, SRCCOPY);
RestoreDC(hdcCapture, nCapture);
DeleteDC(hdcCapture);
DeleteDC(hdcScreen);
CLSID imageCLSID;
Bitmap *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);
int result = (pScreenShot->Save(lpszFilename, &imageCLSID, &encoderParams) == Ok);
delete pScreenShot;
DeleteObject(hbmCapture);
GdiplusShutdown(gdiplusToken);
return result;
}
ASKER
It seems to be the right function. I'm trying to get all the bitmap's content as a jped and instead of saving it to a file i want to save those bytes into a buffer. Then just dump the buffer to either a flat file or to the stdout.
the GetEncoderClsid() function on the code that i posted earlier is here below.
any idea of the code for doing this? I mean, from the example on the MSDN i can learn a bit about how to read that data but i am still having trouble putting all those bytes into a buffer that i can use.
thanks
the GetEncoderClsid() function on the code that i posted earlier is here below.
any idea of the code for doing this? I mean, from the example on the MSDN i can learn a bit about how to read that data but i am still having trouble putting all those bytes into a buffer that i can use.
thanks
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;
}
So do you want the jpeg output saved to a memory block? If that is the case, you should use the Save method which takes a stream (instead of a file name).
http://msdn.microsoft.com/en-us/library/ms535406(VS.85).aspx
To create a memory stream, you can use CreateStreamOnHGlobal:
http://msdn.microsoft.com/en-us/library/ms535406(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms535406(VS.85).aspx
To create a memory stream, you can use CreateStreamOnHGlobal:
http://msdn.microsoft.com/en-us/library/ms535406(VS.85).aspx
I messed up the link to the CreateStreamOnHGlobal. Here is the correct link:
http://msdn.microsoft.com/en-us/library/aa378980.aspx
http://msdn.microsoft.com/en-us/library/aa378980.aspx
ASKER
Thanks,
I run into those functions after your first post as I was searching the gdiplus API.
Maybe it is my lack of experience with COM, or the fact that i never got any of the MSDN code to work or the fact that I don't understand the way the MSDN explains anything (i'm an old time UNIX programmer).
In any case, i still can't find a way to save that image to a buffer.
If you can, could you please post some working code that can do this?
I appreciate the help
I run into those functions after your first post as I was searching the gdiplus API.
Maybe it is my lack of experience with COM, or the fact that i never got any of the MSDN code to work or the fact that I don't understand the way the MSDN explains anything (i'm an old time UNIX programmer).
In any case, i still can't find a way to save that image to a buffer.
If you can, could you please post some working code that can do this?
I appreciate the help
Come now, it is not that hard. (I am a UNIX programmer from way back myself). Attached is a code snippet which shows you how you might do it.
HGLOBAL hMem;
if (hMem = GlobalAlloc(GMEM_MOVEABLE, 0))
{
IStream * pStream;
if (CreateStreamOnHGlobal(hMem, FALSE, &pStream) == S_OK)
{
Status result;
result = pBitmap->Save(pStream, pEncoder);
pStream->Release();
if (result == Ok)
{
unsigned char * pBytes;
if (pBytes = (unsigned char *) GlobalLock(hMem))
{
/*
* pBytes now points to your image file in memory
* in whatever format was specified by your encoder
* parameter.
*/
}
}
}
}
ASKER
error C2664: 'Gdiplus::Status Gdiplus::Image::Save(const WCHAR *,const CLSID *,const Gdiplus::EncoderParameters *)' : cannot convert parameter 1 from 'IStream *' to 'const WCHAR *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
I am casting it but i still get the error. besides, you are placing inside the save something i assume is EncoderParameters (the variable is pEncoder). Now, maybe i am missing something but that won't point to the actual bitmap data.
anyway, it's a mess to try to putt hat code inside the original function since i am guessing most of the variables on your code.
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
I am casting it but i still get the error. besides, you are placing inside the save something i assume is EncoderParameters (the variable is pEncoder). Now, maybe i am missing something but that won't point to the actual bitmap data.
anyway, it's a mess to try to putt hat code inside the original function since i am guessing most of the variables on your code.
ASKER
ok, this code below is my try. it compiles but it just does nothing. I debug it but nothing gets saved anywhere.
if (hMem = GlobalAlloc(GMEM_MOVEABLE, 0))
{
IStream * pStream;
if (CreateStreamOnHGlobal(hMem, FALSE, &pStream) == S_OK)
{
// 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);
result = pScreenShot->Save(pStream, &imageCLSID, &encoderParams);
pStream->Release();
//if (result == Ok)
//{
unsigned char * pBytes;
if (pBytes = (unsigned char *) GlobalLock(hMem))
{
/*
* pBytes now points to your image file in memory
* in whatever format was specified by your encoder
* parameter.
*/
printf("bitmap = %s\n", pBytes);
}
else
{
printf("error GlobalLock. Last err: %d\n", GetLastError());
return 0;
}
//}
}
else
{
printf("error CreateStreamOnHGlobal. Last err: %d\n", GetLastError());
return 0;
}
}
else
{
printf("error GlobalAlloc. Last err: %d\n", GetLastError());
return 0;
}
return result;
Is the save returning OK (I notice that you have the check commented out)? I am not really sure why you are trying to print the string returned by GlobalLock. It is NOT an ASCII string that you can print in that manner, rather it is a pointer to the binary JPEG file.
Perhaps if you tell me exactly what you are trying to do, I might be able to suggest something.
Perhaps if you tell me exactly what you are trying to do, I might be able to suggest something.
ASKER
the printf was there for the purpose of testing.
what i need to do is to grab that jpeg data, copy it to an array to whatever and wither save it to a file or add it to another buffer. That's all.
thanks for the help
what i need to do is to grab that jpeg data, copy it to an array to whatever and wither save it to a file or add it to another buffer. That's all.
thanks for the help
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
great! thanks!
ASKER
thanks so much for all the effort.
http://msdn.microsoft.com/en-us/library/ms536298(VS.85).aspx