I\'m trying to find a (somewhat) easy way to take a screenshot on window and save the resulting HBITMAP as a JPEG. The tricky part here is that since the code is in C I can\
Good image compression is hard. There's a reason library code exists for the common formats. It requires a lot of code to do. Your constraints on the problem don't make it sound like there is a practical solution.
There are a couple things to try.
Use an 8-bit per pixel BMP rather than a true color BMP. This assumes that the information loss in color mapping is acceptable, of course. It will buy you a factor of three in file size over a 24-bit BMP.
Try using run length encoding in the BMP you write. RLE is a documented format for BMP, and there should be plenty of sample code out there to make it. It works best on images that have a lot of long runs of identical color. A typical screen without too many gradients and fills fits that description.
If those aren't sufficient, then you might need to resort to a stronger compression. The source code to libjpeg is readily available, and it is possible to statically link it rather than using the DLL. It will require some effort to configure in only the bits you need, but the compression and decompression code are almost completely independent of each other and that splits the library almost in half.
You will probably have to use an external library to create a JPEG in C code--there won't be a standard library function to do it. Of course, you could also study the file format and write a function to generate your own, based on the criteria. You could start at wikipedia. If you really can't just use an external library, you could read into the relevant functions of the library to learn about how to generate your own JPEGs. But that sounds like a lot more work than just using the library.
Also, I don't believe the size of a library really comes into play with C -- I believe you only get the size of the functions you call from that library (I think, anyway). Of course if all the functions are tightly coupled than it'd be huge anyway.
Translating to the flat GDI+ API is fairly straight forward:
void SaveJpeg(HBITMAP hBmp, LPCWSTR lpszFilename, ULONG uQuality)
{
GpBitmap* pBitmap;
GdipCreateBitmapFromHBITMAP(hBmp, NULL, &pBitmap);
CLSID imageCLSID;
GetEncoderClsid(L"image/jpeg", &imageCLSID);
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;
GdipSaveImageToFile(pBitmap, lpszFilename, &imageCLSID, &encoderParams);
}
The one thing that wasn't evident was the cleanup of the GpBitmap created by GdipCreateBitmapFromHBITMAP(). The Gdiplus::Bitmap class doesn't seem to have a destructor, and so doesn't do anything with it's internal GpBitmap. Also, there is no GdipDeleteBitmap(), like there are for other GDI+ objects. So, it is unclear to me what needs to be done to avoid leaks.
Edit: This code does not address the fact that the Microsoft supplied GDI+ header files declare all the necessary functions in C++ namespaces. One solution is to copy the necessary declarations (and convert as needed to C code) to your own header. Another possibility is to use the headers supplied by the Wine or Mono projects. They both appear to be much better behaved for compilation as C code.
If you're really concerned about space, you can probably jettison the C runtime libraries as well. If you're only using a few functions, just write your own version (e.g. strcpy). It is possible to write Windows applications that are only a few K bytes. I can send you a small sample app which does this.
If I take my C imaging code and strip it down to just the JPEG encoder, it will probably produce about 20K of code (less if you don't need to support grayscale images).
libjpeg is free, open source, coded in C. You can copy their code into yours.
http://sourceforge.net/project/showfiles.php?group_id=159521