基于Gdi+的图像读存图像处理

来源:互联网 发布:mac os 知乎 编辑:程序博客网 时间:2024/05/21 17:55

 其实gdiplus已经处理了很多东西和设置了,只可以由Cimage封装之后,很多东西不开放接口出来,结果处理起来很不方便,比如不能设置jpeg quality,会丢失exif信息等等。

 没时间深究,随意整理了一个类,基本还算满足简单要求,对gdiplus的很多东西还很不清楚,只是一样画葫芦,总算保住一些信息。

 还有很多东西可以追加和修改。看个人喜好,我本身很不喜欢读存文件操作,比较乐意关注算法的计算设计。将就能用就好,哈。

 本来呢,我是想找个现成能用的,结果搜不到,闷。只好又为难自己。

 私布以下代码好了。(在VC2005测试通过,实在懒得排版,要源文件的,可以留言索要,也可以花点时间自己整理一下,如果你有了好的修改版本,希望白送个给我,kghcy@163.com,谢谢)
 /************************************************************
 *
 *  kghcy@163.com | kghcy.blog.163.com
 *     use as following:
 *   HImageFile cif;
 *   cif.Load(...);
 *   //here can get image information:
 *   //width, height, bpp, pBits etc. then to eidt
 *   cif.SetBits(...);
 *   cif.Save(...);
 *  no re-allocate cif, the result almostly reserve the source
 *  information, such as: exif.
 *  also can use cif.SetJpegQuality() save high quality jpeg
 *
 *************************************************************/

 //HImageFile.h
#pragma once

#include <gdiplus.h>
#include <shlwapi.h>

#ifndef _ATL_NO_DEFAULT_LIBS
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "gdiplus.lib")
#endif

class HImageFile
{
public:
 HImageFile(void);
 ~HImageFile(void);

public:
 bool Load(const CString FileName);
 bool Save(const CString FileName);

 UINT GetBPP();
 UINT GetWidth();
 UINT GetHeight();
 UINT GetPicth();
 void* GetBits();

 void SetWidth(UINT Width);
 void SetHeight(UINT Height);
 void    SetPixelFormat(Gdiplus::PixelFormat PixelFormat);
 void SetBits(void *pBits);

 void SetJpegQuality(BYTE Quality);

private:
 bool InitGdiplus();
 void ReleaseGDIPlus();
 void IncreaseCImageCount();
 void DecreaseCImageCount();
private:
 void *mpBits;
 bool    mIsDelBuf;
 UINT mnBpp;
 UINT mnWidth;
 UINT mnPitch;
 UINT mnHeight;
 BYTE mnQuality;
 Gdiplus::PixelFormat mPixelFormat;

 UINT mnOldWidth;
 UINT mnOldHeight;
 Gdiplus::PixelFormat mOldPixelFormat;
 ///////use gdiplus//////////
 Gdiplus::Bitmap  *mpImg;
 ULONG_PTR   mdwToken;
 CRITICAL_SECTION mSect;
 LONG    mnCImageObjects;
};

//HImageFile.cpp

#include "StdAfx.h"
#include "HImageFile.h"

