4

I am trying to take a screenshot of the whole screen and would like to send it over the network to a server. (the server will be the one to save it)

I am currently using this code

HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, w, h);

CImage image;
image.Attach(hBitmap);
image.Save(L"screen.jpg");

It does save the file, but that's not what I want. I'm also not sure how to get the bytes, I was thinking of GetBits() but the documentation says it is a pointer to the data of the underlying Bitmap.

What I want to get is the JPG data which I can send through the network and save the image using the server.

So, why am I not just using bitmap and sending it directly? because it is a bit complicated and the code was quite long, you'll have to get the header and stuff. I could be wrong though.

My question:
- How do I get the bytes from the image so I can send it to the server? (like a BLOB to save to the database)
- Any library that can help me convert and get bytes all in memory?

references:
https://msdn.microsoft.com/en-us/library/ms535406(v=VS.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms535406(v=vs.85).aspx
http://www.codeproject.com/Tips/738533/save-load-image-between-buffer
majidarif
  • 18,694
  • 16
  • 88
  • 133
  • You already know how to save the image to a (temporary) jpeg encoded file. So the simplest approach would be to read the binary file into some array, send the array across, and on the server save it. – Dan Mašek Apr 11 '16 at 09:04
  • 1
    @DanMašek yes, but I wan't to avoid writing files to disk, I wish to do it all in memory. – majidarif Apr 11 '16 at 09:05
  • I follow. How about the comment by Hans Passant to [this answer](http://stackoverflow.com/a/10461459/3962537)? I realize it's about loading, but I assume saving should work similarly. Other than that, you could also use libjpeg. – Dan Mašek Apr 11 '16 at 09:09
  • Quite confused with how the comment helps me, he is talking about loading the image from the buffer. I want to get the buffer from the converted image. – majidarif Apr 11 '16 at 09:14
  • AFAICT, there is an overload `HRESULT Save(IStream* pStream, REFGUID guidFileType) const throw();`. So you create an in-memory stream to write to, instead of reading from. The documenation for [`CreateStreamOnHGlobal(...)`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa378980%28v=vs.85%29.aspx) has some info too. – Dan Mašek Apr 11 '16 at 09:20
  • Ah, right, I just noticed. Will try. – majidarif Apr 11 '16 at 09:23

1 Answers1

5

So Dan pointed out that there is actually a method Save that can use a Stream. I've decided to use this approach, which I got from one of the references listed in my question

vector<BYTE> buf;
IStream *stream = NULL;
HRESULT hr = CreateStreamOnHGlobal(0, TRUE, &stream);
CImage image;
ULARGE_INTEGER liSize;

// screenshot to jpg and save to stream
image.Attach(hBitmap);
image.Save(stream, Gdiplus::ImageFormatJPEG);
IStream_Size(stream, &liSize);
DWORD len = liSize.LowPart;
IStream_Reset(stream);
buf.resize(len);
IStream_Read(stream, &buf[0], len);
stream->Release();

// just testing if the buf contains the correct data
fstream fi;
fi.open("aaashot.jpg", fstream::binary | fstream::out);
fi.write(reinterpret_cast<const char*>(&buf[0]), buf.size()*sizeof(BYTE));
fi.close();
majidarif
  • 18,694
  • 16
  • 88
  • 133