/BotE Game/branch/Alpha7/Source/include/ImageStone/include/imagefile/imagehandle_gdiplus.h
C++ Header | 360 lines | 286 code | 29 blank | 45 comment | 71 complexity | 08b78ed457a09d8424ba09665aa65917 MD5 | raw file
Possible License(s): GPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.0
- /*
- * Copyright (C) =USTC= Fu Li
- *
- * Author : Fu Li
- * Create : 2004-6-18
- * Home : http://www.crazy-bit.com/
- * Mail : crazybitwps@hotmail.com
- * History :
- */
- #ifndef __FOO_IMAGE_HANDLE_GDIPLUS__2004_06_18__H__
- #define __FOO_IMAGE_HANDLE_GDIPLUS__2004_06_18__H__
- #include "../FWin32.h"
-
- //class FCImageHandle ;
- class FCImageHandle_Gdiplus ;
-
- //=============================================================================
- /**
- * Auto load GDI+ module.
- * load GDI+ module at constructor and unload at destructor.
- */
- class FCAutoInitGDIPlus
- {
- ULONG_PTR m_GdiplusToken ;
- public:
- /// Constructor (load GDI+ module).
- FCAutoInitGDIPlus()
- {
- Gdiplus::GdiplusStartupInput gpSI ;
- Gdiplus::GdiplusStartup (&m_GdiplusToken, &gpSI, NULL) ;
- }
- /// Destructor (unload GDI+ module).
- virtual ~FCAutoInitGDIPlus()
- {
- Gdiplus::GdiplusShutdown (m_GdiplusToken) ;
- }
-
- /// Get bmp/jpeg/gif/tiff/png image's CLSID.
- static bool GetImageEncoderClsid (IMAGE_TYPE imgType, CLSID* pClsid)
- {
- bstr_t strType ;
- switch (imgType)
- {
- case IMG_BMP : strType = "image/bmp" ; break;
- case IMG_JPG : strType = "image/jpeg" ; break;
- case IMG_GIF : strType = "image/gif" ; break;
- case IMG_TIF : strType = "image/tiff" ; break;
- case IMG_PNG : strType = "image/png" ; break;
- default : return false ;
- }
-
- UINT nNum=0, nSize=0 ;
- Gdiplus::GetImageEncodersSize (&nNum, &nSize) ;
- if (nSize <= 0)
- return false ;
-
- PCL_array<Gdiplus::ImageCodecInfo> pICI (new BYTE[nSize]) ;
- Gdiplus::GetImageEncoders (nNum, nSize, pICI.get()) ;
-
- for (UINT i=0 ; i < nNum; i++)
- {
- if (bstr_t(pICI[i].MimeType) == strType)
- {
- *pClsid = pICI[i].Clsid ;
- return true ;
- }
- }
- return false ;
- }
- };
-
- //=============================================================================
- /**
- * Read/Write image via Gdi+.
- * if you load a gif image with transparent color, you will get a 32bpp image object, transparent color be converted to alpha=0 pixel
- */
- class FCImageHandle_Gdiplus : public FCImageHandleBase,
- public FCAutoInitGDIPlus
- {
- // create image property object base on Bitmap, must delete returned object
- static FCImageProperty* CreatePropertyFromBitmap (Gdiplus::Bitmap& gp_Bmp)
- {
- // get all property
- UINT nBytes, nNum ;
- gp_Bmp.GetPropertySize (&nBytes, &nNum) ;
- PCL_array<Gdiplus::PropertyItem> gp_Item (new BYTE[nBytes]) ;
- gp_Bmp.GetAllPropertyItems (nBytes, nNum, gp_Item.get()) ;
-
- // fill tag
- FCImageProperty * pProp = new FCImageProperty ;
- for (UINT i=0 ; i < nNum ; i++)
- {
- Gdiplus::PropertyItem & rItem = gp_Item[i] ;
- FIMAGE_TAG nTag = (FIMAGE_TAG)rItem.id ;
-
- // convert all type to string
- if (rItem.type == PropertyTagTypeASCII)
- {
- std::string s ((char*)rItem.value, rItem.length) ;
- pProp->SetPropertyValue (nTag, s.c_str()) ;
- }
- else if (rItem.type == PropertyTagTypeRational)
- {
- if (rItem.length == 8)
- {
- std::string s = FCOXOHelper::X2A (*(unsigned long*)rItem.value) ;
- s += "/" ;
- s += FCOXOHelper::X2A (((unsigned long*)rItem.value)[1]) ;
- pProp->SetPropertyValue (nTag, s.c_str()) ;
- }
- }
- else if (rItem.type == PropertyTagTypeSRational)
- {
- if (rItem.length == 8)
- {
- std::string s = FCOXOHelper::X2A (*(long*)rItem.value) ;
- s += "/" ;
- s += FCOXOHelper::X2A (((long*)rItem.value)[1]) ;
- pProp->SetPropertyValue (nTag, s.c_str()) ;
- }
- }
- else if (rItem.type == PropertyTagTypeShort)
- {
- if (rItem.length == 2)
- {
- std::string s = FCOXOHelper::X2A (*(unsigned short*)rItem.value) ;
- pProp->SetPropertyValue (nTag, s.c_str()) ;
- }
- }
- else if (rItem.type == PropertyTagTypeLong)
- {
- if (rItem.id == PropertyTagFrameDelay)
- {
- assert (rItem.length % 4 == 0) ;
- for (ULONG i=0 ; i < rItem.length/4 ; i++)
- {
- unsigned long lv = ((unsigned long*)rItem.value)[i] ;
- pProp->PutFrameDelay ((int)lv * 10) ;
- }
- }
- else
- {
- if (rItem.length == 4)
- {
- std::string s = FCOXOHelper::X2A (*(unsigned long*)rItem.value) ;
- pProp->SetPropertyValue (nTag, s.c_str()) ;
- }
- }
- }
- }
- return pProp ;
- }
-
- // property tag <==> type
- static void GetGdiplusPropertyTypeTab (PCL_TT_Convertor<PROPID, WORD>& aTab)
- {
- aTab.Clear() ;
- aTab.AddElement (PropertyTagEquipMake, PropertyTagTypeASCII) ;
- aTab.AddElement (PropertyTagEquipModel, PropertyTagTypeASCII) ;
- aTab.AddElement (PropertyTagExifDTOrig, PropertyTagTypeASCII) ;
- aTab.AddElement (PropertyTagExifExposureTime, PropertyTagTypeRational) ;
- aTab.AddElement (PropertyTagExifFNumber, PropertyTagTypeRational) ;
- aTab.AddElement (PropertyTagExifFocalLength, PropertyTagTypeRational) ;
- aTab.AddElement (PropertyTagExifISOSpeed, PropertyTagTypeShort) ;
- aTab.AddElement (PropertyTagExifExposureBias, PropertyTagTypeSRational) ;
- aTab.AddElement (PropertyTagExifMaxAperture, PropertyTagTypeRational) ;
- aTab.AddElement (PropertyTagExifFlash, PropertyTagTypeShort) ;
- aTab.AddElement (PropertyTagExifMeteringMode, PropertyTagTypeShort) ;
- aTab.AddElement (PropertyTagExifExposureProg, PropertyTagTypeShort) ;
- }
-
- // Add property into bitmap object.
- static void AddPropertyInBitmap (const FCImageProperty& rImageProp, Gdiplus::Bitmap& gpBmp)
- {
- PCL_TT_Convertor<PROPID, WORD> tabType ;
- GetGdiplusPropertyTypeTab (tabType) ;
-
- // put image's property
- for (int i=0 ; i < rImageProp.GetElementCount() ; i++)
- {
- Gdiplus::PropertyItem aItem ;
- aItem.id = rImageProp.GetT1(i) ;
- aItem.type = tabType.First_to_Second (aItem.id, PropertyTagTypeUndefined) ;
- if (aItem.type == PropertyTagTypeUndefined)
- continue ;
-
- const std::string & s = rImageProp.GetT2(i) ;
- if (aItem.type == PropertyTagTypeASCII)
- {
- PCL_array<char> pBuf (s.length() + 1) ;
- ZeroMemory (pBuf.get(), s.length() + 1) ;
- CopyMemory (pBuf.get(), s.c_str(), s.length()) ;
- aItem.length = s.length() + 1 ;
- aItem.value = pBuf.get() ;
- gpBmp.SetPropertyItem (&aItem) ;
- }
- else if (aItem.type == PropertyTagTypeRational)
- {
- size_t nPos = s.find ("/") ;
- if (nPos != std::string::npos)
- {
- unsigned long p[2] ;
- FCOXOHelper::A2X (s.substr(0,nPos), p[0]) ;
- FCOXOHelper::A2X (s.substr(nPos+1), p[1]) ;
- aItem.length = 8 ;
- aItem.value = p ;
- gpBmp.SetPropertyItem (&aItem) ;
- }
- }
- else if (aItem.type == PropertyTagTypeSRational)
- {
- size_t nPos = s.find ("/") ;
- if (nPos != std::string::npos)
- {
- long p[2] ;
- FCOXOHelper::A2X (s.substr(0,nPos), p[0]) ;
- FCOXOHelper::A2X (s.substr(nPos+1), p[1]) ;
- aItem.length = 8 ;
- aItem.value = p ;
- gpBmp.SetPropertyItem (&aItem) ;
- }
- }
- else if (aItem.type == PropertyTagTypeShort)
- {
- unsigned short n ;
- FCOXOHelper::A2X (s, n) ;
- aItem.length = 2 ;
- aItem.value = &n ;
- gpBmp.SetPropertyItem (&aItem) ;
- }
- else if (aItem.type == PropertyTagTypeLong)
- {
- unsigned long n ;
- FCOXOHelper::A2X (s, n) ;
- aItem.length = 4 ;
- aItem.value = &n ;
- gpBmp.SetPropertyItem (&aItem) ;
- }
- }
- }
-
- // Load image file via GDIPlus.
- virtual bool LoadImageFile (const char* szFileName,
- PCL_Interface_Composite<FCObjImage>& rImageList,
- std::auto_ptr<FCImageProperty>& rImageProp)
- {
- // load image file
- Gdiplus::Bitmap gpBmp (bstr_t(szFileName), FALSE) ;
- return StoreMultiFrame (gpBmp, rImageList, rImageProp) ;
- }
-
- // Load image memory via GDIPlus.
- virtual bool LoadImageMemory (const BYTE* pStart, int nMemSize,
- PCL_Interface_Composite<FCObjImage>& rImageList,
- std::auto_ptr<FCImageProperty>& rImageProp)
- {
- if (!pStart || (nMemSize <= 0))
- return false ;
-
- // copy to HGLOBAL then load
- HGLOBAL hBuffer = ::GlobalAlloc (GMEM_MOVEABLE, nMemSize) ;
- ::CopyMemory (::GlobalLock(hBuffer), pStart, nMemSize) ;
- ::GlobalUnlock (hBuffer) ;
-
- bool bRet = false ;
- IStream * pStream = NULL ;
- if (::CreateStreamOnHGlobal (hBuffer, TRUE, &pStream) == S_OK)
- {
- Gdiplus::Bitmap gpBmp (pStream, FALSE) ;
- bRet = StoreMultiFrame (gpBmp, rImageList, rImageProp) ;
- }
- if (pStream)
- pStream->Release() ;
- return bRet ;
- }
-
- // Get all frames in gp_Bmp, add into rImageList.
- static bool StoreMultiFrame (Gdiplus::Bitmap& gp_Bmp,
- PCL_Interface_Composite<FCObjImage>& rImageList,
- std::auto_ptr<FCImageProperty>& rImageProp)
- {
- if (gp_Bmp.GetLastStatus() != Gdiplus::Ok)
- {
- /*assert(false);*/ return false;
- }
-
- // get frame dimensions
- const UINT nDim = gp_Bmp.GetFrameDimensionsCount() ;
- PCL_array<GUID> listID (nDim) ;
- gp_Bmp.GetFrameDimensionsList (listID.get(), nDim) ;
-
- // get frame and store
- for (UINT i=0 ; i < nDim ; i++)
- {
- UINT nFrame = gp_Bmp.GetFrameCount (&listID[i]) ;
- for (UINT j=0 ; j < nFrame ; j++)
- {
- gp_Bmp.SelectActiveFrame (&listID[i], j) ;
-
- FCObjImage * pImg = new FCObjImage ;
- FCWin32::GDIPlus_LoadBitmap (gp_Bmp, *pImg) ;
- if (pImg->IsValidImage())
- {
- rImageList.PCL_PushObject(pImg) ;
- }
- else
- {
- delete pImg ; assert(false);
- }
- }
- }
-
- // store image property
- rImageProp = std::auto_ptr<FCImageProperty>(CreatePropertyFromBitmap(gp_Bmp)) ;
- return (rImageList.PCL_GetObjectCount() != 0) ;
- }
-
- // Save image to file via GDI+.
- virtual bool SaveImageFile (const char* szFileName,
- const std::deque<const FCObjImage*>& rImageList,
- const FCImageProperty& rImageProp)
- {
- if (rImageList.empty() || !rImageList[0]->IsValidImage())
- return false ;
- const FCObjImage &img = *rImageList[0] ;
-
- // get encoder's CLSID
- CLSID clsID ;
- IMAGE_TYPE imgType = FCObjImage::GetImageHandleFactory()->QueryImageFileType(szFileName) ;
- if (!GetImageEncoderClsid (imgType, &clsID))
- return false ;
-
- // if image is jpeg format, set save quality
- std::auto_ptr<Gdiplus::EncoderParameters> pEnParas ;
- ULONG nQuality = JpegSaveQuality(rImageProp) ;
- if (imgType == IMG_JPG)
- {
- pEnParas = std::auto_ptr<Gdiplus::EncoderParameters>(new Gdiplus::EncoderParameters) ;
- pEnParas->Count = 1 ;
- pEnParas->Parameter[0].Guid = Gdiplus::EncoderQuality ;
- pEnParas->Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong ;
- pEnParas->Parameter[0].NumberOfValues = 1 ;
- pEnParas->Parameter[0].Value = &nQuality ;
- }
-
- // create a GDI+ bitmap and put property
- std::auto_ptr<Gdiplus::Bitmap> pBmp (FCWin32::GDIPlus_CreateBitmap(img)) ;
- if (!pBmp.get())
- return false ;
-
- AddPropertyInBitmap (rImageProp, *pBmp) ;
- return (pBmp->Save (bstr_t(szFileName), &clsID, pEnParas.get()) == Gdiplus::Ok) ;
- }
- };
-
- //=============================================================================
- // inline Implement
- //=============================================================================
-
- #endif