我用GDI+缩小一个JPG图片,从网上down下来的这个图片原本是208×275,大小为10K,我使用GDI+将尺寸缩小至151×200后,图片的大小反而变成了22K,我的代码如下:void compressImpl(const std::string& path, int size, UInt8 quality)
{
  HBITMAP hbmReturn = NULL;
  Bitmap* bmPhoto = NULL;  std::wstring upath;
  UnicodeConverter::toUTF16(path, upath);  {
    Bitmap image(upath.c_str());    int srcWidth = image.GetWidth();
    int srcHeight = image.GetHeight();    float percent = 0;
    int destX = 0, destY = 0;
    if (srcWidth > srcHeight)
    {
      percent = ((float)size/(float)srcWidth);
      destX  = (int)((size - (srcWidth * percent))/2);
    }
    else
    {
      percent = ((float)size/(float)srcHeight);
      destY  = (int)((size - (srcHeight * percent))/2);
    }
    
    if (percent >= 1.0f)
      return; // skip compress    int destWidth = (int)(srcWidth * percent);
    int destHeight = (int)(srcHeight * percent);    bmPhoto = new Bitmap(destWidth, destHeight, PixelFormat24bppRGB);
    bmPhoto->SetResolution(image.GetHorizontalResolution(), image.GetVerticalResolution());    Graphics *grPhoto = Graphics::FromImage(bmPhoto);
    Color colorW(255, 255, 255, 255);
    grPhoto->Clear(colorW);
    grPhoto->SetInterpolationMode(InterpolationModeHighQualityBicubic);
    grPhoto->DrawImage(&image, Rect(destX, destY, destWidth, destHeight));    bmPhoto->GetHBITMAP(colorW, &hbmReturn);
    delete grPhoto;
  }  // find appropriate encoder, jpeg
  CLSID encoderClsid;
  getEncoderClsid(L"image/jpeg", &encoderClsid);  // set output quality for jpeg alone
  EncoderParameters encoderParameters;
  setEncoderQuality(&encoderParameters, quality);  // output to image file with desired quality
  bmPhoto->Save(upath.c_str(), &encoderClsid, &encoderParameters);  // release resources
  delete bmPhoto;
  DeleteObject(hbmReturn);
}int getEncoderClsid(const WCHAR* format, void* clsid)
{
  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);
  for (UINT j = 0; j < num; ++j)
  {
    if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
    {
      *(CLSID*)clsid = pImageCodecInfo[j].Clsid;
      free(pImageCodecInfo);
      return j;  //Success
    }
  }  free(pImageCodecInfo);
  return -1; // Failure
}void setEncoderQuality(void* params, UInt8 quality)
{
  EncoderParameters* encoderParams = (EncoderParameters*)params;
  encoderParams->Count = 1;
  encoderParams->Parameter[0].Guid = EncoderQuality;
  encoderParams->Parameter[0].Type = EncoderParameterValueTypeLong;
  encoderParams->Parameter[0].NumberOfValues = 1;  encoderParams->Parameter[0].Value = &quality;
}

解决方案 »

  1.   

    保存jpg可以选择压缩等级的:
    #include <stdio.h>
    #include <tchar.h>
    #include <windows.h>
    int A2U(const char* szA,wchar_t* szU,size_t cnt)
    {
    return MultiByteToWideChar (CP_ACP, 0, szA, -1, szU, cnt) ;
    }
    bool SaveImageToFile(Bitmap* pimage, LPCTSTR szFileName, ULONG quality)
    //quality表示压缩等级,取值范围0-100,越小,压缩等级越大,图像质量越差
    {
    if(NULL==pimage || NULL==szFileName)
    return false;
    CLSID   encoderClsid;
    EncoderParameters encoderParameters,*pencoderParameters=NULL;
    TCHAR*  pstr;
    TCHAR   szFtr[16];
    TCHAR   strcode[32]=TEXT("image/");
    pstr=_tcsrchr(szFileName,TEXT('.'));
    if(NULL==pstr)
    return false;
    _tcscpy(szFtr,pstr+1);
    _tcslwr(szFtr);
    if(_tcscmp(TEXT("jpeg"),szFtr)==0 || _tcscmp(TEXT("jpg"),szFtr)==0)
    {
    _tcscat(strcode,TEXT("jpeg"));
    pencoderParameters=&encoderParameters;
    }
    else
    _tcscat(strcode,szFtr);
    if(-1==GetEncoderClsid(strcode, &encoderClsid))
    return false;
    if(quality>100)
    quality=100;
    encoderParameters.Count = 1;
    encoderParameters.Parameter[0].Guid = EncoderQuality;
    encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
    encoderParameters.Parameter[0].NumberOfValues = 1;
    encoderParameters.Parameter[0].Value = &quality;
    #ifndef UNICODE
    wchar_t wszFileName[MAX_PATH];
    A2U(szFileName,wszFileName,MAX_PATH);
    return Ok==pimage->Save(wszFileName, &encoderClsid, pencoderParameters)?true:false;
    #else
    return Ok==pimage->Save(szFileName, &encoderClsid, pencoderParameters)?true:false;
    #endif
    }
      

  2.   

    上面少了一个函数:
    int GetEncoderClsid(LPCTSTR szFormat, CLSID* pClsid)  // help
    {
    UINT  j;
    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);
    #ifndef UNICODE
    wchar_t  wszFormat[32];
    A2U(szFormat,wszFormat,32);
    for(j = 0; j < num; ++j)
    {
    if( wcscmp(pImageCodecInfo[j].MimeType, wszFormat) == 0 )
    #else
    for(j = 0; j < num; ++j)
    {
    if( wcscmp(pImageCodecInfo[j].MimeType, szFormat) == 0 )
    #endif
    {
    *pClsid = pImageCodecInfo[j].Clsid;
    free(pImageCodecInfo);
    return j;  // Success
    }
    }
    free(pImageCodecInfo);
    return -1;  // Failure
    }