ImageHandle_Gdiplus.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. * Copyright (C) =USTC= Fu Li
  3. *
  4. * Author : Fu Li
  5. * Create : 2004-6-18
  6. * Home : http://www.crazy-bit.com/
  7. * Mail : crazybit@263.net
  8. * History :
  9. */
  10. #ifndef __FOO_IMAGE_HANDLE_GDIPLUS__2004_06_18__H__
  11. #define __FOO_IMAGE_HANDLE_GDIPLUS__2004_06_18__H__
  12. #include "../ObjImage.h"
  13. //class FCImageHandle ;
  14. class FCImageHandle_Gdiplus ;
  15. //=============================================================================
  16. /**
  17. * Auto load GDI+ module.
  18. * load GDI+ module at constructor and unload at destructor.
  19. */
  20. class FCAutoInitGDIPlus
  21. {
  22. ULONG_PTR m_GdiplusToken ;
  23. public:
  24. /// Constructor (load GDI+ module).
  25. FCAutoInitGDIPlus()
  26. {
  27. Gdiplus::GdiplusStartupInput gpSI ;
  28. Gdiplus::GdiplusStartup (&m_GdiplusToken, &gpSI, NULL) ;
  29. }
  30. /// Destructor (unload GDI+ module).
  31. virtual ~FCAutoInitGDIPlus()
  32. {
  33. Gdiplus::GdiplusShutdown (m_GdiplusToken) ;
  34. }
  35. /// Get bmp/jpeg/gif/tiff/png image's CLSID.
  36. static bool GetImageEncoderClsid (IMAGE_TYPE imgType, CLSID* pClsid)
  37. {
  38. bstr_t strType ;
  39. switch (imgType)
  40. {
  41. case IMG_BMP : strType = "image/bmp" ; break;
  42. case IMG_JPG : strType = "image/jpeg" ; break;
  43. case IMG_GIF : strType = "image/gif" ; break;
  44. case IMG_TIF : strType = "image/tiff" ; break;
  45. case IMG_PNG : strType = "image/png" ; break;
  46. default : return false ;
  47. }
  48. UINT nNum=0, nSize=0 ;
  49. Gdiplus::GetImageEncodersSize (&nNum, &nSize) ;
  50. if (nSize <= 0)
  51. return false ;
  52. PCL_array<Gdiplus::ImageCodecInfo> pICI (new BYTE[nSize]) ;
  53. Gdiplus::GetImageEncoders (nNum, nSize, pICI.get()) ;
  54. for (UINT i=0 ; i < nNum; i++)
  55. {
  56. if (bstr_t(pICI[i].MimeType) == strType)
  57. {
  58. *pClsid = pICI[i].Clsid ;
  59. return true ;
  60. }
  61. }
  62. return false ;
  63. }
  64. /// Get table of <GDI+ property tag, type>.
  65. static void GetGdiplusPropertyTypeTab (PCL_TT_Convertor<PROPID, WORD>& aTab)
  66. {
  67. aTab.Clear() ;
  68. aTab.AddElement (PropertyTagFrameDelay, PropertyTagTypeLong) ;
  69. aTab.AddElement (PropertyTagLoopCount, PropertyTagTypeShort) ;
  70. // aTab.AddElement (PropertyTagJPEGQuality, PropertyTagTypeUndefined) ;
  71. aTab.AddElement (PropertyTagEquipMake, PropertyTagTypeASCII) ;
  72. aTab.AddElement (PropertyTagEquipModel, PropertyTagTypeASCII) ;
  73. aTab.AddElement (PropertyTagOrientation, PropertyTagTypeShort) ;
  74. aTab.AddElement (PropertyTagXResolution, PropertyTagTypeRational) ;
  75. aTab.AddElement (PropertyTagYResolution, PropertyTagTypeRational) ;
  76. aTab.AddElement (PropertyTagResolutionUnit, PropertyTagTypeShort) ;
  77. aTab.AddElement (PropertyTagDateTime, PropertyTagTypeASCII) ;
  78. aTab.AddElement (PropertyTagExifExposureTime, PropertyTagTypeRational) ;
  79. aTab.AddElement (PropertyTagExifFNumber, PropertyTagTypeRational) ;
  80. aTab.AddElement (PropertyTagExifExposureProg, PropertyTagTypeShort) ;
  81. // aTab.AddElement (PropertyTagExifSpectralSense, PropertyTagTypeUndefined) ;
  82. aTab.AddElement (PropertyTagExifISOSpeed, PropertyTagTypeShort) ;
  83. // aTab.AddElement (PropertyTagExifOECF, PropertyTagTypeUndefined) ;
  84. // aTab.AddElement (PropertyTagExifVer, PropertyTagTypeUndefined) ;
  85. aTab.AddElement (PropertyTagExifDTOrig, PropertyTagTypeASCII) ;
  86. aTab.AddElement (PropertyTagExifDTDigitized, PropertyTagTypeASCII) ;
  87. // aTab.AddElement (PropertyTagExifCompConfig, PropertyTagTypeUndefined) ;
  88. aTab.AddElement (PropertyTagExifCompBPP, PropertyTagTypeRational) ;
  89. aTab.AddElement (PropertyTagExifShutterSpeed, PropertyTagTypeSRational) ;
  90. aTab.AddElement (PropertyTagExifAperture, PropertyTagTypeRational) ;
  91. // aTab.AddElement (PropertyTagExifBrightness, PropertyTagTypeUndefined) ;
  92. aTab.AddElement (PropertyTagExifExposureBias, PropertyTagTypeSRational) ;
  93. aTab.AddElement (PropertyTagExifMaxAperture, PropertyTagTypeRational) ;
  94. // aTab.AddElement (PropertyTagExifSubjectDist, PropertyTagTypeUndefined) ;
  95. aTab.AddElement (PropertyTagExifMeteringMode, PropertyTagTypeShort) ;
  96. aTab.AddElement (PropertyTagExifLightSource, PropertyTagTypeShort) ;
  97. aTab.AddElement (PropertyTagExifFlash, PropertyTagTypeShort) ;
  98. aTab.AddElement (PropertyTagExifFocalLength, PropertyTagTypeRational) ;
  99. // aTab.AddElement (PropertyTagExifMakerNote, PropertyTagTypeUndefined) ;
  100. aTab.AddElement (PropertyTagExifUserComment, PropertyTagTypeASCII) ;
  101. // aTab.AddElement (PropertyTagExifDTSubsec, PropertyTagTypeUndefined) ;
  102. // aTab.AddElement (PropertyTagExifDTOrigSS, PropertyTagTypeUndefined) ;
  103. // aTab.AddElement (PropertyTagExifDTDigSS, PropertyTagTypeUndefined) ;
  104. // aTab.AddElement (PropertyTagExifFPXVer, PropertyTagTypeUndefined) ;
  105. aTab.AddElement (PropertyTagExifColorSpace, PropertyTagTypeShort) ;
  106. aTab.AddElement (PropertyTagExifPixXDim, PropertyTagTypeShort) ;
  107. aTab.AddElement (PropertyTagExifPixYDim, PropertyTagTypeShort) ;
  108. // aTab.AddElement (PropertyTagExifRelatedWav, PropertyTagTypeUndefined) ;
  109. // aTab.AddElement (PropertyTagExifInterop, PropertyTagTypeUndefined) ;
  110. // aTab.AddElement (PropertyTagExifFlashEnergy, PropertyTagTypeUndefined) ;
  111. // aTab.AddElement (PropertyTagExifSpatialFR, PropertyTagTypeUndefined) ;
  112. aTab.AddElement (PropertyTagExifFocalXRes, PropertyTagTypeRational) ;
  113. aTab.AddElement (PropertyTagExifFocalYRes, PropertyTagTypeRational) ;
  114. aTab.AddElement (PropertyTagExifFocalResUnit, PropertyTagTypeShort) ;
  115. // aTab.AddElement (PropertyTagExifSubjectLoc, PropertyTagTypeUndefined) ;
  116. // aTab.AddElement (PropertyTagExifExposureIndex, PropertyTagTypeUndefined) ;
  117. aTab.AddElement (PropertyTagExifSensingMethod, PropertyTagTypeShort) ;
  118. // aTab.AddElement (PropertyTagExifFileSource, PropertyTagTypeUndefined) ;
  119. // aTab.AddElement (PropertyTagExifSceneType, PropertyTagTypeUndefined) ;
  120. // aTab.AddElement (PropertyTagExifCfaPattern, PropertyTagTypeUndefined) ;
  121. }
  122. /// Get table of <GDI+ property tag, ImageStone property tag>.
  123. static void GetPropertyTagTab (PCL_TT_Convertor<PROPID, UIS_PROPERTY_TAG>& aTab)
  124. {
  125. aTab.Clear() ;
  126. aTab.AddElement (PropertyTagFrameDelay, PROPERTY_TAG_GIF_FRAMEDELAY) ;
  127. aTab.AddElement (PropertyTagLoopCount, PROPERTY_TAG_GIF_LOOPCOUNT) ;
  128. aTab.AddElement (PropertyTagJPEGQuality, PROPERTY_TAG_JPEG_QUALITY) ;
  129. aTab.AddElement (PropertyTagEquipMake, PROPERTY_TAG_EquipMake) ;
  130. aTab.AddElement (PropertyTagEquipModel, PROPERTY_TAG_EquipModel) ;
  131. aTab.AddElement (PropertyTagOrientation, PROPERTY_TAG_Orientation) ;
  132. aTab.AddElement (PropertyTagXResolution, PROPERTY_TAG_XResolution) ;
  133. aTab.AddElement (PropertyTagYResolution, PROPERTY_TAG_YResolution) ;
  134. aTab.AddElement (PropertyTagResolutionUnit, PROPERTY_TAG_ResolutionUnit) ;
  135. aTab.AddElement (PropertyTagDateTime, PROPERTY_TAG_DateTime) ;
  136. aTab.AddElement (PropertyTagExifExposureTime, PROPERTY_TAG_EXIF_ExposureTime) ;
  137. aTab.AddElement (PropertyTagExifFNumber, PROPERTY_TAG_EXIF_FNumber) ;
  138. aTab.AddElement (PropertyTagExifExposureProg, PROPERTY_TAG_EXIF_ExposureProg) ;
  139. aTab.AddElement (PropertyTagExifSpectralSense, PROPERTY_TAG_EXIF_SpectralSense) ;
  140. aTab.AddElement (PropertyTagExifISOSpeed, PROPERTY_TAG_EXIF_ISOSpeed) ;
  141. aTab.AddElement (PropertyTagExifOECF, PROPERTY_TAG_EXIF_OECF) ;
  142. aTab.AddElement (PropertyTagExifVer, PROPERTY_TAG_EXIF_Ver) ;
  143. aTab.AddElement (PropertyTagExifDTOrig, PROPERTY_TAG_EXIF_DTOrig) ;
  144. aTab.AddElement (PropertyTagExifDTDigitized, PROPERTY_TAG_EXIF_DTDigitized) ;
  145. aTab.AddElement (PropertyTagExifCompConfig, PROPERTY_TAG_EXIF_CompConfig) ;
  146. aTab.AddElement (PropertyTagExifCompBPP, PROPERTY_TAG_EXIF_CompBPP) ;
  147. aTab.AddElement (PropertyTagExifShutterSpeed, PROPERTY_TAG_EXIF_ShutterSpeed) ;
  148. aTab.AddElement (PropertyTagExifAperture, PROPERTY_TAG_EXIF_Aperture) ;
  149. aTab.AddElement (PropertyTagExifBrightness, PROPERTY_TAG_EXIF_Brightness) ;
  150. aTab.AddElement (PropertyTagExifExposureBias, PROPERTY_TAG_EXIF_ExposureBias) ;
  151. aTab.AddElement (PropertyTagExifMaxAperture, PROPERTY_TAG_EXIF_MaxAperture) ;
  152. aTab.AddElement (PropertyTagExifSubjectDist, PROPERTY_TAG_EXIF_SubjectDist) ;
  153. aTab.AddElement (PropertyTagExifMeteringMode, PROPERTY_TAG_EXIF_MeteringMode) ;
  154. aTab.AddElement (PropertyTagExifLightSource, PROPERTY_TAG_EXIF_LightSource) ;
  155. aTab.AddElement (PropertyTagExifFlash, PROPERTY_TAG_EXIF_Flash) ;
  156. aTab.AddElement (PropertyTagExifFocalLength, PROPERTY_TAG_EXIF_FocalLength) ;
  157. aTab.AddElement (PropertyTagExifMakerNote, PROPERTY_TAG_EXIF_MakerNote) ;
  158. aTab.AddElement (PropertyTagExifUserComment, PROPERTY_TAG_EXIF_UserComment) ;
  159. aTab.AddElement (PropertyTagExifDTSubsec, PROPERTY_TAG_EXIF_DTSubsec) ;
  160. aTab.AddElement (PropertyTagExifDTOrigSS, PROPERTY_TAG_EXIF_DTOrigSS) ;
  161. aTab.AddElement (PropertyTagExifDTDigSS, PROPERTY_TAG_EXIF_DTDigSS) ;
  162. aTab.AddElement (PropertyTagExifFPXVer, PROPERTY_TAG_EXIF_FPXVer) ;
  163. aTab.AddElement (PropertyTagExifColorSpace, PROPERTY_TAG_EXIF_ColorSpace) ;
  164. aTab.AddElement (PropertyTagExifPixXDim, PROPERTY_TAG_EXIF_PixXDim) ;
  165. aTab.AddElement (PropertyTagExifPixYDim, PROPERTY_TAG_EXIF_PixYDim) ;
  166. aTab.AddElement (PropertyTagExifRelatedWav, PROPERTY_TAG_EXIF_RelatedWav) ;
  167. aTab.AddElement (PropertyTagExifInterop, PROPERTY_TAG_EXIF_Interop) ;
  168. aTab.AddElement (PropertyTagExifFlashEnergy, PROPERTY_TAG_EXIF_FlashEnergy) ;
  169. aTab.AddElement (PropertyTagExifSpatialFR, PROPERTY_TAG_EXIF_SpatialFR) ;
  170. aTab.AddElement (PropertyTagExifFocalXRes, PROPERTY_TAG_EXIF_FocalXRes) ;
  171. aTab.AddElement (PropertyTagExifFocalYRes, PROPERTY_TAG_EXIF_FocalYRes) ;
  172. aTab.AddElement (PropertyTagExifFocalResUnit, PROPERTY_TAG_EXIF_FocalResUnit) ;
  173. aTab.AddElement (PropertyTagExifSubjectLoc, PROPERTY_TAG_EXIF_SubjectLoc) ;
  174. aTab.AddElement (PropertyTagExifExposureIndex, PROPERTY_TAG_EXIF_ExposureIndex) ;
  175. aTab.AddElement (PropertyTagExifSensingMethod, PROPERTY_TAG_EXIF_SensingMethod) ;
  176. aTab.AddElement (PropertyTagExifFileSource, PROPERTY_TAG_EXIF_FileSource) ;
  177. aTab.AddElement (PropertyTagExifSceneType, PROPERTY_TAG_EXIF_SceneType) ;
  178. aTab.AddElement (PropertyTagExifCfaPattern, PROPERTY_TAG_EXIF_CfaPattern) ;
  179. }
  180. };
  181. //=============================================================================
  182. /**
  183. * Read/Write image via Gdi+.
  184. * if you load a gif image with transparent color, you will get a 32bpp image object, transparent color be converted to alpha=0 pixel
  185. */
  186. class FCImageHandle_Gdiplus : public FCImageHandleBase,
  187. public FCAutoInitGDIPlus
  188. {
  189. /// Load image file via GDIPlus.
  190. virtual bool LoadImageFile (const char* szFileName,
  191. PCL_Interface_Composite<FCObjImage>& rImageList,
  192. std::auto_ptr<FCImageProperty>& rImageProp)
  193. {
  194. // load image file
  195. Gdiplus::Bitmap * gp_Bmp = new Gdiplus::Bitmap (bstr_t(szFileName), FALSE) ;
  196. bool bRet = StoreMultiFrame (gp_Bmp, rImageList, rImageProp) ;
  197. delete gp_Bmp ;
  198. return bRet ;
  199. }
  200. /// Load image memory via GDIPlus.
  201. virtual bool LoadImageMemory (const BYTE* pStart, int nMemSize,
  202. PCL_Interface_Composite<FCObjImage>& rImageList,
  203. std::auto_ptr<FCImageProperty>& rImageProp)
  204. {
  205. if (!pStart || (nMemSize <= 0))
  206. return false ;
  207. bool bRet = false ;
  208. HGLOBAL hBuffer = ::GlobalAlloc (GMEM_MOVEABLE, nMemSize) ;
  209. // copy to HGLOBAL then load
  210. ::CopyMemory (::GlobalLock(hBuffer), pStart, nMemSize) ;
  211. ::GlobalUnlock (hBuffer) ;
  212. IStream * pStream = NULL ;
  213. if (::CreateStreamOnHGlobal (hBuffer, TRUE, &pStream) == S_OK)
  214. {
  215. Gdiplus::Bitmap * gp_Bmp = new Gdiplus::Bitmap (pStream, FALSE) ;
  216. bRet = StoreMultiFrame (gp_Bmp, rImageList, rImageProp) ;
  217. delete gp_Bmp ;
  218. pStream->Release() ;
  219. }
  220. return bRet ;
  221. }
  222. static FCObjImage* CreateImageFromBitmap (Gdiplus::Bitmap* gp_Bmp) ;
  223. // Get all frames in gp_Bmp, add into rImageList.
  224. static bool StoreMultiFrame (Gdiplus::Bitmap* gp_Bmp,
  225. PCL_Interface_Composite<FCObjImage>& rImageList,
  226. std::auto_ptr<FCImageProperty>& rImageProp)
  227. {
  228. if (!gp_Bmp || (gp_Bmp->GetLastStatus() != Gdiplus::Ok))
  229. {
  230. assert(false); return false;
  231. }
  232. // get frame dimensions
  233. const UINT nDim = gp_Bmp->GetFrameDimensionsCount() ;
  234. PCL_array<GUID> listID (nDim) ;
  235. gp_Bmp->GetFrameDimensionsList (listID.get(), nDim) ;
  236. // get frame and store
  237. for (UINT i=0 ; i < nDim ; i++)
  238. {
  239. UINT nFrame = gp_Bmp->GetFrameCount (&listID[i]) ;
  240. for (UINT j=0 ; j < nFrame ; j++)
  241. {
  242. gp_Bmp->SelectActiveFrame (&listID[i], j) ;
  243. FCObjImage * pImg = CreateImageFromBitmap(gp_Bmp) ;
  244. if (pImg)
  245. {
  246. rImageList.PCL_PushObject(pImg) ;
  247. }
  248. }
  249. }
  250. // store image property
  251. rImageProp = std::auto_ptr<FCImageProperty>(CreatePropertyFromBitmap(gp_Bmp)) ;
  252. return true ;
  253. }
  254. // create image property object base Bitmap
  255. static FCImageProperty* CreatePropertyFromBitmap (Gdiplus::Bitmap* gp_Bmp)
  256. {
  257. // GDI+ tag <==> UIS tag
  258. PCL_TT_Convertor<PROPID, UIS_PROPERTY_TAG> aTab ;
  259. GetPropertyTagTab (aTab) ;
  260. // get all property
  261. UINT nBytes, nNum ;
  262. gp_Bmp->GetPropertySize (&nBytes, &nNum) ;
  263. PCL_array<Gdiplus::PropertyItem> gp_Item (new BYTE[nBytes]) ;
  264. gp_Bmp->GetAllPropertyItems (nBytes, nNum, gp_Item.get()) ;
  265. // fill tag
  266. FCImageProperty * pProp = new FCImageProperty ;
  267. for (UINT i=0 ; i < nNum ; i++)
  268. {
  269. Gdiplus::PropertyItem & rItem = gp_Item[i] ;
  270. UIS_PROPERTY_TAG nTag = aTab.First_to_Second (rItem.id, PROPERTY_TAG_UNKNOW) ;
  271. if (nTag == PROPERTY_TAG_UNKNOW)
  272. continue ;
  273. // convert all type to string
  274. if (rItem.type == PropertyTagTypeASCII)
  275. {
  276. std::string s ((char*)rItem.value, rItem.length) ;
  277. pProp->SetPropertyValue (nTag, s.c_str()) ;
  278. }
  279. else if (rItem.type == PropertyTagTypeRational)
  280. {
  281. assert (rItem.length == 8) ;
  282. if (rItem.length == 8)
  283. {
  284. std::string s = FCOXOHelper::X2A (*(unsigned long*)rItem.value) ;
  285. s += "/" ;
  286. s += FCOXOHelper::X2A (((unsigned long*)rItem.value)[1]) ;
  287. pProp->SetPropertyValue (nTag, s.c_str()) ;
  288. }
  289. }
  290. else if (rItem.type == PropertyTagTypeSRational)
  291. {
  292. assert (rItem.length == 8) ;
  293. if (rItem.length == 8)
  294. {
  295. std::string s = FCOXOHelper::X2A (*(long*)rItem.value) ;
  296. s += "/" ;
  297. s += FCOXOHelper::X2A (((long*)rItem.value)[1]) ;
  298. pProp->SetPropertyValue (nTag, s.c_str()) ;
  299. }
  300. }
  301. else if (rItem.type == PropertyTagTypeShort)
  302. {
  303. assert (rItem.length == 2) ;
  304. if (rItem.length == 2)
  305. {
  306. std::string s = FCOXOHelper::X2A (*(unsigned short*)rItem.value) ;
  307. pProp->SetPropertyValue (nTag, s.c_str()) ;
  308. }
  309. }
  310. else if (rItem.type == PropertyTagTypeLong)
  311. {
  312. if (rItem.id == PropertyTagFrameDelay)
  313. {
  314. assert (rItem.length % 4 == 0) ;
  315. for (ULONG i=0 ; i < rItem.length/4 ; i++)
  316. {
  317. unsigned long lv = ((unsigned long*)rItem.value)[i] ;
  318. pProp->PutFrameDelay ((int)lv * 10) ;
  319. }
  320. }
  321. else
  322. {
  323. assert (rItem.length == 4) ;
  324. if (rItem.length == 4)
  325. {
  326. std::string s = FCOXOHelper::X2A (*(unsigned long*)rItem.value) ;
  327. pProp->SetPropertyValue (nTag, s.c_str()) ;
  328. }
  329. }
  330. }
  331. }
  332. return pProp ;
  333. }
  334. /// Put property into bitmap object.
  335. static void PutPropertyInBitmap (const FCImageProperty& rImageProp, Gdiplus::Bitmap& gpBmp)
  336. {
  337. PCL_TT_Convertor<PROPID, WORD> tabType ;
  338. PCL_TT_Convertor<PROPID, UIS_PROPERTY_TAG> tabProp ;
  339. GetGdiplusPropertyTypeTab (tabType) ;
  340. GetPropertyTagTab (tabProp) ;
  341. // put image's property
  342. for (int i=0 ; i < rImageProp.GetElementCount() ; i++)
  343. {
  344. // becayse PropertyTagExifVer return PropertyTagTypeUndefined
  345. Gdiplus::PropertyItem aItem ;
  346. aItem.id = tabProp.Second_to_First (rImageProp.GetT1(i), PropertyTagExifVer) ;
  347. aItem.type = tabType.First_to_Second (aItem.id, PropertyTagTypeUndefined) ;
  348. if (aItem.type == PropertyTagTypeUndefined)
  349. continue ;
  350. const std::string & s = rImageProp.GetT2(i) ;
  351. if (aItem.type == PropertyTagTypeASCII)
  352. {
  353. PCL_array<char> pBuf (s.length() + 1) ;
  354. memset (pBuf.get(), 0, s.length() + 1) ;
  355. memcpy (pBuf.get(), s.c_str(), s.length()) ;
  356. aItem.length = s.length() + 1 ;
  357. aItem.value = pBuf.get() ;
  358. gpBmp.SetPropertyItem (&aItem) ;
  359. }
  360. else if (aItem.type == PropertyTagTypeRational)
  361. {
  362. size_t nPos = s.find ("/") ;
  363. if (nPos != std::string::npos)
  364. {
  365. unsigned long p[2] ;
  366. FCOXOHelper::A2X (s.substr(0,nPos), p[0]) ;
  367. FCOXOHelper::A2X (s.substr(nPos+1), p[1]) ;
  368. aItem.length = 8 ;
  369. aItem.value = p ;
  370. gpBmp.SetPropertyItem (&aItem) ;
  371. }
  372. }
  373. else if (aItem.type == PropertyTagTypeSRational)
  374. {
  375. size_t nPos = s.find ("/") ;
  376. if (nPos != std::string::npos)
  377. {
  378. long p[2] ;
  379. FCOXOHelper::A2X (s.substr(0,nPos), p[0]) ;
  380. FCOXOHelper::A2X (s.substr(nPos+1), p[1]) ;
  381. aItem.length = 8 ;
  382. aItem.value = p ;
  383. gpBmp.SetPropertyItem (&aItem) ;
  384. }
  385. }
  386. else if (aItem.type == PropertyTagTypeShort)
  387. {
  388. unsigned short n ;
  389. FCOXOHelper::A2X (s, n) ;
  390. aItem.length = 2 ;
  391. aItem.value = &n ;
  392. gpBmp.SetPropertyItem (&aItem) ;
  393. }
  394. else if (aItem.type == PropertyTagTypeLong)
  395. {
  396. unsigned long n ;
  397. FCOXOHelper::A2X (s, n) ;
  398. aItem.length = 4 ;
  399. aItem.value = &n ;
  400. gpBmp.SetPropertyItem (&aItem) ;
  401. }
  402. }
  403. }
  404. /**
  405. * Save image to file via GDI+.
  406. */
  407. virtual bool SaveImageFile (const char* szFileName,
  408. const std::deque<const FCObjImage*>& rImageList,
  409. const FCImageProperty& rImageProp)
  410. {
  411. if (rImageList.empty() || !rImageList[0]->IsValidImage())
  412. return false ;
  413. const FCObjImage &img = *rImageList[0] ;
  414. // get encoder's CLSID
  415. CLSID clsID ;
  416. IMAGE_TYPE imgType = FCObjImage::GetImageHandleFactory()->QueryImageFileType(szFileName) ;
  417. if (!GetImageEncoderClsid (imgType, &clsID))
  418. return false ;
  419. // if image is jpeg, set save quality
  420. std::auto_ptr<Gdiplus::EncoderParameters> pEnParas ;
  421. ULONG nQuality = JpegSaveQuality(rImageProp) ;
  422. if (imgType == IMG_JPG)
  423. {
  424. pEnParas = std::auto_ptr<Gdiplus::EncoderParameters>(new Gdiplus::EncoderParameters) ;
  425. pEnParas->Count = 1 ;
  426. pEnParas->Parameter[0].Guid = Gdiplus::EncoderQuality ;
  427. pEnParas->Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong ;
  428. pEnParas->Parameter[0].NumberOfValues = 1 ;
  429. pEnParas->Parameter[0].Value = &nQuality ;
  430. }
  431. // create a GDI+ bitmap and put property
  432. PCL_array<BITMAPINFO> bmfh (img.NewImgInfoWithPalette()) ;
  433. Gdiplus::Bitmap gpBmp (bmfh.get(), img.GetMemStart()) ;
  434. PutPropertyInBitmap (rImageProp, gpBmp) ;
  435. return (gpBmp.Save (bstr_t(szFileName), &clsID, pEnParas.get()) == Gdiplus::Ok) ;
  436. }
  437. };
  438. //=============================================================================
  439. // inline Implement
  440. //=============================================================================
  441. inline FCObjImage* FCImageHandle_Gdiplus::CreateImageFromBitmap (Gdiplus::Bitmap* gp_Bmp)
  442. {
  443. // get image's info
  444. BOOL bInitAlpha = FALSE ;
  445. BYTE __bufImgInfo[sizeof(BITMAPINFOHEADER) + 16] = {0} ;
  446. BITMAPINFOHEADER * pInfo = (BITMAPINFOHEADER*)__bufImgInfo ;
  447. DWORD * pMask = (DWORD*)(pInfo + 1) ;
  448. pInfo->biWidth = gp_Bmp->GetWidth() ;
  449. pInfo->biHeight = gp_Bmp->GetHeight() ;
  450. pInfo->biCompression = BI_RGB ;
  451. switch (gp_Bmp->GetPixelFormat())
  452. {
  453. case PixelFormat1bppIndexed : pInfo->biBitCount = 1 ; break ;
  454. case PixelFormat4bppIndexed : pInfo->biBitCount = 4 ; break ;
  455. case PixelFormat8bppIndexed : pInfo->biBitCount = 8 ; break ;
  456. case PixelFormat16bppRGB555 :
  457. case PixelFormat16bppARGB1555 :
  458. pInfo->biBitCount = 16 ;
  459. pInfo->biCompression = BI_BITFIELDS ;
  460. pMask[0] = MASK16_RED_555 ;
  461. pMask[1] = MASK16_GREEN_555 ;
  462. pMask[2] = MASK16_BLUE_555 ;
  463. break ;
  464. case PixelFormat16bppRGB565 :
  465. pInfo->biBitCount = 16 ;
  466. pInfo->biCompression = BI_BITFIELDS ;
  467. pMask[0] = MASK16_RED_565 ;
  468. pMask[1] = MASK16_GREEN_565 ;
  469. pMask[2] = MASK16_BLUE_565 ;
  470. break ;
  471. case PixelFormat24bppRGB : pInfo->biBitCount = 24 ; break ;
  472. case PixelFormat32bppRGB :
  473. pInfo->biBitCount = 32 ; // no alpha channel, fill 0xFF
  474. bInitAlpha = TRUE ;
  475. break ;
  476. case PixelFormat32bppPARGB :
  477. case PixelFormat32bppARGB : pInfo->biBitCount = 32 ; break ;
  478. default :
  479. return NULL ;
  480. }
  481. // create image
  482. FCObjImage * pImg = new FCObjImage ;
  483. if (!pImg->Create(pInfo))
  484. {
  485. delete pImg; return NULL ;
  486. }
  487. // set palette
  488. if (pImg->ColorBits() <= 8)
  489. {
  490. const int nByte = gp_Bmp->GetPaletteSize() ;
  491. PCL_array<Gdiplus::ColorPalette> pPal (new BYTE[nByte]) ;
  492. gp_Bmp->GetPalette (pPal.get(), nByte) ;
  493. pImg->SetColorTable (0, pPal.get()->Count, (RGBQUAD*)&pPal.get()->Entries[0]) ;
  494. }
  495. // set pixel
  496. Gdiplus::Rect rcLock (0, 0, pImg->Width(), pImg->Height()) ;
  497. Gdiplus::BitmapData BmpData ;
  498. #if _MSC_VER > 1200 // VC7
  499. gp_Bmp->LockBits (&rcLock, Gdiplus::ImageLockModeRead, gp_Bmp->GetPixelFormat(), &BmpData) ;
  500. #else
  501. gp_Bmp->LockBits (rcLock, Gdiplus::ImageLockModeRead, gp_Bmp->GetPixelFormat(), &BmpData) ;
  502. #endif
  503. const BYTE * pPix = (BYTE*)BmpData.Scan0 ;
  504. const int nPitch = FMin (pImg->GetPitch(), BmpData.Stride) ;
  505. for(int y=0 ; y < pImg->Height() ; y++)
  506. {
  507. CopyMemory (pImg->GetBits(y), &pPix[y * BmpData.Stride], nPitch) ;
  508. }
  509. gp_Bmp->UnlockBits (&BmpData) ;
  510. // over
  511. if (bInitAlpha)
  512. pImg->SetAlphaChannelValue(0xFF) ;
  513. return pImg ;
  514. }
  515. //-----------------------------------------------------------------------------
  516. #endif