tags:

views:

267

answers:

1

In one of my previous questions I asked how to take a screenshot and save it as JPEG without the use of GDI+ due to the constrains of having to use only C. At the end I answered the question myself with the help of of some of the comments there. Using a very terse C version of GDI+ (loaded at runtime) i can take a screenshot and save it as a JPEG to a file. Now, how would I save that same screenshot not to a file but to a buffer? an unsigned char* buffer? here's the code that needs to be converted.

int SaveJpeg(HBITMAP hBmp, LPCWSTR lpszFilename, ULONG uQuality)
{
    ULONG *pBitmap = NULL;
    CLSID imageCLSID;
    EncoderParameters encoderParams;
    int iRes = 0;

    typedef Status (WINAPI *pGdipCreateBitmapFromHBITMAP)(HBITMAP, HPALETTE, ULONG**);
    pGdipCreateBitmapFromHBITMAP lGdipCreateBitmapFromHBITMAP;

    typedef Status (WINAPI *pGdipSaveImageToFile)(ULONG *, const WCHAR*, const CLSID*, const EncoderParameters*);
    pGdipSaveImageToFile lGdipSaveImageToFile;

    // load GdipCreateBitmapFromHBITMAP
    lGdipCreateBitmapFromHBITMAP = (pGdipCreateBitmapFromHBITMAP)GetProcAddress(hModuleThread, "GdipCreateBitmapFromHBITMAP");
    if(lGdipCreateBitmapFromHBITMAP == NULL)
    {
     // error
     return 0;
    }

    // load GdipSaveImageToFile
    lGdipSaveImageToFile = (pGdipSaveImageToFile)GetProcAddress(hModuleThread, "GdipSaveImageToFile");
    if(lGdipSaveImageToFile == NULL)
    {
     // error
     return 0;
    }

        lGdipCreateBitmapFromHBITMAP(hBmp, NULL, &pBitmap);

       iRes = GetEncoderClsid(L"image/jpeg", &imageCLSID);
       if(iRes == -1)
    {
     // error
     return 0;
    }
    encoderParams.Count = 1;
    encoderParams.Parameter[0].NumberOfValues = 1;
    encoderParams.Parameter[0].Guid  = EncoderQuality;
    encoderParams.Parameter[0].Type  = EncoderParameterValueTypeLong;
    encoderParams.Parameter[0].Value = &uQuality;

    lGdipSaveImageToFile(pBitmap, lpszFilename, &imageCLSID, &encoderParams);


    return 1;
}

Thanks for the help.

A: 

Instead of calling GdipSaveImageToFile, you should use GdipSaveImageToStream. This will let you save the image into a stream directly, instead of writing it to a file.

See the GDI image functions for details.

In order to create an IStream in memory, you can use CreateStreamOnHGlobal. This has the option of allowing the IStream to allocate its own memory, or to use a pre-allocated buffer.

Reed Copsey
Fantastic! thanks
wonderer