加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

如何截取屏幕截图并将其保存为Windows上的JPEG?

发布时间:2021-05-22 19:33:39 所属栏目:Windows 来源:网络整理
导读:我试图找到一个(有点)简单的方法来在窗口上截图,并将得到的HBITMAP保存为JPEG.这里的棘手部分是,由于代码是C,我不能使用GDI,因为代码是一个更大的程序的模块,我不能使用外部lib(如libjpeg). 此代码需要截图并返回HBITMAP.将该位图保存到文件中很容易.问题是

我试图找到一个(有点)简单的方法来在窗口上截图,并将得到的HBITMAP保存为JPEG.这里的棘手部分是,由于代码是C,我不能使用GDI,因为代码是一个更大的程序的模块,我不能使用外部lib(如libjpeg).

此代码需要截图并返回HBITMAP.将该位图保存到文件中很容易.问题是位图是2或3mb.

HDC hDCMem = CreateCompatibleDC(NULL);
HBITMAP hBmp;
RECT rect;
HDC hDC;
HGDIOBJ hOld;    

GetWindowRect(hWnd,& rect);

hBmp = NULL;

{
    hDC = GetDC(hWnd);
    hBmp = CreateCompatibleBitmap(hDC,rect.right - rect.left,rect.bottom - rect.top);
    ReleaseDC(hWnd,hDC);
}

hOld = SelectObject(hDCMem,hBmp);
SendMessage(hWnd,WM_PRINT,(WPARAM) hDCMem,PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);

SelectObject(hDCMem,hOld);
DeleteObject(hDCMem);

return hBmp;

任何想法如何做到这一点?
非常感谢,任何帮助都不胜感激

编辑:
由于我们进入GDI的方向,我以为我会发布代码iv C,可以使用截图,并将其转换为使用GDI的JPEG.如果有人知道如何使用FLAT GDI来实现这一点,我将不胜感激.
码:

#include <windows.h>
#include <stdio.h>
#include <gdiplus.h>

using namespace Gdiplus;


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;
}

int GetScreeny(LPWSTR lpszFilename,ULONG uQuality) // by Napalm
{
    ULONG_PTR gdiplusToken;
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
    HWND hMyWnd = GetForegroundWindow(); // 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,};

    // 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: %dn",GetLastError());
        return 0;
    }

    // copy the screenshot buffer
    nCapture = SaveDC(hdcCapture);
    SelectObject(hdcCapture,hbmCapture);
    BitBlt(hdcCapture,h,dc,SRCCOPY);
    RestoreDC(hdcCapture,nCapture);
    DeleteDC(hdcCapture);
    DeleteDC(dc);

    // 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);
    iRes = (pScreenShot->Save(lpszFilename,&imageCLSID,&encoderParams) == Ok);
    delete pScreenShot;
    DeleteObject(hbmCapture);
    GdiplusShutdown(gdiplusToken);
    return iRes;

}
好的,经过这么多的努力,这里的答案是:
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,&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,&encoderParams);


    return 1;
}

>什么是hModuleThread?看看在here.你可以用GetModuleHandle()
>什么是GetEncoderClsid?看here.

现在的问题是,如何将编码的pBitmap(作为jpeg)保存到BYTE缓冲区?

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读