VC中屏幕保存为JPG文件的方法和VFW的使用


VC6 图像和视频处理之一:保存JPG文件

前一阵接了个项目,使用电脑上的摄像头拍照,所以花了一些时间研究了Windows 的VFW函数,发现这个挺好玩的,网上资

料也很多。简单介绍一下:


(1)使用 capCreateCaptureWindow 来创建一个图像窗口

(2)使用capCaptureGetSetup获取设置,在获取到的设置的基础上,对参数进行修改,包括:

    是否同时捕获音频
    帧数
    是否有时间限制

    等等
    再使用capCaptureSetSetup设置

(3)使用capPreviewScale、capPreview开始预览

(4)可以使用capFileSaveDIB保存为BMP

(5)可以使用capCaptureSequence开始视频采集,capCaptureAbort、capFileSaveAs结束预览并保存为AVI


(6)可以设置帧回调函数和视频流、音频流的回调函数(基于这些函数,可以做成网络视频和音频点对点的程序)



存在问题的地方:

1、这样的API只能保存为BMP,太大了


    有两个解决办法,一是使用VFW的函数,设置位图的像素、品质,二是不使用VFW,直接从系统获取JPEG的编码器来

压缩,方法如下:



先获取JPEG的CLSID

int GetEncoderClsid(const   WCHAR*   format,   CLSID*   pClsid)
{
      UINT     num   =   0;                     //   number   of   image   encoders
      UINT     size   =   0;                   //   size   of   the   image   encoder   array   in   bytes

      ImageCodecInfo*   pImageCodecInfo   =   NULL;

      GetImageEncodersSize(&num,&size);
      if(size   ==   0)
            return   -1;     //   Failure

      pImageCodecInfo   =   (ImageCodecInfo*)(malloc(size));
      if(pImageCodecInfo   ==   NULL)
            return   -1;     //   Failure

      GetImageEncoders(num,   size,   pImageCodecInfo);

      CString s1="";
      CString s2="";
      for(UINT   kk   =   0;   kk  <   num;   ++kk)
      {
            if(   TRUE  )
            {
                s1+="[";
                s1+=pImageCodecInfo[kk].MimeType;
                s1+="]";

                BSTR bs;
                 StringFromCLSID(pImageCodecInfo[kk].Clsid,&bs);
                 CString str=(LPCTSTR)_bstr_t(bs);

                s2+="[";
                s2+=str;
                s2+="]";
            }        
      }
      AfxMessageBox( s1 );
        AfxMessageBox( s2 );



      for(UINT   j   =   0;   j   <   num;   ++j)
      {
            if(   wcscmp(pImageCodecInfo[j].MimeType,   format)   ==   0   )
            {
                  *pClsid   =   pImageCodecInfo[j].Clsid;
                  free(pImageCodecInfo);
                  return   j;     //   Success
            }        
      }

      free(pImageCodecInfo);
      return   -1;     //   Failure
}


保存jpg

    HWND hWnd = m_VFWImageProc.GetCapWindow();
    HDC hdc = ::GetWindowDC(hWnd);  
    RECT rr;
    ::GetWindowRect( hWnd,&rr);
    int x = rr.right-rr.left;// GetDeviceCaps(hdc, HORZRES);  
    int y = rr.bottom-rr.top;// GetDeviceCaps(hdc, VERTRES);  
    HBITMAP hbmp = ::CreateCompatibleBitmap(hdc, x, y), hold;  
    HDC hmemdc = ::CreateCompatibleDC(hdc);  
    hold = (HBITMAP)::SelectObject(hmemdc,   hbmp);  
    BitBlt(hmemdc, 0, 0, x, y, hdc, 0, 0, SRCCOPY);  
    SelectObject(hmemdc, hold);  
   
    const unsigned short *pszFileName=L"e:\\new.jpg";//保存路径
    int xs=x;//GetSystemMetrics(SM_CXSCREEN);
    int ys=y;//GetSystemMetrics(SM_CYSCREEN);

    Bitmap bit(xs, ys), bit2(hbmp, NULL);  
    Graphics g(&bit);  
    g.ScaleTransform((float)xs/x,   (float)ys/y);  
    g.DrawImage(&bit2,   0,   0);  
   
    CLSID  encoderClsid;  
    ULONG  quality;
    quality = 30;

    EncoderParameters   encoderParameters;  
   
    encoderParameters.Count   =   1;  
    encoderParameters.Parameter[0].Guid   =   EncoderQuality;  
    encoderParameters.Parameter[0].Type   =   EncoderParameterValueTypeLong;  
    encoderParameters.Parameter[0].NumberOfValues   =   1;  
    encoderParameters.Parameter[0].Value   =   &quality;  
   
    GetEncoderClsid(L"image/jpeg",&encoderClsid);  
    bit.Save(pszFileName,   &encoderClsid,   &encoderParameters);  
  
    ::DeleteObject(hbmp);  
    ::DeleteObject(hmemdc);  


这样,保存图片的大小一下子发生了质的变化。BMP的要240k,而同样品质和清晰度的jpg,才不到10k。





你可能感兴趣的:(C/C++)