HImageFile::HImageFile(void)
{
 mnWidth   = 0;
 mnPitch   = 0;
 mnHeight  = 0;
 mnBpp   = 0;

 mpImg   = NULL;
 mpBits   = NULL;
 mnQuality = 90;
 mIsDelBuf = false;

 mdwToken  = 0;
 mnCImageObjects = 0;
 InitializeCriticalSection(&mSect);
 IncreaseCImageCount();
}
HImageFile::~HImageFile(void)
{
 if(mpImg)    { delete mpImg;  mpImg = NULL; }
 if(mIsDelBuf && mpBits) { delete[] mpBits; mpBits = NULL; }

 DecreaseCImageCount();
 DeleteCriticalSection(&mSect);
}
UINT HImageFile::GetBPP()
{
 return mnBpp;
}
UINT HImageFile::GetWidth()
{
 return mnWidth;
}
UINT HImageFile::GetPicth()
{
 return mnPitch;
}
UINT HImageFile::GetHeight()
{
 return mnHeight;
}
void* HImageFile::GetBits()
{
 return mpBits;
}
void HImageFile::SetWidth(UINT Width)
{
 mnWidth = Width;
}
void HImageFile::SetHeight(UINT Height)
{
 mnHeight = Height;
}
void HImageFile::SetPixelFormat(Gdiplus::PixelFormat PixelFormat)
{
 mPixelFormat = PixelFormat;
}
void HImageFile::SetBits(void *pBits)
{
 if(mIsDelBuf && mpBits) { delete[] mpBits; mpBits = NULL; }
 mIsDelBuf = false;
 mpBits = pBits;
}
void HImageFile::SetJpegQuality(BYTE Quality)
{
 mnQuality = Quality;
}
bool HImageFile::Load(const CString FileName)
{
 if(!InitGdiplus())
  return false;

 if(mpImg) { delete mpImg; mpImg = NULL; }
 mpImg = new Gdiplus::Bitmap(FileName);
 if(!mpImg || mpImg->GetLastStatus() != Gdiplus::Ok)
  return false;

 /////////read image info////////////
 mnWidth   = mnOldWidth  = mpImg->GetWidth();
 mnHeight  = mnOldHeight  = mpImg->GetHeight();
 mPixelFormat = mOldPixelFormat = mpImg->GetPixelFormat();
 mnBpp = 0;

 if(mPixelFormat & PixelFormatGDI)
  mnBpp = Gdiplus::GetPixelFormatSize(mPixelFormat);

 mnPitch = AtlAlignUp(mnWidth*mnBpp, 8)/8;

 /////////read image data////////////
 if(mIsDelBuf && mpBits)
  delete[] mpBits;
 mpBits = NULL;

 mpBits = new BYTE [mnPitch*mnHeight];
 if(!mpBits)
  return false;
 mIsDelBuf = true;

 Gdiplus::BitmapData ImgData;
 Gdiplus::Rect Roi(0, 0, mnWidth, mnHeight);
 if(mpImg->LockBits(&Roi, Gdiplus::ImageLockModeRead, mPixelFormat, &ImgData) != Gdiplus::Ok)
  return false;

 BYTE *ptrD = (BYTE *)mpBits;
 BYTE *ptrS = (BYTE *)ImgData.Scan0;
 for(UINT j=0; j<mnHeight; j++)
 {
  memcpy(ptrD, ptrS, mnPitch);
  ptrS += ImgData.Stride;
  ptrD += mnPitch;
 }
 mpImg->UnlockBits(&ImgData);

 return true;
}
bool HImageFile::Save(const CString FileName)
{
 //////find image type///////
 UINT nEncoders;
 UINT nBytes;
 Gdiplus::Status status;
 status = Gdiplus::GetImageEncodersSize(&nEncoders, &nBytes);
 if(status != Gdiplus::Ok)
  return false;

 USES_ATL_SAFE_ALLOCA;
 Gdiplus::ImageCodecInfo* pEncoders = static_cast<Gdiplus::ImageCodecInfo*>(_ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD));
 if(!pEncoders)
  return false;
 if(GetImageEncoders(nEncoders, nBytes, pEncoders) != Gdiplus::Ok)
  return false;

 CLSID clsidEncoder = CLSID_NULL;
 CStringW strFileExt = ::PathFindExtensionW(FileName);
 for(UINT icode = 0; clsidEncoder == CLSID_NULL && icode < nEncoders; icode++)
 {
  CStringW strExtList(pEncoders[icode].FilenameExtension);
  int np = 0;
  do{
   CStringW strExt = ::PathFindExtensionW(strExtList.Tokenize(L";", np));
   if(np != -1)
   {
    if(strExt.CompareNoCase(strFileExt) == 0)
    {
     clsidEncoder = pEncoders[icode].Clsid;
     break;
    }
   }
  }while(np != -1);
 }
 if(clsidEncoder == CLSID_NULL)
  return false;

 long nQuality = (long)mnQuality;
 Gdiplus::EncoderParameters EncParams;
 Gdiplus::EncoderParameter  ep;
 ep.Guid    = Gdiplus::EncoderQuality;
 ep.NumberOfValues = 1;
 ep.Type    = Gdiplus::EncoderParameterValueType::EncoderParameterValueTypeLong;
 ep.Value   = &nQuality;

 EncParams.Count   = 1;
 EncParams.Parameter[0] = ep;

 if(mnOldWidth != mnWidth || mnOldHeight != mnHeight || mOldPixelFormat != mPixelFormat)
 {
  if(!InitGdiplus())
   return false;

  mnPitch = AtlAlignUp(mnWidth*mnBpp, 8)/8;
  if(mpImg) { delete mpImg; mpImg = NULL; }
  mpImg = new Gdiplus::Bitmap(mnWidth, mnHeight, mnPitch, mPixelFormat, (BYTE*)mpBits);
  if(!mpImg)
   return false;
 }
 else//updata image data
 {
  Gdiplus::BitmapData ImgData;
  Gdiplus::Rect Roi(0, 0, mnWidth, mnHeight);
  if(mpImg->LockBits(&Roi, Gdiplus::ImageLockModeWrite, mPixelFormat, &ImgData) != Gdiplus::Ok)
   return false;

  BYTE *ptrS = (BYTE *)mpBits;
  BYTE *ptrD = (BYTE *)ImgData.Scan0;
  for(UINT j=0; j<mnHeight; j++)
  {
   memcpy(ptrD, ptrS, mnPitch);
   ptrS += mnPitch;
   ptrD += ImgData.Stride;
  }
  if(mpImg->UnlockBits(&ImgData) != Gdiplus::Ok)
   return false;
 }

 return (mpImg->Save(FileName, &clsidEncoder, &EncParams) == Gdiplus::Ok);
}
////////////////////////////////
bool HImageFile::InitGdiplus()
{
 EnterCriticalSection(&mSect);
 bool bRet = true;
 if(mdwToken == 0)
 {
  Gdiplus::GdiplusStartupInput Input;
  Gdiplus::GdiplusStartupOutput Output;
  bRet = Gdiplus::GdiplusStartup(&mdwToken, &Input, &Output) == Gdiplus::Ok;
 }
 LeaveCriticalSection(&mSect);
 return bRet;
}
void HImageFile::ReleaseGDIPlus()
{
 EnterCriticalSection(&mSect);
 if(mdwToken)
  Gdiplus::GdiplusShutdown(mdwToken);
 mdwToken = 0;
 LeaveCriticalSection(&mSect);
}
void HImageFile::IncreaseCImageCount()
{
 EnterCriticalSection(&mSect);
 mnCImageObjects++;
 LeaveCriticalSection(&mSect);
}

void HImageFile::DecreaseCImageCount()
{
 EnterCriticalSection(&mSect);
 if(--mnCImageObjects == 0)
  ReleaseGDIPlus();
 LeaveCriticalSection(&mSect);
}

原创粉丝点击