JXRGlueJxr.c 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280
  1. //*@@@+++@@@@******************************************************************
  2. //
  3. // Copyright © Microsoft Corp.
  4. // All rights reserved.
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are met:
  8. //
  9. // • Redistributions of source code must retain the above copyright notice,
  10. // this list of conditions and the following disclaimer.
  11. // • Redistributions in binary form must reproduce the above copyright notice,
  12. // this list of conditions and the following disclaimer in the documentation
  13. // and/or other materials provided with the distribution.
  14. //
  15. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  19. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. // POSSIBILITY OF SUCH DAMAGE.
  26. //
  27. //*@@@---@@@@******************************************************************
  28. #include <limits.h>
  29. #include <JXRGlue.h>
  30. static const char szHDPhotoFormat[] = "<dc:format>image/vnd.ms-photo</dc:format>";
  31. const U32 IFDEntryTypeSizes[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 };
  32. const U32 SizeofIFDEntry = sizeof(struct IFDEntry);
  33. void CalcMetadataSizeLPSTR(const DPKPROPVARIANT var,
  34. U16 *pcInactiveMetadata,
  35. U32 *pcbOffsetSize,
  36. U32 *pcbCount)
  37. {
  38. if (DPKVT_EMPTY != var.vt)
  39. {
  40. U32 uiLenWithNull = (U32)strlen(var.VT.pszVal) + 1; // +1 for NULL;
  41. assert(DPKVT_LPSTR == var.vt);
  42. // We only use offset if size > 4
  43. if (uiLenWithNull > 4)
  44. *pcbOffsetSize += uiLenWithNull;
  45. if (pcbCount)
  46. *pcbCount = uiLenWithNull;
  47. }
  48. else
  49. *pcInactiveMetadata += 1;
  50. }
  51. void CalcMetadataSizeLPWSTR(const DPKPROPVARIANT var,
  52. U16 *pcInactiveMetadata,
  53. U32 *pcbOffsetSize,
  54. U32 *pcbCount)
  55. {
  56. if (DPKVT_EMPTY != var.vt)
  57. {
  58. U32 uiCBWithNull = sizeof(U16) * ((U32)wcslen((wchar_t *) var.VT.pwszVal) + 1); // +1 for NULL term;
  59. assert(DPKVT_LPWSTR == var.vt);
  60. // We only use offset if size > 4
  61. if (uiCBWithNull > 4)
  62. *pcbOffsetSize += uiCBWithNull;
  63. if (pcbCount)
  64. *pcbCount = uiCBWithNull;
  65. }
  66. else
  67. *pcInactiveMetadata += 1;
  68. }
  69. void CalcMetadataSizeUI2(const DPKPROPVARIANT var,
  70. U16 *pcInactiveMetadata,
  71. U32 *pcbMetadataSize)
  72. {
  73. UNREFERENCED_PARAMETER( pcbMetadataSize );
  74. if (DPKVT_EMPTY != var.vt)
  75. {
  76. assert(DPKVT_UI2 == var.vt);
  77. // This is a single UI2, so it will not be written via offset, but rather as value
  78. }
  79. else
  80. *pcInactiveMetadata += 1;
  81. }
  82. void CalcMetadataSizeUI4(const DPKPROPVARIANT var,
  83. U16 *pcInactiveMetadata,
  84. U32 *pcbContainer)
  85. {
  86. UNREFERENCED_PARAMETER( pcbContainer );
  87. if (DPKVT_EMPTY != var.vt)
  88. {
  89. assert(DPKVT_UI4 == var.vt);
  90. // This is a single UI4, so it will not be written via offset, but rather as value
  91. }
  92. else
  93. *pcInactiveMetadata += 1;
  94. }
  95. ERR CalcMetadataOffsetSize(PKImageEncode* pIE,
  96. U16 *pcInactiveMetadata,
  97. U32 *pcbMetadataSize)
  98. {
  99. ERR err = WMP_errSuccess;
  100. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarImageDescription, pcInactiveMetadata, pcbMetadataSize, NULL);
  101. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarCameraMake, pcInactiveMetadata, pcbMetadataSize, NULL);
  102. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarCameraModel, pcInactiveMetadata, pcbMetadataSize, NULL);
  103. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarSoftware, pcInactiveMetadata, pcbMetadataSize, NULL);
  104. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarDateTime, pcInactiveMetadata, pcbMetadataSize, NULL);
  105. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarArtist, pcInactiveMetadata, pcbMetadataSize, NULL);
  106. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarCopyright, pcInactiveMetadata, pcbMetadataSize, NULL);
  107. CalcMetadataSizeUI2(pIE->sDescMetadata.pvarRatingStars, pcInactiveMetadata, pcbMetadataSize);
  108. CalcMetadataSizeUI2(pIE->sDescMetadata.pvarRatingValue, pcInactiveMetadata, pcbMetadataSize);
  109. CalcMetadataSizeLPWSTR(pIE->sDescMetadata.pvarCaption, pcInactiveMetadata, pcbMetadataSize, NULL);
  110. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarDocumentName, pcInactiveMetadata, pcbMetadataSize, NULL);
  111. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarPageName, pcInactiveMetadata, pcbMetadataSize, NULL);
  112. CalcMetadataSizeUI4(pIE->sDescMetadata.pvarPageNumber, pcInactiveMetadata, pcbMetadataSize);
  113. CalcMetadataSizeLPSTR(pIE->sDescMetadata.pvarHostComputer, pcInactiveMetadata, pcbMetadataSize, NULL);
  114. return err;
  115. }
  116. ERR CopyDescMetadata(DPKPROPVARIANT *pvarDst,
  117. const DPKPROPVARIANT varSrc)
  118. {
  119. ERR err = WMP_errSuccess;
  120. size_t uiSize;
  121. pvarDst->vt = varSrc.vt;
  122. switch (varSrc.vt)
  123. {
  124. case DPKVT_LPSTR:
  125. pvarDst->vt = DPKVT_LPSTR;
  126. uiSize = strlen(varSrc.VT.pszVal) + 1;
  127. Call(PKAlloc((void **) &pvarDst->VT.pszVal, uiSize));
  128. memcpy(pvarDst->VT.pszVal, varSrc.VT.pszVal, uiSize);
  129. break;
  130. case DPKVT_LPWSTR:
  131. pvarDst->vt = DPKVT_LPWSTR;
  132. uiSize = sizeof(U16) * (wcslen((wchar_t *) varSrc.VT.pwszVal) + 1); // +1 for NULL term
  133. Call(PKAlloc((void **) &pvarDst->VT.pszVal, uiSize));
  134. memcpy(pvarDst->VT.pwszVal, varSrc.VT.pwszVal, uiSize);
  135. break;
  136. case DPKVT_UI2:
  137. pvarDst->VT.uiVal = varSrc.VT.uiVal;
  138. break;
  139. case DPKVT_UI4:
  140. pvarDst->VT.ulVal = varSrc.VT.ulVal;
  141. break;
  142. default:
  143. assert(FALSE); // This case is not handled
  144. FailIf(TRUE, WMP_errNotYetImplemented);
  145. // *** FALL THROUGH ***
  146. case DPKVT_EMPTY:
  147. memset(pvarDst, 0, sizeof(*pvarDst));
  148. assert(DPKVT_EMPTY == pvarDst->vt);
  149. break;
  150. }
  151. Cleanup:
  152. return err;
  153. }
  154. void FreeDescMetadata(DPKPROPVARIANT *pvar)
  155. {
  156. switch (pvar->vt)
  157. {
  158. case DPKVT_LPSTR:
  159. PKFree((void **) &pvar->VT.pszVal);
  160. break;
  161. case DPKVT_LPWSTR:
  162. PKFree((void **) &pvar->VT.pwszVal);
  163. break;
  164. default:
  165. assert(FALSE); // This case is not handled
  166. break;
  167. case DPKVT_EMPTY:
  168. case DPKVT_UI2:
  169. case DPKVT_UI4:
  170. break;
  171. }
  172. }
  173. ERR WriteDescMetadata(PKImageEncode *pIE,
  174. const DPKPROPVARIANT var,
  175. WmpDE *pwmpDE,
  176. U32 *puiCurrDescMetadataOffset,
  177. size_t *poffPos)
  178. {
  179. ERR err = WMP_errSuccess;
  180. WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc;
  181. struct WMPStream* pWS = pIE->pStream;
  182. U32 uiMetadataOffsetSize = 0;
  183. U32 uiCount = 0;
  184. U32 uiDataWrittenToOffset = 0;
  185. U16 uiTemp = 0;
  186. if (0 == pDEMisc->uDescMetadataOffset || 0 == pDEMisc->uDescMetadataByteCount)
  187. goto Cleanup; // Nothing to do here
  188. // Sanity check before - can be equal due to remaining metadata being DPKVT_EMPTY
  189. assert(*puiCurrDescMetadataOffset <= pDEMisc->uDescMetadataByteCount);
  190. switch (var.vt)
  191. {
  192. case DPKVT_EMPTY:
  193. break;
  194. case DPKVT_LPSTR:
  195. CalcMetadataSizeLPSTR(var, &uiTemp, &uiMetadataOffsetSize, &uiCount);
  196. pwmpDE->uCount = uiCount;
  197. pwmpDE->uValueOrOffset = pDEMisc->uDescMetadataOffset + *puiCurrDescMetadataOffset;
  198. Call(WriteWmpDE(pWS, poffPos, pwmpDE, (U8*)var.VT.pszVal, &uiDataWrittenToOffset));
  199. break;
  200. case DPKVT_LPWSTR:
  201. CalcMetadataSizeLPWSTR(var, &uiTemp, &uiMetadataOffsetSize, &uiCount);
  202. pwmpDE->uCount = uiCount;
  203. pwmpDE->uValueOrOffset = pDEMisc->uDescMetadataOffset + *puiCurrDescMetadataOffset;
  204. Call(WriteWmpDE(pWS, poffPos, pwmpDE, (U8*)var.VT.pwszVal, &uiDataWrittenToOffset));
  205. break;
  206. case DPKVT_UI2:
  207. CalcMetadataSizeUI2(var, &uiTemp, &uiMetadataOffsetSize);
  208. pwmpDE->uCount = 1;
  209. pwmpDE->uValueOrOffset = var.VT.uiVal;
  210. Call(WriteWmpDE(pWS, poffPos, pwmpDE, NULL, NULL));
  211. break;
  212. case DPKVT_UI4:
  213. CalcMetadataSizeUI4(var, &uiTemp, &uiMetadataOffsetSize);
  214. pwmpDE->uCount = 1;
  215. pwmpDE->uValueOrOffset = var.VT.ulVal;
  216. Call(WriteWmpDE(pWS, poffPos, pwmpDE, NULL, NULL));
  217. break;
  218. default:
  219. assert(FALSE); // This case is not handled
  220. FailIf(TRUE, WMP_errNotYetImplemented);
  221. break;
  222. }
  223. *puiCurrDescMetadataOffset += uiDataWrittenToOffset;
  224. // Sanity check after
  225. assert(*puiCurrDescMetadataOffset <= pDEMisc->uDescMetadataByteCount); // Can be equal
  226. Cleanup:
  227. return err;
  228. }
  229. //================================================================
  230. // PKImageEncode_WMP
  231. //================================================================
  232. ERR WriteContainerPre(
  233. PKImageEncode* pIE)
  234. {
  235. ERR err = WMP_errSuccess;
  236. const U32 OFFSET_OF_PFD = 0x20;
  237. struct WMPStream* pWS = pIE->pStream;
  238. WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc;
  239. PKPixelInfo PI;
  240. size_t offPos = 0;
  241. U8 IIMM[2] = {'\x49', '\x49'};
  242. // const U32 cbWmpDEMisc = OFFSET_OF_PFD;
  243. U32 cbMetadataOffsetSize = 0;
  244. U16 cInactiveMetadata = 0;
  245. U32 uiCurrDescMetadataOffset = 0;
  246. static WmpDE wmpDEs[] =
  247. {
  248. {WMP_tagDocumentName, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  249. {WMP_tagImageDescription, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  250. {WMP_tagCameraMake, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  251. {WMP_tagCameraModel, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  252. {WMP_tagPageName, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  253. {WMP_tagPageNumber, WMP_typSHORT, 2, (U32) -1}, // Descriptive metadata
  254. {WMP_tagSoftware, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  255. {WMP_tagDateTime, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  256. {WMP_tagArtist, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  257. {WMP_tagHostComputer, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  258. {WMP_tagRatingStars, WMP_typSHORT, 1, (U32) -1}, // Descriptive metadata
  259. {WMP_tagRatingValue, WMP_typSHORT, 1, (U32) -1}, // Descriptive metadata
  260. {WMP_tagCopyright, WMP_typASCII, 1, (U32) -1}, // Descriptive metadata
  261. {WMP_tagCaption, WMP_typBYTE, 1, (U32) -1}, // Descriptive metadata
  262. {WMP_tagXMPMetadata, WMP_typBYTE, 1, (U32) -1},
  263. {WMP_tagIPTCNAAMetadata, WMP_typBYTE, 1, (U32) -1},
  264. {WMP_tagPhotoshopMetadata, WMP_typBYTE, 1, (U32) -1},
  265. {WMP_tagEXIFMetadata, WMP_typLONG, 1, (U32) -1},
  266. {WMP_tagIccProfile, WMP_typUNDEFINED, 1, (U32) -1},
  267. {WMP_tagGPSInfoMetadata, WMP_typLONG, 1, (U32) -1},
  268. {WMP_tagPixelFormat, WMP_typBYTE, 16, (U32) -1},
  269. {WMP_tagTransformation, WMP_typLONG, 1, (U32) -1},
  270. {WMP_tagImageWidth, WMP_typLONG, 1, (U32) -1},
  271. {WMP_tagImageHeight, WMP_typLONG, 1, (U32) -1},
  272. {WMP_tagWidthResolution, WMP_typFLOAT, 1, (U32) -1},
  273. {WMP_tagHeightResolution, WMP_typFLOAT, 1, (U32) -1},
  274. {WMP_tagImageOffset, WMP_typLONG, 1, (U32) -1},
  275. {WMP_tagImageByteCount, WMP_typLONG, 1, (U32) -1},
  276. {WMP_tagAlphaOffset, WMP_typLONG, 1, (U32) -1},
  277. {WMP_tagAlphaByteCount, WMP_typLONG, 1, (U32) -1},
  278. };
  279. U16 cWmpDEs = sizeof(wmpDEs) / sizeof(wmpDEs[0]);
  280. WmpDE wmpDE = {0};
  281. size_t i = 0;
  282. U8* pbEXIFMetadata = NULL;
  283. U8* pbGPSInfoMetadata = NULL;
  284. // const unsigned char Zero[0x20] = { 0 };
  285. const unsigned char Zero[sizeof(struct IFDEntry) * sizeof(wmpDEs) / sizeof(wmpDEs[0]) + sizeof(U32)] = { 0 };
  286. assert(SizeofIFDEntry * sizeof(wmpDEs) / sizeof(wmpDEs[0]) + sizeof(U32) > 0x20);
  287. //================
  288. Call(pWS->GetPos(pWS, &offPos));
  289. FailIf(0 != offPos, WMP_errUnsupportedFormat);
  290. //================
  291. // Header (8 bytes)
  292. Call(pWS->Write(pWS, IIMM, sizeof(IIMM))); offPos += 2;
  293. Call(PutUShort(pWS, offPos, 0x01bc)); offPos += 2;
  294. Call(PutULong(pWS, offPos, (U32)OFFSET_OF_PFD)); offPos += 4;
  295. //================
  296. // Write overflow area
  297. pDEMisc->uOffPixelFormat = (U32)offPos;
  298. PI.pGUIDPixFmt = &pIE->guidPixFormat;
  299. PixelFormatLookup(&PI, LOOKUP_FORWARD);
  300. //Call(pWS->Write(pWS, PI.pGUIDPixFmt, sizeof(*PI.pGUIDPixFmt))); offPos += 16;
  301. /** following code is endian-agnostic **/
  302. {
  303. unsigned char *pGuid = (unsigned char *) &pIE->guidPixFormat;
  304. Call(PutULong(pWS, offPos, ((U32 *)pGuid)[0]));
  305. Call(PutUShort(pWS, offPos + 4, ((U16 *)(pGuid + 4))[0]));
  306. Call(PutUShort(pWS, offPos + 6, ((U16 *)(pGuid + 6))[0]));
  307. Call(pWS->Write(pWS, pGuid + 8, 8));
  308. offPos += 16;
  309. }
  310. //================
  311. // Tally up space required for descriptive metadata
  312. Call(CalcMetadataOffsetSize(pIE, &cInactiveMetadata, &cbMetadataOffsetSize));
  313. cWmpDEs -= cInactiveMetadata;
  314. //================
  315. // PFD
  316. assert (offPos <= OFFSET_OF_PFD); // otherwise stuff is overwritten
  317. if (offPos < OFFSET_OF_PFD)
  318. Call(pWS->Write(pWS, Zero, OFFSET_OF_PFD - offPos));
  319. offPos = (size_t)OFFSET_OF_PFD;
  320. if (!pIE->WMP.bHasAlpha || pIE->WMP.wmiSCP.uAlphaMode != 2) //no planar alpha
  321. cWmpDEs -= 2;
  322. if (0 == pIE->cbXMPMetadataByteCount)
  323. cWmpDEs -= 1; // No XMP metadata
  324. if (0 == pIE->cbIPTCNAAMetadataByteCount)
  325. cWmpDEs -= 1; // No IPTCNAA metadata
  326. if (0 == pIE->cbPhotoshopMetadataByteCount)
  327. cWmpDEs -= 1; // No Photoshop metadata
  328. if (0 == pIE->cbEXIFMetadataByteCount)
  329. cWmpDEs -= 1; // No EXIF metadata
  330. if (0 == pIE->cbColorContext)
  331. cWmpDEs -= 1; // No color context
  332. if (0 == pIE->cbGPSInfoMetadataByteCount)
  333. cWmpDEs -= 1; // No GPSInfo metadata
  334. pDEMisc->uImageOffset = (U32)(offPos + sizeof(U16) + SizeofIFDEntry * cWmpDEs + sizeof(U32));
  335. if (cbMetadataOffsetSize > 0)
  336. {
  337. pDEMisc->uDescMetadataByteCount = cbMetadataOffsetSize;
  338. pDEMisc->uDescMetadataOffset = pDEMisc->uImageOffset;
  339. pDEMisc->uImageOffset += cbMetadataOffsetSize;
  340. }
  341. if (pIE->cbXMPMetadataByteCount > 0)
  342. {
  343. pDEMisc->uXMPMetadataOffset = pDEMisc->uImageOffset;
  344. pDEMisc->uImageOffset += pIE->cbXMPMetadataByteCount;
  345. }
  346. if (pIE->cbIPTCNAAMetadataByteCount > 0)
  347. {
  348. pDEMisc->uIPTCNAAMetadataOffset = pDEMisc->uImageOffset;
  349. pDEMisc->uImageOffset += pIE->cbIPTCNAAMetadataByteCount;
  350. }
  351. if (pIE->cbPhotoshopMetadataByteCount > 0)
  352. {
  353. pDEMisc->uPhotoshopMetadataOffset = pDEMisc->uImageOffset;
  354. pDEMisc->uImageOffset += pIE->cbPhotoshopMetadataByteCount;
  355. }
  356. if (pIE->cbEXIFMetadataByteCount > 0)
  357. {
  358. pDEMisc->uEXIFMetadataOffset = pDEMisc->uImageOffset;
  359. pDEMisc->uImageOffset += (pDEMisc->uImageOffset & 1);
  360. pDEMisc->uImageOffset += pIE->cbEXIFMetadataByteCount;
  361. }
  362. if (pIE->cbColorContext > 0)
  363. {
  364. pDEMisc->uColorProfileOffset = pDEMisc->uImageOffset;
  365. pDEMisc->uImageOffset += pIE->cbColorContext;
  366. }
  367. if (pIE->cbGPSInfoMetadataByteCount > 0)
  368. {
  369. pDEMisc->uGPSInfoMetadataOffset = pDEMisc->uImageOffset;
  370. pDEMisc->uImageOffset += (pDEMisc->uImageOffset & 1);
  371. pDEMisc->uImageOffset += pIE->cbGPSInfoMetadataByteCount;
  372. }
  373. Call(PutUShort(pWS, offPos, cWmpDEs)); offPos += 2;
  374. Call(pWS->Write(pWS, Zero, SizeofIFDEntry * cWmpDEs + sizeof(U32)));
  375. //================
  376. wmpDE = wmpDEs[i++];
  377. assert(WMP_tagDocumentName == wmpDE.uTag);
  378. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarDocumentName, &wmpDE,
  379. &uiCurrDescMetadataOffset, &offPos));
  380. wmpDE = wmpDEs[i++];
  381. assert(WMP_tagImageDescription == wmpDE.uTag);
  382. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarImageDescription, &wmpDE,
  383. &uiCurrDescMetadataOffset, &offPos));
  384. wmpDE = wmpDEs[i++];
  385. assert(WMP_tagCameraMake == wmpDE.uTag);
  386. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCameraMake, &wmpDE,
  387. &uiCurrDescMetadataOffset, &offPos));
  388. wmpDE = wmpDEs[i++];
  389. assert(WMP_tagCameraModel == wmpDE.uTag);
  390. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCameraModel, &wmpDE,
  391. &uiCurrDescMetadataOffset, &offPos));
  392. wmpDE = wmpDEs[i++];
  393. assert(WMP_tagPageName == wmpDE.uTag);
  394. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarPageName, &wmpDE,
  395. &uiCurrDescMetadataOffset, &offPos));
  396. wmpDE = wmpDEs[i++];
  397. assert(WMP_tagPageNumber == wmpDE.uTag);
  398. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarPageNumber, &wmpDE,
  399. &uiCurrDescMetadataOffset, &offPos));
  400. wmpDE = wmpDEs[i++];
  401. assert(WMP_tagSoftware == wmpDE.uTag);
  402. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarSoftware, &wmpDE,
  403. &uiCurrDescMetadataOffset, &offPos));
  404. wmpDE = wmpDEs[i++];
  405. assert(WMP_tagDateTime == wmpDE.uTag);
  406. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarDateTime, &wmpDE,
  407. &uiCurrDescMetadataOffset, &offPos));
  408. wmpDE = wmpDEs[i++];
  409. assert(WMP_tagArtist == wmpDE.uTag);
  410. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarArtist, &wmpDE,
  411. &uiCurrDescMetadataOffset, &offPos));
  412. wmpDE = wmpDEs[i++];
  413. assert(WMP_tagHostComputer == wmpDE.uTag);
  414. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarHostComputer, &wmpDE,
  415. &uiCurrDescMetadataOffset, &offPos));
  416. wmpDE = wmpDEs[i++];
  417. assert(WMP_tagRatingStars == wmpDE.uTag);
  418. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarRatingStars, &wmpDE,
  419. &uiCurrDescMetadataOffset, &offPos));
  420. wmpDE = wmpDEs[i++];
  421. assert(WMP_tagRatingValue == wmpDE.uTag);
  422. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarRatingValue, &wmpDE,
  423. &uiCurrDescMetadataOffset, &offPos));
  424. wmpDE = wmpDEs[i++];
  425. assert(WMP_tagCopyright == wmpDE.uTag);
  426. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCopyright, &wmpDE,
  427. &uiCurrDescMetadataOffset, &offPos));
  428. wmpDE = wmpDEs[i++];
  429. assert(WMP_tagCaption == wmpDE.uTag);
  430. Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCaption, &wmpDE,
  431. &uiCurrDescMetadataOffset, &offPos));
  432. // XMP Metadata
  433. wmpDE = wmpDEs[i++];
  434. assert(WMP_tagXMPMetadata == wmpDE.uTag);
  435. if (pIE->cbXMPMetadataByteCount > 0)
  436. {
  437. U32 uiTemp;
  438. wmpDE.uCount = pIE->cbXMPMetadataByteCount;
  439. wmpDE.uValueOrOffset = pDEMisc->uXMPMetadataOffset;
  440. Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbXMPMetadata, &uiTemp));
  441. }
  442. // IPTCNAA Metadata
  443. wmpDE = wmpDEs[i++];
  444. assert(WMP_tagIPTCNAAMetadata == wmpDE.uTag);
  445. if (pIE->cbIPTCNAAMetadataByteCount > 0)
  446. {
  447. U32 uiTemp;
  448. wmpDE.uCount = pIE->cbIPTCNAAMetadataByteCount;
  449. wmpDE.uValueOrOffset = pDEMisc->uIPTCNAAMetadataOffset;
  450. Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbIPTCNAAMetadata, &uiTemp));
  451. }
  452. // Photoshop Metadata
  453. wmpDE = wmpDEs[i++];
  454. assert(WMP_tagPhotoshopMetadata == wmpDE.uTag);
  455. if (pIE->cbPhotoshopMetadataByteCount > 0)
  456. {
  457. U32 uiTemp;
  458. wmpDE.uCount = pIE->cbPhotoshopMetadataByteCount;
  459. wmpDE.uValueOrOffset = pDEMisc->uPhotoshopMetadataOffset;
  460. Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbPhotoshopMetadata, &uiTemp));
  461. }
  462. // EXIF Metadata
  463. wmpDE = wmpDEs[i++];
  464. assert(WMP_tagEXIFMetadata == wmpDE.uTag);
  465. if (pIE->cbEXIFMetadataByteCount > 0)
  466. {
  467. U32 uiTemp;
  468. if ((pDEMisc->uEXIFMetadataOffset & 1) != 0)
  469. {
  470. Call(pWS->SetPos(pWS, pDEMisc->uEXIFMetadataOffset));
  471. Call(pWS->Write(pWS, Zero, 1));
  472. }
  473. pDEMisc->uEXIFMetadataOffset += (pDEMisc->uEXIFMetadataOffset & 1);
  474. wmpDE.uValueOrOffset = pDEMisc->uEXIFMetadataOffset;
  475. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  476. Call(PKAlloc((void **) &pbEXIFMetadata, pIE->cbEXIFMetadataByteCount));
  477. uiTemp = pDEMisc->uEXIFMetadataOffset;
  478. Call(BufferCopyIFD(pIE->pbEXIFMetadata, pIE->cbEXIFMetadataByteCount, 0, WMP_INTEL_ENDIAN,
  479. pbEXIFMetadata - uiTemp, uiTemp + pIE->cbEXIFMetadataByteCount, &uiTemp));
  480. Call(pWS->SetPos(pWS, pDEMisc->uEXIFMetadataOffset));
  481. Call(pWS->Write(pWS, pbEXIFMetadata, pIE->cbEXIFMetadataByteCount));
  482. }
  483. // ICC Profile
  484. wmpDE = wmpDEs[i++];
  485. assert(WMP_tagIccProfile == wmpDE.uTag);
  486. if (pIE->cbColorContext > 0)
  487. {
  488. U32 uiTemp;
  489. wmpDE.uCount = pIE->cbColorContext;
  490. wmpDE.uValueOrOffset = pDEMisc->uColorProfileOffset;
  491. Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbColorContext, &uiTemp));
  492. }
  493. // GPSInfo Metadata
  494. wmpDE = wmpDEs[i++];
  495. assert(WMP_tagGPSInfoMetadata == wmpDE.uTag);
  496. if (pIE->cbGPSInfoMetadataByteCount > 0)
  497. {
  498. U32 uiTemp;
  499. if ((pDEMisc->uGPSInfoMetadataOffset & 1) != 0)
  500. {
  501. Call(pWS->SetPos(pWS, pDEMisc->uGPSInfoMetadataOffset));
  502. Call(pWS->Write(pWS, Zero, 1));
  503. }
  504. pDEMisc->uGPSInfoMetadataOffset += (pDEMisc->uGPSInfoMetadataOffset & 1);
  505. wmpDE.uValueOrOffset = pDEMisc->uGPSInfoMetadataOffset;
  506. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  507. Call(PKAlloc((void **) &pbGPSInfoMetadata, pIE->cbGPSInfoMetadataByteCount));
  508. uiTemp = pDEMisc->uGPSInfoMetadataOffset;
  509. Call(BufferCopyIFD(pIE->pbGPSInfoMetadata, pIE->cbGPSInfoMetadataByteCount, 0, WMP_INTEL_ENDIAN,
  510. pbGPSInfoMetadata - uiTemp, uiTemp + pIE->cbGPSInfoMetadataByteCount, &uiTemp));
  511. Call(pWS->SetPos(pWS, pDEMisc->uGPSInfoMetadataOffset));
  512. Call(pWS->Write(pWS, pbGPSInfoMetadata, pIE->cbGPSInfoMetadataByteCount));
  513. }
  514. wmpDE = wmpDEs[i++];
  515. assert(WMP_tagPixelFormat == wmpDE.uTag);
  516. wmpDE.uValueOrOffset = pDEMisc->uOffPixelFormat;
  517. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  518. wmpDE = wmpDEs[i++];
  519. assert(WMP_tagTransformation == wmpDE.uTag);
  520. wmpDE.uValueOrOffset = pIE->WMP.oOrientation;
  521. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  522. wmpDE = wmpDEs[i++];
  523. assert(WMP_tagImageWidth == wmpDE.uTag);
  524. wmpDE.uValueOrOffset = pIE->uWidth;
  525. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  526. wmpDE = wmpDEs[i++];
  527. assert(WMP_tagImageHeight == wmpDE.uTag);
  528. wmpDE.uValueOrOffset = pIE->uHeight;
  529. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  530. wmpDE = wmpDEs[i++];
  531. assert(WMP_tagWidthResolution == wmpDE.uTag);
  532. *((float *) &wmpDE.uValueOrOffset) = pIE->fResX;
  533. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  534. wmpDE = wmpDEs[i++];
  535. assert(WMP_tagHeightResolution == wmpDE.uTag);
  536. *((float *) &wmpDE.uValueOrOffset) = pIE->fResY;
  537. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  538. wmpDE = wmpDEs[i++];
  539. assert(WMP_tagImageOffset == wmpDE.uTag);
  540. wmpDE.uValueOrOffset = pDEMisc->uImageOffset;
  541. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  542. // fix up in WriteContainerPost()
  543. wmpDE = wmpDEs[i++];
  544. assert(WMP_tagImageByteCount == wmpDE.uTag);
  545. pDEMisc->uOffImageByteCount = (U32)offPos;
  546. wmpDE.uValueOrOffset = 0;
  547. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  548. if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2)
  549. {
  550. // fix up in WriteContainerPost()
  551. wmpDE = wmpDEs[i++];
  552. assert(WMP_tagAlphaOffset == wmpDE.uTag);
  553. pDEMisc->uOffAlphaOffset = (U32)offPos;
  554. wmpDE.uValueOrOffset = 0;
  555. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  556. // fix up in WriteContainerPost()
  557. wmpDE = wmpDEs[i++];
  558. assert(WMP_tagAlphaByteCount == wmpDE.uTag);
  559. pDEMisc->uOffAlphaByteCount = (U32)offPos;
  560. wmpDE.uValueOrOffset = 0;
  561. Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL));
  562. }
  563. //================
  564. Call(PutULong(pWS, offPos, 0)); offPos += 4;
  565. assert(0 == (offPos & 1));
  566. if (pDEMisc->uColorProfileOffset > 0 || pDEMisc->uDescMetadataOffset > 0 ||
  567. pDEMisc->uXMPMetadataOffset > 0 || pDEMisc->uIPTCNAAMetadataOffset > 0 ||
  568. pDEMisc->uPhotoshopMetadataOffset > 0 || pDEMisc->uEXIFMetadataOffset > 0 ||
  569. pDEMisc->uGPSInfoMetadataOffset > 0)
  570. {
  571. assert(pDEMisc->uColorProfileOffset == offPos ||
  572. pDEMisc->uDescMetadataOffset == offPos ||
  573. pDEMisc->uXMPMetadataOffset == offPos ||
  574. pDEMisc->uIPTCNAAMetadataOffset == offPos ||
  575. pDEMisc->uPhotoshopMetadataOffset == offPos ||
  576. pDEMisc->uEXIFMetadataOffset == offPos ||
  577. pDEMisc->uGPSInfoMetadataOffset == offPos);
  578. // OK, now skip to image offset
  579. Call(pWS->SetPos(pWS, pDEMisc->uImageOffset));
  580. offPos = pDEMisc->uImageOffset;
  581. }
  582. assert(pDEMisc->uImageOffset == offPos);
  583. Cleanup:
  584. if (pbEXIFMetadata != NULL)
  585. PKFree((void **) &pbEXIFMetadata);
  586. if (pbGPSInfoMetadata != NULL)
  587. PKFree((void **) &pbGPSInfoMetadata);
  588. return err;
  589. }
  590. ERR WriteContainerPost(
  591. PKImageEncode* pIE)
  592. {
  593. ERR err = WMP_errSuccess;
  594. struct WMPStream* pWS = pIE->pStream;
  595. WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc;
  596. size_t offPos;
  597. WmpDE deImageByteCount = {WMP_tagImageByteCount, WMP_typLONG, 1, 0};
  598. WmpDE deAlphaOffset = {WMP_tagAlphaOffset, WMP_typLONG, 1, 0};
  599. WmpDE deAlphaByteCount = {WMP_tagAlphaByteCount, WMP_typLONG, 1, 0};
  600. deImageByteCount.uValueOrOffset = pIE->WMP.nCbImage;
  601. offPos = pDEMisc->uOffImageByteCount;
  602. Call(WriteWmpDE(pWS, &offPos, &deImageByteCount, NULL, NULL));
  603. //Alpha
  604. if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2)
  605. {
  606. deAlphaOffset.uValueOrOffset = pIE->WMP.nOffAlpha;
  607. offPos = pDEMisc->uOffAlphaOffset;
  608. Call(WriteWmpDE(pWS, &offPos, &deAlphaOffset, NULL, NULL));
  609. deAlphaByteCount.uValueOrOffset = pIE->WMP.nCbAlpha + pIE->WMP.nOffAlpha;
  610. offPos = pDEMisc->uOffAlphaByteCount;
  611. Call(WriteWmpDE(pWS, &offPos, &deAlphaByteCount, NULL, NULL));
  612. }
  613. Cleanup:
  614. return err;
  615. }
  616. //================================================
  617. ERR PKImageEncode_Initialize_WMP(
  618. PKImageEncode* pIE,
  619. struct WMPStream* pStream,
  620. void* pvParam,
  621. size_t cbParam)
  622. {
  623. ERR err = WMP_errSuccess;
  624. FailIf(sizeof(pIE->WMP.wmiSCP) != cbParam, WMP_errInvalidArgument);
  625. pIE->WMP.wmiSCP = *(CWMIStrCodecParam*)pvParam;
  626. pIE->WMP.wmiSCP_Alpha = *(CWMIStrCodecParam*)pvParam;
  627. pIE->pStream = pStream;
  628. pIE->WMP.wmiSCP.pWStream = pIE->pStream;
  629. pIE->WMP.wmiSCP_Alpha.pWStream = pIE->pStream;
  630. Cleanup:
  631. return err;
  632. }
  633. ERR PKImageEncode_Terminate_WMP(
  634. PKImageEncode* pIE)
  635. {
  636. ERR err = WMP_errSuccess;
  637. UNREFERENCED_PARAMETER( pIE );
  638. return err;
  639. }
  640. ERR PKImageEncode_EncodeContent_Init(
  641. PKImageEncode* pIE,
  642. PKPixelInfo PI,
  643. U32 cLine,
  644. U8* pbPixels,
  645. U32 cbStride)
  646. {
  647. ERR err = WMP_errSuccess;
  648. // init codec
  649. pIE->WMP.wmiI.cWidth = pIE->uWidth;
  650. pIE->WMP.wmiI.cHeight = pIE->uHeight;
  651. pIE->WMP.wmiI.bdBitDepth = PI.bdBitDepth;
  652. pIE->WMP.wmiI.cBitsPerUnit = PI.cbitUnit;
  653. pIE->WMP.wmiI.bRGB = !(PI.grBit & PK_pixfmtBGR);
  654. pIE->WMP.wmiI.cfColorFormat = PI.cfColorFormat;
  655. pIE->WMP.wmiI.oOrientation = pIE->WMP.oOrientation;
  656. // Set the fPaddedUserBuffer if the following conditions are met
  657. if (0 == ((size_t)pbPixels % 128) && // Frame buffer is aligned to 128-byte boundary
  658. 0 == (pIE->uWidth % 16) && // Horizontal resolution is multiple of 16
  659. 0 == (cLine % 16) && // Vertical resolution is multiple of 16
  660. 0 == (cbStride % 128)) // Stride is a multiple of 128 bytes
  661. {
  662. pIE->WMP.wmiI.fPaddedUserBuffer = TRUE;
  663. // Note that there are additional conditions in strenc_x86.c's strEncOpt
  664. // which could prevent optimization from being engaged
  665. }
  666. //if (pIE->WMP.bHasAlpha)
  667. //{
  668. // pIE->WMP.wmiSCP.cChannel = PI.cChannel - 1;
  669. // pIE->WMP.wmiI.cfColorFormat = PI.cfStripAlpha;
  670. //}
  671. //else
  672. if(PI.cfColorFormat == NCOMPONENT && (!(PI.grBit & PK_pixfmtHasAlpha)))//N-channel without Alpha
  673. pIE->WMP.wmiSCP.cChannel = PI.cChannel;
  674. else
  675. pIE->WMP.wmiSCP.cChannel = PI.cChannel - 1;//other formats and (N-channel + Alpha)
  676. pIE->idxCurrentLine = 0;
  677. pIE->WMP.wmiSCP.fMeasurePerf = TRUE;
  678. FailIf(ICERR_OK != ImageStrEncInit(&pIE->WMP.wmiI, &pIE->WMP.wmiSCP, &pIE->WMP.ctxSC), WMP_errFail);
  679. Cleanup:
  680. return err;
  681. }
  682. ERR PKImageEncode_EncodeContent_Encode(
  683. PKImageEncode* pIE,
  684. U32 cLine,
  685. U8* pbPixels,
  686. U32 cbStride)
  687. {
  688. ERR err = WMP_errSuccess;
  689. U32 i = 0;
  690. //================================
  691. for (i = 0; i < cLine; i += 16)
  692. {
  693. Bool f420 = ( pIE->WMP.wmiI.cfColorFormat == YUV_420 ||
  694. (pIE->WMP.wmiSCP.bYUVData && pIE->WMP.wmiSCP.cfColorFormat==YUV_420) );
  695. CWMImageBufferInfo wmiBI = { 0 };
  696. wmiBI.pv = pbPixels + cbStride * i / (f420 ? 2 : 1);
  697. wmiBI.cLine = min(16, cLine - i);
  698. wmiBI.cbStride = cbStride;
  699. FailIf(ICERR_OK != ImageStrEncEncode(pIE->WMP.ctxSC, &wmiBI), WMP_errFail);
  700. }
  701. pIE->idxCurrentLine += cLine;
  702. Cleanup:
  703. return err;
  704. }
  705. ERR PKImageEncode_EncodeContent_Term(PKImageEncode* pIE)
  706. {
  707. ERR err = WMP_errSuccess;
  708. FailIf(ICERR_OK != ImageStrEncTerm(pIE->WMP.ctxSC), WMP_errFail);
  709. Cleanup:
  710. return err;
  711. }
  712. ERR PKImageEncode_EncodeContent(
  713. PKImageEncode* pIE,
  714. PKPixelInfo PI,
  715. U32 cLine,
  716. U8* pbPixels,
  717. U32 cbStride)
  718. {
  719. ERR err = WMP_errSuccess;
  720. size_t offPos = 0;
  721. Call(pIE->pStream->GetPos(pIE->pStream, &offPos));
  722. pIE->WMP.nOffImage = (Long)offPos;
  723. Call(PKImageEncode_EncodeContent_Init(pIE, PI, cLine, pbPixels, cbStride));
  724. Call(PKImageEncode_EncodeContent_Encode(pIE, cLine, pbPixels, cbStride));
  725. Call(PKImageEncode_EncodeContent_Term(pIE));
  726. Call(pIE->pStream->GetPos(pIE->pStream, &offPos));
  727. pIE->WMP.nCbImage = (Long)offPos - pIE->WMP.nOffImage;
  728. Cleanup:
  729. return err;
  730. }
  731. ERR PKImageEncode_EncodeAlpha_Init(
  732. PKImageEncode* pIE,
  733. PKPixelInfo PI,
  734. U32 cLine,
  735. U8* pbPixels,
  736. U32 cbStride)
  737. {
  738. ERR err = WMP_errSuccess;
  739. UNREFERENCED_PARAMETER( cLine );
  740. UNREFERENCED_PARAMETER( pbPixels );
  741. UNREFERENCED_PARAMETER( cbStride );
  742. pIE->WMP.wmiI_Alpha = pIE->WMP.wmiI;
  743. pIE->WMP.wmiI_Alpha.cWidth = pIE->uWidth;
  744. pIE->WMP.wmiI_Alpha.cHeight = pIE->uHeight;
  745. pIE->WMP.wmiI_Alpha.bdBitDepth = PI.bdBitDepth;
  746. pIE->WMP.wmiI_Alpha.cBitsPerUnit = PI.cbitUnit;
  747. pIE->WMP.wmiI_Alpha.bRGB = !(PI.grBit & PK_pixfmtBGR);
  748. pIE->WMP.wmiI.oOrientation = pIE->WMP.oOrientation;
  749. // pIE->WMP.wmiI_Alpha.cLeadingPadding += pIE->WMP.wmiSCP.cChannel;
  750. // pIE->WMP.wmiI_Alpha.cLeadingPadding += PI.cChannel - 1;
  751. switch (pIE->WMP.wmiI.bdBitDepth)
  752. {
  753. case BD_8:
  754. pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) - 1;
  755. break;
  756. case BD_16:
  757. case BD_16S:
  758. case BD_16F:
  759. pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(U16) - 1;
  760. break;
  761. case BD_32:
  762. case BD_32S:
  763. case BD_32F:
  764. pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(float) - 1;
  765. break;
  766. case BD_5:
  767. case BD_10:
  768. case BD_565:
  769. default:
  770. break;
  771. }
  772. // pIE->WMP.wmiSCP_Alpha.uAlphaMode = 1;
  773. //assert(pIE->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now!
  774. pIE->WMP.wmiI_Alpha.cfColorFormat = Y_ONLY;
  775. pIE->WMP.wmiSCP_Alpha.cfColorFormat = Y_ONLY;
  776. pIE->idxCurrentLine = 0;
  777. pIE->WMP.wmiSCP_Alpha.fMeasurePerf = TRUE;
  778. FailIf(ICERR_OK != ImageStrEncInit(&pIE->WMP.wmiI_Alpha, &pIE->WMP.wmiSCP_Alpha, &pIE->WMP.ctxSC_Alpha), WMP_errFail);
  779. Cleanup:
  780. return err;
  781. }
  782. ERR PKImageEncode_EncodeAlpha_Encode(
  783. PKImageEncode* pIE,
  784. U32 cLine,
  785. U8* pbPixels,
  786. U32 cbStride)
  787. {
  788. ERR err = WMP_errSuccess;
  789. U32 i = 0;
  790. //================================
  791. for (i = 0; i < cLine; i += 16)
  792. {
  793. CWMImageBufferInfo wmiBI = { 0 };
  794. wmiBI.pv = pbPixels + cbStride * i;
  795. wmiBI.cLine = min(16, cLine - i);
  796. wmiBI.cbStride = cbStride;
  797. FailIf(ICERR_OK != ImageStrEncEncode(pIE->WMP.ctxSC_Alpha, &wmiBI), WMP_errFail);
  798. }
  799. pIE->idxCurrentLine += cLine;
  800. Cleanup:
  801. return err;
  802. }
  803. ERR PKImageEncode_EncodeAlpha_Term(PKImageEncode* pIE)
  804. {
  805. ERR err = WMP_errSuccess;
  806. FailIf(ICERR_OK != ImageStrEncTerm(pIE->WMP.ctxSC_Alpha), WMP_errFail);
  807. Cleanup:
  808. return err;
  809. }
  810. ERR PKImageEncode_EncodeAlpha(
  811. PKImageEncode* pIE,
  812. PKPixelInfo PI,
  813. U32 cLine,
  814. U8* pbPixels,
  815. U32 cbStride)
  816. {
  817. ERR err = WMP_errSuccess;
  818. size_t offPos = 0;
  819. Call(pIE->pStream->GetPos(pIE->pStream, &offPos));
  820. if ((offPos & 1) != 0)
  821. {
  822. // Make the mark even if it is odd by inserting a pad byte
  823. char zero = 0;
  824. Call(pIE->pStream->Write(pIE->pStream, &zero, 1));
  825. offPos++;
  826. }
  827. pIE->WMP.nOffAlpha = (Long)offPos;
  828. Call(PKImageEncode_EncodeAlpha_Init(pIE, PI, cLine, pbPixels, cbStride));
  829. Call(PKImageEncode_EncodeAlpha_Encode(pIE, cLine, pbPixels, cbStride));
  830. Call(PKImageEncode_EncodeAlpha_Term(pIE));
  831. Call(pIE->pStream->GetPos(pIE->pStream, &offPos));
  832. pIE->WMP.nCbAlpha = (Long)offPos - pIE->WMP.nOffAlpha;
  833. Cleanup:
  834. return err;
  835. }
  836. static ERR SetMetadata(PKImageEncode *pIE, const U8 *pbMetadata, U32 cbMetadata, U8** pbSet, U32* pcbSet)
  837. {
  838. ERR err = WMP_errSuccess;
  839. // Fail if the caller called us after we've already written the header out
  840. if (pIE->fHeaderDone)
  841. {
  842. assert(FALSE); // Message to programmer
  843. err = WMP_errOutOfSequence;
  844. goto Cleanup;
  845. }
  846. // Make a copy of the metadata
  847. PKFree((void **) pbSet);
  848. *pcbSet = 0;
  849. Call(PKAlloc((void **) pbSet, cbMetadata));
  850. memcpy(*pbSet, pbMetadata, cbMetadata);
  851. *pcbSet = cbMetadata;
  852. Cleanup:
  853. return err;
  854. }
  855. ERR PKImageEncode_SetColorContext_WMP(PKImageEncode *pIE,
  856. const U8 *pbColorContext,
  857. U32 cbColorContext)
  858. {
  859. return SetMetadata(pIE, pbColorContext, cbColorContext, &pIE->pbColorContext, &pIE->cbColorContext);
  860. }
  861. ERR PKImageEncode_SetXMPMetadata_WMP(PKImageEncode *pIE, const U8 *pbXMPMetadata, U32 cbXMPMetadata)
  862. { // same as the other Set's, but make sure dc:format is <dc:format>image/vnd.ms-photo</dc:format>
  863. ERR err = WMP_errSuccess;
  864. char* pbTemp = 0;
  865. U32 cbTemp;
  866. char* pszFormatBegin;
  867. // const char* pszXMPMetadata = (const char*)pbXMPMetadata;
  868. size_t cbBuffer;
  869. // Fail if the caller called us after we've already written the header out
  870. FailIf(pIE->fHeaderDone, WMP_errOutOfSequence);
  871. // Free any previously set XMP metadata
  872. PKFree((void **) &pIE->pbXMPMetadata);
  873. pIE->cbXMPMetadataByteCount = 0;
  874. // allocate a block big enough for data passed in plus added trailing null plus added HD Photo dc:format
  875. // there may already be a trailing null (but ps doesn't seem to)
  876. // there may already be a dc:format we will replace with HD Photo's
  877. // but anyway this block will be large enough guaranteed
  878. cbBuffer = cbXMPMetadata + 1 + sizeof("<dc:format>") - 1 + sizeof("</dc:format>") - 1 + sizeof(szHDPhotoFormat) - 1;
  879. Call(PKAlloc((void **) &pbTemp, cbBuffer));
  880. memcpy(pbTemp, pbXMPMetadata, cbXMPMetadata); // Make a copy of the metadata
  881. pbTemp[cbXMPMetadata] = '\0';
  882. cbXMPMetadata = (U32)strlen(pbTemp);
  883. pszFormatBegin = strstr(pbTemp, "<dc:format>");
  884. if ( pszFormatBegin != 0 )
  885. {
  886. char* pszFormatEnd;
  887. const char* pszLessThan;
  888. pszFormatEnd = strstr(pszFormatBegin, "</dc:format>");
  889. FailIf(pszFormatEnd == 0, WMP_errFail);
  890. pszLessThan = strchr(pszFormatBegin + sizeof("<dc:format>") - 1, '<');
  891. FailIf(pszLessThan != pszFormatEnd, WMP_errFail);
  892. pszFormatEnd += sizeof("</dc:format>") - 1;
  893. // photoshop doesn't put a trailing null, so we don't either
  894. // hd and tiff don't put a trailing null, so we don't either
  895. cbTemp = cbXMPMetadata - (U32) ( pszFormatEnd - pszFormatBegin ) + sizeof(szHDPhotoFormat) - 1;
  896. assert(cbTemp <= cbBuffer);
  897. FailIf(0 != STRCPY_SAFE(pszFormatBegin,
  898. cbBuffer - (pszFormatBegin - pbTemp),
  899. szHDPhotoFormat),
  900. WMP_errBufferOverflow);
  901. memcpy(pszFormatBegin + sizeof(szHDPhotoFormat) - 1, pbXMPMetadata + ( pszFormatEnd - pbTemp ),
  902. cbXMPMetadata - ( pszFormatEnd - pbTemp ));
  903. }
  904. else
  905. {
  906. cbTemp = cbXMPMetadata;
  907. }
  908. pIE->pbXMPMetadata = (U8 *) pbTemp;
  909. pIE->cbXMPMetadataByteCount = cbTemp;
  910. return ( err );
  911. Cleanup:
  912. PKFree((void **) &pbTemp);
  913. pIE->cbXMPMetadataByteCount = 0;
  914. return err;
  915. }
  916. ERR PKImageEncode_SetEXIFMetadata_WMP(PKImageEncode *pIE, const U8 *pbEXIFMetadata, U32 cbEXIFMetadata)
  917. {
  918. return SetMetadata(pIE, pbEXIFMetadata, cbEXIFMetadata,
  919. &pIE->pbEXIFMetadata, &pIE->cbEXIFMetadataByteCount);
  920. }
  921. ERR PKImageEncode_SetGPSInfoMetadata_WMP(PKImageEncode *pIE, const U8 *pbGPSInfoMetadata, U32 cbGPSInfoMetadata)
  922. {
  923. return SetMetadata(pIE, pbGPSInfoMetadata, cbGPSInfoMetadata,
  924. &pIE->pbGPSInfoMetadata, &pIE->cbGPSInfoMetadataByteCount);
  925. }
  926. ERR PKImageEncode_SetIPTCNAAMetadata_WMP(PKImageEncode *pIE, const U8 *pbIPTCNAAMetadata, U32 cbIPTCNAAMetadata)
  927. {
  928. return SetMetadata(pIE, pbIPTCNAAMetadata, cbIPTCNAAMetadata,
  929. &pIE->pbIPTCNAAMetadata, &pIE->cbIPTCNAAMetadataByteCount);
  930. }
  931. ERR PKImageEncode_SetPhotoshopMetadata_WMP(PKImageEncode *pIE, const U8 *pbPhotoshopMetadata, U32 cbPhotoshopMetadata)
  932. {
  933. return SetMetadata(pIE, pbPhotoshopMetadata, cbPhotoshopMetadata,
  934. &pIE->pbPhotoshopMetadata, &pIE->cbPhotoshopMetadataByteCount);
  935. }
  936. ERR PKImageEncode_SetDescriptiveMetadata_WMP(PKImageEncode *pIE, const DESCRIPTIVEMETADATA *pSrcMeta)
  937. {
  938. ERR err = WMP_errSuccess;
  939. DESCRIPTIVEMETADATA *pDstMeta = &pIE->sDescMetadata;
  940. // Fail if the caller called us after we've already written the header out
  941. if (pIE->fHeaderDone)
  942. {
  943. assert(FALSE); // Message to programmer
  944. FailIf(TRUE, WMP_errOutOfSequence);
  945. }
  946. // Make a copy of the descriptive metadata
  947. Call(CopyDescMetadata(&pDstMeta->pvarImageDescription, pSrcMeta->pvarImageDescription));
  948. Call(CopyDescMetadata(&pDstMeta->pvarCameraMake, pSrcMeta->pvarCameraMake));
  949. Call(CopyDescMetadata(&pDstMeta->pvarCameraModel, pSrcMeta->pvarCameraModel));
  950. Call(CopyDescMetadata(&pDstMeta->pvarSoftware, pSrcMeta->pvarSoftware));
  951. Call(CopyDescMetadata(&pDstMeta->pvarDateTime, pSrcMeta->pvarDateTime));
  952. Call(CopyDescMetadata(&pDstMeta->pvarArtist, pSrcMeta->pvarArtist));
  953. Call(CopyDescMetadata(&pDstMeta->pvarCopyright, pSrcMeta->pvarCopyright));
  954. Call(CopyDescMetadata(&pDstMeta->pvarRatingStars, pSrcMeta->pvarRatingStars));
  955. Call(CopyDescMetadata(&pDstMeta->pvarRatingValue, pSrcMeta->pvarRatingValue));
  956. Call(CopyDescMetadata(&pDstMeta->pvarCaption, pSrcMeta->pvarCaption));
  957. Call(CopyDescMetadata(&pDstMeta->pvarDocumentName, pSrcMeta->pvarDocumentName));
  958. Call(CopyDescMetadata(&pDstMeta->pvarPageName, pSrcMeta->pvarPageName));
  959. Call(CopyDescMetadata(&pDstMeta->pvarPageNumber, pSrcMeta->pvarPageNumber));
  960. Call(CopyDescMetadata(&pDstMeta->pvarHostComputer, pSrcMeta->pvarHostComputer));
  961. Cleanup:
  962. return err;
  963. }
  964. ERR PKImageEncode_WritePixels_WMP(
  965. PKImageEncode* pIE,
  966. U32 cLine,
  967. U8* pbPixels,
  968. U32 cbStride)
  969. {
  970. ERR err = WMP_errSuccess;
  971. // U32 i = 0;
  972. PKPixelInfo PI;
  973. // Performing non-banded encode
  974. assert(BANDEDENCSTATE_UNINITIALIZED == pIE->WMP.eBandedEncState);
  975. pIE->WMP.eBandedEncState = BANDEDENCSTATE_NONBANDEDENCODE;
  976. PI.pGUIDPixFmt = &pIE->guidPixFormat;
  977. PixelFormatLookup(&PI, LOOKUP_FORWARD);
  978. pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha);
  979. if (!pIE->fHeaderDone)
  980. {
  981. // write metadata
  982. Call(WriteContainerPre(pIE));
  983. pIE->fHeaderDone = !FALSE;
  984. }
  985. /* if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2){
  986. pIE->WMP.wmiSCP_Alpha = pIE->WMP.wmiSCP;
  987. }
  988. */
  989. Call(PKImageEncode_EncodeContent(pIE, PI, cLine, pbPixels, cbStride));
  990. if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2){//planar alpha
  991. Call(PKImageEncode_EncodeAlpha(pIE, PI, cLine, pbPixels, cbStride));
  992. }
  993. Call(WriteContainerPost(pIE));
  994. Cleanup:
  995. return err;
  996. }
  997. ERR PKImageEncode_WritePixelsBandedBegin_WMP(PKImageEncode* pIE, struct WMPStream *pPATempFile)
  998. {
  999. ERR err = WMP_errSuccess;
  1000. // Just make sure that we are in the correct state to begin a banded decode
  1001. assert(BANDEDENCSTATE_UNINITIALIZED == pIE->WMP.eBandedEncState);
  1002. pIE->WMP.eBandedEncState = BANDEDENCSTATE_INIT;
  1003. // Save the planar alpha tempfile for future use
  1004. pIE->WMP.pPATempFile = pPATempFile;
  1005. //Cleanup:
  1006. return err;
  1007. }
  1008. ERR PKImageEncode_WritePixelsBanded_WMP(PKImageEncode* pIE, U32 cLine, U8* pbPixels, U32 cbStride, Bool fLastCall)
  1009. {
  1010. ERR err = WMP_errSuccess;
  1011. PKPixelInfo PI = {0};
  1012. Bool fPI = FALSE;
  1013. BANDEDENCSTATE eEncStateOrig = pIE->WMP.eBandedEncState;
  1014. struct WMPStream *pPATempFile = pIE->WMP.pPATempFile;
  1015. // Unless this is the last call, reject inputs which are not multiples of 16
  1016. FailIf(!fLastCall && 0 != cLine % 16, WMP_errMustBeMultipleOf16LinesUntilLastCall);
  1017. if (!pIE->fHeaderDone || BANDEDENCSTATE_INIT == pIE->WMP.eBandedEncState)
  1018. {
  1019. PI.pGUIDPixFmt = &pIE->guidPixFormat;
  1020. PixelFormatLookup(&PI, LOOKUP_FORWARD);
  1021. pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha);
  1022. fPI = TRUE;
  1023. // Check if this is planar alpha: banded encode requires temp file
  1024. if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2)
  1025. {
  1026. FailIf(NULL == pPATempFile, WMP_errPlanarAlphaBandedEncRequiresTempFile);
  1027. }
  1028. }
  1029. if (!pIE->fHeaderDone)
  1030. {
  1031. // write metadata
  1032. assert(fPI);
  1033. Call(WriteContainerPre(pIE));
  1034. pIE->fHeaderDone = !FALSE;
  1035. }
  1036. if (BANDEDENCSTATE_INIT == pIE->WMP.eBandedEncState)
  1037. {
  1038. // Record start of main content for future call to WriteContainerPost
  1039. size_t offPos;
  1040. Call(pIE->pStream->GetPos(pIE->pStream, &offPos));
  1041. pIE->WMP.nOffImage = (Long)offPos;
  1042. assert(fPI);
  1043. Call(PKImageEncode_EncodeContent_Init(pIE, PI, cLine, pbPixels, cbStride));
  1044. pIE->WMP.eBandedEncState = BANDEDENCSTATE_ENCODING;
  1045. }
  1046. Call(PKImageEncode_EncodeContent_Encode(pIE, cLine, pbPixels, cbStride));
  1047. if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2)
  1048. {
  1049. //planar alpha
  1050. if (BANDEDENCSTATE_INIT == eEncStateOrig)
  1051. {
  1052. size_t offStart;
  1053. // We assume the following which allows us to avoid saving state
  1054. Call(pPATempFile->GetPos(pPATempFile, &offStart));
  1055. assert(0 == offStart);
  1056. assert(pIE->WMP.wmiSCP_Alpha.pWStream == pIE->WMP.wmiSCP.pWStream);
  1057. // For planar alpha, we write the file to a temp file
  1058. pIE->WMP.wmiSCP_Alpha.pWStream = pPATempFile;
  1059. Call(PKImageEncode_EncodeAlpha_Init(pIE, PI, cLine, pbPixels, cbStride));
  1060. }
  1061. Call(PKImageEncode_EncodeAlpha_Encode(pIE, cLine, pbPixels, cbStride));
  1062. }
  1063. Cleanup:
  1064. return err;
  1065. }
  1066. ERR PKImageEncode_WritePixelsBandedEnd_WMP(PKImageEncode* pIE)
  1067. {
  1068. ERR err = WMP_errSuccess;
  1069. struct WMPStream *pMainStream = pIE->WMP.wmiSCP.pWStream;
  1070. size_t offAlpha;
  1071. assert(BANDEDENCSTATE_ENCODING == pIE->WMP.eBandedEncState);
  1072. // Finish off main content, update its length ptr for WriteContainerPost
  1073. Call(PKImageEncode_EncodeContent_Term(pIE));
  1074. Call(pMainStream->GetPos(pIE->pStream, &offAlpha));
  1075. pIE->WMP.nCbImage = (Long)offAlpha - pIE->WMP.nOffImage;
  1076. if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2)
  1077. {
  1078. size_t cbAlpha;
  1079. size_t cbBytesCopied;
  1080. struct WMPStream *pAlphaStream = pIE->WMP.wmiSCP_Alpha.pWStream;
  1081. assert(pAlphaStream != pMainStream); // Otherwise we didn't use a temp file
  1082. // Close it up - this causes write to temp file
  1083. Call(PKImageEncode_EncodeAlpha_Term(pIE));
  1084. // Calculate size of alpha bitstream and its new offset
  1085. Call(pAlphaStream->GetPos(pAlphaStream, &cbAlpha));
  1086. // Copy alpha bitstream to end of main stream
  1087. cbBytesCopied = 0;
  1088. Call(pAlphaStream->SetPos(pAlphaStream, 0));
  1089. while (cbBytesCopied < cbAlpha)
  1090. {
  1091. char rgbBuf[TEMPFILE_COPYBUF_SIZE];
  1092. size_t cbCopy;
  1093. cbCopy = min(sizeof(rgbBuf), cbAlpha - cbBytesCopied);
  1094. Call(pAlphaStream->Read(pAlphaStream, rgbBuf, cbCopy));
  1095. Call(pMainStream->Write(pMainStream, rgbBuf, cbCopy));
  1096. cbBytesCopied += cbCopy;
  1097. }
  1098. assert(cbBytesCopied == cbAlpha);
  1099. // Update alpha offset/length for WriteContainerPost
  1100. pIE->WMP.nOffAlpha = (Long)offAlpha;
  1101. pIE->WMP.nCbAlpha = (Long)cbAlpha;
  1102. }
  1103. Call(WriteContainerPost(pIE));
  1104. Cleanup:
  1105. return err;
  1106. }
  1107. ERR PKImageEncode_Transcode_WMP(
  1108. PKImageEncode* pIE,
  1109. PKImageDecode* pID,
  1110. CWMTranscodingParam* pParam)
  1111. {
  1112. ERR err = WMP_errSuccess;
  1113. Float fResX = 0, fResY = 0;
  1114. PKPixelFormatGUID pixGUID = {0};
  1115. CWMTranscodingParam tcParamAlpha;
  1116. size_t offPos = 0;
  1117. Bool fPlanarAlpha;
  1118. PKPixelInfo PI;
  1119. struct WMPStream* pWSDec = NULL;
  1120. struct WMPStream* pWSEnc= pIE->pStream;
  1121. // pass through metadata
  1122. Call(pID->GetPixelFormat(pID, &pixGUID));
  1123. Call(pIE->SetPixelFormat(pIE, pixGUID));
  1124. Call(pIE->SetSize(pIE, (I32)pParam->cWidth, (I32)pParam->cHeight));
  1125. Call(pID->GetResolution(pID, &fResX, &fResY));
  1126. Call(pIE->SetResolution(pIE, fResX, fResY));
  1127. PI.pGUIDPixFmt = &pIE->guidPixFormat;
  1128. PixelFormatLookup(&PI, LOOKUP_FORWARD);
  1129. pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha) && (2 == pParam->uAlphaMode);
  1130. assert(0 == pIE->WMP.bHasAlpha || (pParam->uAlphaMode == 2)); // Decode alpha mode does not match encode alpha mode!
  1131. // Check for any situations where transcoder is being asked to convert alpha - we can't do this
  1132. // NOTE: Decoder's bHasAlpha parameter really means, "has PLANAR alpha"
  1133. PI.pGUIDPixFmt = &pixGUID;
  1134. PixelFormatLookup(&PI, LOOKUP_FORWARD);
  1135. FailIf(0 == (PI.grBit & PK_pixfmtHasAlpha) && pParam->uAlphaMode != 0,
  1136. WMP_errAlphaModeCannotBeTranscoded); // Destination is planar/interleaved, src has no alpha
  1137. FailIf(!!(PI.grBit & PK_pixfmtHasAlpha) && 2 == pParam->uAlphaMode &&
  1138. FALSE == pID->WMP.bHasAlpha, WMP_errAlphaModeCannotBeTranscoded); // Destination is planar, src is interleaved
  1139. FailIf(!!(PI.grBit & PK_pixfmtHasAlpha) && 3 == pParam->uAlphaMode &&
  1140. pID->WMP.bHasAlpha, WMP_errAlphaModeCannotBeTranscoded); // Destination is interleaved, src is planar
  1141. assert(/*pParam->uAlphaMode >= 0 &&*/ pParam->uAlphaMode <= 3); // All the above statements make this assumption
  1142. fPlanarAlpha = pIE->WMP.bHasAlpha && (2 == pParam->uAlphaMode);
  1143. // write matadata
  1144. Call(WriteContainerPre(pIE));
  1145. // Copy transcoding params for alpha (codec changes the struct)
  1146. if (fPlanarAlpha)
  1147. tcParamAlpha = *pParam;
  1148. // write compressed bitstream
  1149. Call(pID->GetRawStream(pID, &pWSDec));
  1150. FailIf(ICERR_OK != WMPhotoTranscode(pWSDec, pWSEnc, pParam), WMP_errFail);
  1151. Call(pIE->pStream->GetPos(pIE->pStream, &offPos));
  1152. pIE->WMP.nCbImage = (Long)offPos - pIE->WMP.nOffImage;
  1153. if (fPlanarAlpha)
  1154. {
  1155. pIE->WMP.nOffAlpha = (Long)offPos;
  1156. // Cue the stream to alpha block
  1157. assert(pID->WMP.wmiDEMisc.uAlphaOffset > 0);
  1158. Call(pWSDec->SetPos(pWSDec, pID->WMP.wmiDEMisc.uAlphaOffset));
  1159. FailIf(ICERR_OK != WMPhotoTranscode(pWSDec, pWSEnc, &tcParamAlpha), WMP_errFail);
  1160. Call(pIE->pStream->GetPos(pIE->pStream, &offPos));
  1161. pIE->WMP.nCbAlpha = (Long)offPos - pIE->WMP.nOffAlpha;
  1162. }
  1163. // fixup matadata
  1164. Call(WriteContainerPost(pIE));
  1165. Cleanup:
  1166. return err;
  1167. }
  1168. ERR PKImageEncode_CreateNewFrame_WMP(
  1169. PKImageEncode* pIE,
  1170. void* pvParam,
  1171. size_t cbParam)
  1172. {
  1173. ERR err = WMP_errSuccess;
  1174. UNREFERENCED_PARAMETER( pIE );
  1175. UNREFERENCED_PARAMETER( pvParam );
  1176. UNREFERENCED_PARAMETER( cbParam );
  1177. Call(WMP_errNotYetImplemented);
  1178. Cleanup:
  1179. return err;
  1180. }
  1181. ERR PKImageEncode_Release_WMP(
  1182. PKImageEncode** ppIE)
  1183. {
  1184. ERR err = WMP_errSuccess;
  1185. PKImageEncode *pIE = *ppIE;
  1186. pIE->pStream->Close(&pIE->pStream);
  1187. PKFree((void **) &pIE->pbColorContext);
  1188. pIE->cbColorContext = 0;
  1189. PKFree((void **) &pIE->pbXMPMetadata);
  1190. pIE->cbXMPMetadataByteCount = 0;
  1191. PKFree((void **) &pIE->pbEXIFMetadata);
  1192. pIE->cbEXIFMetadataByteCount = 0;
  1193. PKFree((void **) &pIE->pbGPSInfoMetadata);
  1194. pIE->cbGPSInfoMetadataByteCount = 0;
  1195. PKFree((void **) &pIE->pbIPTCNAAMetadata);
  1196. pIE->cbIPTCNAAMetadataByteCount = 0;
  1197. PKFree((void **) &pIE->pbPhotoshopMetadata);
  1198. pIE->cbPhotoshopMetadataByteCount = 0;
  1199. // Free descriptive metadata
  1200. FreeDescMetadata(&pIE->sDescMetadata.pvarImageDescription);
  1201. FreeDescMetadata(&pIE->sDescMetadata.pvarCameraMake);
  1202. FreeDescMetadata(&pIE->sDescMetadata.pvarCameraModel);
  1203. FreeDescMetadata(&pIE->sDescMetadata.pvarSoftware);
  1204. FreeDescMetadata(&pIE->sDescMetadata.pvarDateTime);
  1205. FreeDescMetadata(&pIE->sDescMetadata.pvarArtist);
  1206. FreeDescMetadata(&pIE->sDescMetadata.pvarCopyright);
  1207. FreeDescMetadata(&pIE->sDescMetadata.pvarRatingStars);
  1208. FreeDescMetadata(&pIE->sDescMetadata.pvarRatingValue);
  1209. FreeDescMetadata(&pIE->sDescMetadata.pvarCaption);
  1210. FreeDescMetadata(&pIE->sDescMetadata.pvarDocumentName);
  1211. FreeDescMetadata(&pIE->sDescMetadata.pvarPageName);
  1212. FreeDescMetadata(&pIE->sDescMetadata.pvarPageNumber);
  1213. FreeDescMetadata(&pIE->sDescMetadata.pvarHostComputer);
  1214. Call(PKFree((void **) ppIE));
  1215. Cleanup:
  1216. return err;
  1217. }
  1218. //----------------------------------------------------------------
  1219. ERR PKImageEncode_Create_WMP(PKImageEncode** ppIE)
  1220. {
  1221. ERR err = WMP_errSuccess;
  1222. PKImageEncode* pIE = NULL;
  1223. Call(PKImageEncode_Create(ppIE));
  1224. pIE = *ppIE;
  1225. pIE->Initialize = PKImageEncode_Initialize_WMP;
  1226. pIE->Terminate = PKImageEncode_Terminate_WMP;
  1227. pIE->SetColorContext = PKImageEncode_SetColorContext_WMP;
  1228. pIE->SetDescriptiveMetadata = PKImageEncode_SetDescriptiveMetadata_WMP;
  1229. pIE->WritePixels = PKImageEncode_WritePixels_WMP;
  1230. pIE->WritePixelsBandedBegin = PKImageEncode_WritePixelsBandedBegin_WMP;
  1231. pIE->WritePixelsBanded = PKImageEncode_WritePixelsBanded_WMP;
  1232. pIE->WritePixelsBandedEnd = PKImageEncode_WritePixelsBandedEnd_WMP;
  1233. pIE->Transcode = PKImageEncode_Transcode_WMP;
  1234. pIE->CreateNewFrame = PKImageEncode_CreateNewFrame_WMP;
  1235. pIE->Release = PKImageEncode_Release_WMP;
  1236. pIE->bWMP = TRUE;
  1237. Cleanup:
  1238. return err;
  1239. }
  1240. //================================================================
  1241. // PKImageDecode_WMP
  1242. //================================================================
  1243. ERR ParsePFDEntry(
  1244. PKImageDecode* pID,
  1245. U16 uTag,
  1246. U16 uType,
  1247. U32 uCount,
  1248. U32 uValue)
  1249. {
  1250. ERR err = WMP_errSuccess;
  1251. ERR errTmp = WMP_errSuccess;
  1252. PKPixelInfo PI;
  1253. struct WMPStream* pWS = pID->pStream;
  1254. // size_t offPos = 0;
  1255. union uf{
  1256. U32 uVal;
  1257. Float fVal;
  1258. }ufValue = {0};
  1259. //================================
  1260. switch (uTag)
  1261. {
  1262. case WMP_tagPixelFormat:
  1263. {
  1264. unsigned char *pGuid = (unsigned char *) &pID->guidPixFormat;
  1265. /** following code is endian-agnostic **/
  1266. Call(GetULong(pWS, uValue, (U32 *)pGuid));
  1267. Call(GetUShort(pWS, uValue + 4, (unsigned short *)(pGuid + 4)));
  1268. Call(GetUShort(pWS, uValue + 6, (unsigned short *)(pGuid + 6)));
  1269. Call(pWS->Read(pWS, pGuid + 8, 8));
  1270. PI.pGUIDPixFmt = &pID->guidPixFormat;
  1271. PixelFormatLookup(&PI, LOOKUP_FORWARD);
  1272. pID->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha);
  1273. pID->WMP.wmiI.cBitsPerUnit = PI.cbitUnit;
  1274. pID->WMP.wmiI.bRGB = !(PI.grBit & PK_pixfmtBGR);
  1275. break;
  1276. }
  1277. case WMP_tagTransformation:
  1278. FailIf(1 != uCount, WMP_errUnsupportedFormat);
  1279. assert(uValue < O_MAX);
  1280. pID->WMP.fOrientationFromContainer = TRUE;
  1281. pID->WMP.oOrientationFromContainer = uValue;
  1282. break;
  1283. case WMP_tagImageWidth:
  1284. FailIf(0 == uValue, WMP_errUnsupportedFormat);
  1285. break;
  1286. case WMP_tagImageHeight:
  1287. FailIf(0 == uValue, WMP_errUnsupportedFormat);
  1288. break;
  1289. case WMP_tagImageOffset:
  1290. FailIf(1 != uCount, WMP_errUnsupportedFormat);
  1291. pID->WMP.wmiDEMisc.uImageOffset = uValue;
  1292. break;
  1293. case WMP_tagImageByteCount:
  1294. FailIf(1 != uCount, WMP_errUnsupportedFormat);
  1295. pID->WMP.wmiDEMisc.uImageByteCount = uValue;
  1296. break;
  1297. case WMP_tagAlphaOffset:
  1298. FailIf(1 != uCount, WMP_errUnsupportedFormat);
  1299. pID->WMP.wmiDEMisc.uAlphaOffset = uValue;
  1300. break;
  1301. case WMP_tagAlphaByteCount:
  1302. FailIf(1 != uCount, WMP_errUnsupportedFormat);
  1303. pID->WMP.wmiDEMisc.uAlphaByteCount = uValue;
  1304. break;
  1305. case WMP_tagWidthResolution:
  1306. FailIf(1 != uCount, WMP_errUnsupportedFormat);
  1307. ufValue.uVal = uValue;
  1308. pID->fResX = ufValue.fVal;
  1309. break;
  1310. case WMP_tagHeightResolution:
  1311. FailIf(1 != uCount, WMP_errUnsupportedFormat);
  1312. ufValue.uVal = uValue;
  1313. pID->fResY = ufValue.fVal;
  1314. break;
  1315. case WMP_tagIccProfile:
  1316. pID->WMP.wmiDEMisc.uColorProfileByteCount = uCount;
  1317. pID->WMP.wmiDEMisc.uColorProfileOffset = uValue;
  1318. break;
  1319. case WMP_tagXMPMetadata:
  1320. pID->WMP.wmiDEMisc.uXMPMetadataByteCount = uCount;
  1321. pID->WMP.wmiDEMisc.uXMPMetadataOffset = uValue;
  1322. break;
  1323. case WMP_tagEXIFMetadata:
  1324. pID->WMP.wmiDEMisc.uEXIFMetadataOffset = uValue;
  1325. CallIgnoreError(errTmp, StreamCalcIFDSize(pWS, uValue, &pID->WMP.wmiDEMisc.uEXIFMetadataByteCount));
  1326. break;
  1327. case WMP_tagGPSInfoMetadata:
  1328. pID->WMP.wmiDEMisc.uGPSInfoMetadataOffset = uValue;
  1329. CallIgnoreError(errTmp, StreamCalcIFDSize(pWS, uValue, &pID->WMP.wmiDEMisc.uGPSInfoMetadataByteCount));
  1330. break;
  1331. case WMP_tagIPTCNAAMetadata:
  1332. pID->WMP.wmiDEMisc.uIPTCNAAMetadataByteCount = uCount;
  1333. pID->WMP.wmiDEMisc.uIPTCNAAMetadataOffset = uValue;
  1334. break;
  1335. case WMP_tagPhotoshopMetadata:
  1336. pID->WMP.wmiDEMisc.uPhotoshopMetadataByteCount = uCount;
  1337. pID->WMP.wmiDEMisc.uPhotoshopMetadataOffset = uValue;
  1338. break;
  1339. case WMP_tagCompression:
  1340. case WMP_tagImageType:
  1341. case WMP_tagImageDataDiscard:
  1342. case WMP_tagAlphaDataDiscard:
  1343. break;
  1344. // Descriptive Metadata
  1345. case WMP_tagImageDescription:
  1346. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1347. &pID->WMP.sDescMetadata.pvarImageDescription));
  1348. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarImageDescription.vt);
  1349. break;
  1350. case WMP_tagCameraMake:
  1351. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1352. &pID->WMP.sDescMetadata.pvarCameraMake));
  1353. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarCameraMake.vt);
  1354. break;
  1355. case WMP_tagCameraModel:
  1356. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1357. &pID->WMP.sDescMetadata.pvarCameraModel));
  1358. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarCameraModel.vt);
  1359. break;
  1360. case WMP_tagSoftware:
  1361. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1362. &pID->WMP.sDescMetadata.pvarSoftware));
  1363. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarSoftware.vt);
  1364. break;
  1365. case WMP_tagDateTime:
  1366. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1367. &pID->WMP.sDescMetadata.pvarDateTime));
  1368. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarDateTime.vt);
  1369. break;
  1370. case WMP_tagArtist:
  1371. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1372. &pID->WMP.sDescMetadata.pvarArtist));
  1373. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarArtist.vt);
  1374. break;
  1375. case WMP_tagCopyright:
  1376. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1377. &pID->WMP.sDescMetadata.pvarCopyright));
  1378. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarCopyright.vt);
  1379. break;
  1380. case WMP_tagRatingStars:
  1381. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1382. &pID->WMP.sDescMetadata.pvarRatingStars));
  1383. assert(DPKVT_UI2 == pID->WMP.sDescMetadata.pvarRatingStars.vt);
  1384. break;
  1385. case WMP_tagRatingValue:
  1386. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1387. &pID->WMP.sDescMetadata.pvarRatingValue));
  1388. assert(DPKVT_UI2 == pID->WMP.sDescMetadata.pvarRatingValue.vt);
  1389. break;
  1390. case WMP_tagCaption:
  1391. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1392. &pID->WMP.sDescMetadata.pvarCaption));
  1393. assert((DPKVT_BYREF | DPKVT_UI1) == pID->WMP.sDescMetadata.pvarCaption.vt);
  1394. // Change type from C-style byte array to LPWSTR
  1395. assert((U8*)pID->WMP.sDescMetadata.pvarCaption.VT.pwszVal ==
  1396. pID->WMP.sDescMetadata.pvarCaption.VT.pbVal);
  1397. assert(0 == pID->WMP.sDescMetadata.pvarCaption.VT.pwszVal[uCount/sizeof(U16) - 1]); // Confirm null-term
  1398. // make sure null term (ReadPropvar allocated enough space for this)
  1399. pID->WMP.sDescMetadata.pvarCaption.VT.pwszVal[uCount/sizeof(U16)] = 0;
  1400. pID->WMP.sDescMetadata.pvarCaption.vt = DPKVT_LPWSTR;
  1401. break;
  1402. case WMP_tagDocumentName:
  1403. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1404. &pID->WMP.sDescMetadata.pvarDocumentName));
  1405. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarDocumentName.vt);
  1406. break;
  1407. case WMP_tagPageName:
  1408. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1409. &pID->WMP.sDescMetadata.pvarPageName));
  1410. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarPageName.vt);
  1411. break;
  1412. case WMP_tagPageNumber:
  1413. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1414. &pID->WMP.sDescMetadata.pvarPageNumber));
  1415. assert(DPKVT_UI4 == pID->WMP.sDescMetadata.pvarPageNumber.vt);
  1416. break;
  1417. case WMP_tagHostComputer:
  1418. CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue,
  1419. &pID->WMP.sDescMetadata.pvarHostComputer));
  1420. assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarHostComputer.vt);
  1421. break;
  1422. default:
  1423. fprintf(stderr, "Unrecognized WMPTag: %d(%#x), %d, %d, %#x" CRLF,
  1424. (int)uTag, (int)uTag, (int)uType, (int)uCount, (int)uValue);
  1425. break;
  1426. }
  1427. Cleanup:
  1428. return err;
  1429. }
  1430. ERR ParsePFD(
  1431. PKImageDecode* pID,
  1432. size_t offPos,
  1433. U16 cEntry)
  1434. {
  1435. ERR err = WMP_errSuccess;
  1436. struct WMPStream* pWS = pID->pStream;
  1437. U16 i = 0;
  1438. for (i = 0; i < cEntry; ++i)
  1439. {
  1440. U16 uTag = 0;
  1441. U16 uType = 0;
  1442. U32 uCount = 0;
  1443. U32 uValue = 0;
  1444. Call(GetUShort(pWS, offPos, &uTag)); offPos += 2;
  1445. Call(GetUShort(pWS, offPos, &uType)); offPos += 2;
  1446. Call(GetULong(pWS, offPos, &uCount)); offPos += 4;
  1447. Call(GetULong(pWS, offPos, &uValue)); offPos += 4;
  1448. Call(ParsePFDEntry(pID, uTag, uType, uCount, uValue));
  1449. }
  1450. pID->WMP.bHasAlpha = ((pID->WMP.bHasAlpha) && (pID->WMP.wmiDEMisc.uAlphaOffset != 0) && (pID->WMP.wmiDEMisc.uAlphaByteCount != 0));//has planar alpha
  1451. Cleanup:
  1452. return err;
  1453. }
  1454. ERR ReadContainer(
  1455. PKImageDecode* pID)
  1456. {
  1457. ERR err = WMP_errSuccess;
  1458. struct WMPStream* pWS = pID->pStream;
  1459. size_t offPos = 0;
  1460. char szSig[2] = {0};
  1461. U16 uWmpID = 0;
  1462. U32 offPFD = 0;
  1463. U16 cPFDEntry = 0;
  1464. U8 bVersion;
  1465. //================================
  1466. Call(pWS->GetPos(pWS, &offPos));
  1467. FailIf(0 != offPos, WMP_errUnsupportedFormat);
  1468. //================================
  1469. // Header
  1470. Call(pWS->Read(pWS, szSig, sizeof(szSig))); offPos += 2;
  1471. FailIf(szSig != strstr(szSig, "II"), WMP_errUnsupportedFormat);
  1472. Call(GetUShort(pWS, offPos, &uWmpID)); offPos += 2;
  1473. FailIf(WMP_valWMPhotoID != (0x00FF & uWmpID), WMP_errUnsupportedFormat);
  1474. // We accept version 00 and version 01 bitstreams - all others rejected
  1475. bVersion = (0xFF00 & uWmpID) >> 8;
  1476. FailIf(bVersion != 0 && bVersion != 1, WMP_errUnsupportedFormat);
  1477. Call(GetULong(pWS, offPos, &offPFD)); offPos += 4;
  1478. //================================
  1479. // PFD
  1480. offPos = (size_t)offPFD;
  1481. Call(GetUShort(pWS, offPos, &cPFDEntry)); offPos += 2;
  1482. FailIf(0 == cPFDEntry || USHRT_MAX == cPFDEntry, WMP_errUnsupportedFormat);
  1483. Call(ParsePFD(pID, offPos, cPFDEntry));
  1484. //================================
  1485. Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uImageOffset));
  1486. Cleanup:
  1487. return err;
  1488. }
  1489. //================================================
  1490. ERR PKImageDecode_Initialize_WMP(
  1491. PKImageDecode* pID,
  1492. struct WMPStream* pWS)
  1493. {
  1494. ERR err = WMP_errSuccess;
  1495. CWMImageInfo* pII = NULL;
  1496. //================================
  1497. Call(PKImageDecode_Initialize(pID, pWS));
  1498. //================================
  1499. Call(ReadContainer(pID));
  1500. //================================
  1501. pID->WMP.wmiSCP.pWStream = pWS;
  1502. pID->WMP.DecoderCurrMBRow = 0;
  1503. pID->WMP.cLinesDecoded = 0;
  1504. pID->WMP.cLinesCropped = 0;
  1505. pID->WMP.fFirstNonZeroDecode = FALSE;
  1506. FailIf(ICERR_OK != ImageStrDecGetInfo(&pID->WMP.wmiI, &pID->WMP.wmiSCP), WMP_errFail);
  1507. assert(Y_ONLY <= pID->WMP.wmiSCP.cfColorFormat && pID->WMP.wmiSCP.cfColorFormat < CFT_MAX);
  1508. assert(BD_SHORT == pID->WMP.wmiSCP.bdBitDepth || BD_LONG == pID->WMP.wmiSCP.bdBitDepth);
  1509. // If HD Photo container provided an orientation, this should override bitstream orientation
  1510. // If container did NOT provide an orientation, force O_NONE. This is to be consistent with
  1511. // Vista behaviour, which is to ignore bitstream orientation (only looks at container).
  1512. if (pID->WMP.fOrientationFromContainer)
  1513. {
  1514. pID->WMP.wmiI.oOrientation = pID->WMP.oOrientationFromContainer;
  1515. }
  1516. else
  1517. {
  1518. // Force to O_NONE to match Vista decode behaviour
  1519. pID->WMP.wmiI.oOrientation = O_NONE;
  1520. }
  1521. pII = &pID->WMP.wmiI;
  1522. pID->uWidth = (U32)pII->cWidth;
  1523. pID->uHeight = (U32)pII->cHeight;
  1524. Cleanup:
  1525. return err;
  1526. }
  1527. ERR PKImageDecode_GetSize_WMP(
  1528. PKImageDecode* pID,
  1529. I32* piWidth,
  1530. I32* piHeight)
  1531. {
  1532. if (pID->WMP.wmiI.oOrientation >= O_RCW)
  1533. {
  1534. *piWidth = (I32)pID->uHeight;
  1535. *piHeight = (I32)pID->uWidth;
  1536. }
  1537. else
  1538. {
  1539. *piWidth = (I32)pID->uWidth;
  1540. *piHeight = (I32)pID->uHeight;
  1541. }
  1542. return WMP_errSuccess;
  1543. }
  1544. ERR PKImageDecode_GetRawStream_WMP(
  1545. PKImageDecode* pID,
  1546. struct WMPStream** ppWS)
  1547. {
  1548. ERR err = WMP_errSuccess;
  1549. struct WMPStream* pWS = pID->pStream;
  1550. *ppWS = NULL;
  1551. Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uImageOffset));
  1552. *ppWS = pWS;
  1553. Cleanup:
  1554. return err;
  1555. }
  1556. ERR PKImageDecode_Copy_WMP(
  1557. PKImageDecode* pID,
  1558. const PKRect* pRect,
  1559. U8* pb,
  1560. U32 cbStride)
  1561. {
  1562. ERR err = WMP_errSuccess;
  1563. U32 cThumbnailScale;
  1564. U32 linesperMBRow;
  1565. CWMImageBufferInfo wmiBI = { 0 };
  1566. #ifdef REENTRANT_MODE
  1567. U8 *pbLowMemAdj = NULL;
  1568. U32 i, cMBRow;
  1569. U32 cMBRowStart;
  1570. #endif // REENTRANT_MODE
  1571. struct WMPStream* pWS = pID->pStream;
  1572. U8 tempAlphaMode = 0;
  1573. wmiBI.pv = pb;
  1574. wmiBI.cLine = pRect->Height;
  1575. wmiBI.cbStride = cbStride;
  1576. #ifdef REENTRANT_MODE
  1577. // In REENTRANT_MODE, we allow rectangles with any top left corner (not just (0,0))
  1578. #else
  1579. FailIf(0 != pRect->X, WMP_errInvalidParameter);
  1580. FailIf(0 != pRect->Y, WMP_errInvalidParameter);
  1581. #endif // REENTRANT_MODE
  1582. cThumbnailScale = 1;
  1583. if (pID->WMP.wmiI.cThumbnailWidth > 0)
  1584. {
  1585. while(cThumbnailScale * pID->WMP.wmiI.cThumbnailWidth < pID->uWidth)
  1586. cThumbnailScale <<= 1;
  1587. }
  1588. // note the following implementation can't handle fractional linesperMBRow limiting
  1589. // us to >= 1/256 thumbnail which is unfortunate, but all the PS plugin needs is 1/256
  1590. // and I didn't care to get into floating point or a bunch of conditional tests or
  1591. // other rewrite for a case not needed nor tested by PS plugin. sorry.
  1592. linesperMBRow = 16 / cThumbnailScale;
  1593. #ifdef REENTRANT_MODE
  1594. if (0 == pID->WMP.DecoderCurrMBRow)
  1595. {
  1596. #endif // REENTRANT_MODE
  1597. // Set the fPaddedUserBuffer if the following conditions are met
  1598. if (0 == ((size_t)pb % 128) && // Frame buffer is aligned to 128-byte boundary
  1599. 0 == (pRect->Height % 16) && // Horizontal resolution is multiple of 16
  1600. 0 == (pRect->Width % 16) && // Vertical resolution is multiple of 16
  1601. 0 == (cbStride % 128)) // Stride is a multiple of 128 bytes
  1602. {
  1603. pID->WMP.wmiI.fPaddedUserBuffer = TRUE;
  1604. // Note that there are additional conditions in strdec_x86.c's strDecOpt
  1605. // which could prevent optimization from being engaged
  1606. }
  1607. #ifdef REENTRANT_MODE
  1608. }
  1609. #endif // REENTRANT_MODE
  1610. //if(pID->WMP.wmiSCP.uAlphaMode != 1)
  1611. if((!pID->WMP.bHasAlpha) || (pID->WMP.wmiSCP.uAlphaMode != 1))
  1612. {
  1613. if(pID->WMP.bHasAlpha)//planar alpha
  1614. {
  1615. tempAlphaMode = pID->WMP.wmiSCP.uAlphaMode;
  1616. pID->WMP.wmiSCP.uAlphaMode = 0;
  1617. }
  1618. pID->WMP.wmiSCP.fMeasurePerf = TRUE;
  1619. #ifdef REENTRANT_MODE
  1620. if (0 == pID->WMP.DecoderCurrMBRow)
  1621. {
  1622. Call(pID->WMP.wmiSCP.pWStream->GetPos(pID->WMP.wmiSCP.pWStream, &(pID->WMP.cMarker)));
  1623. FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail);
  1624. }
  1625. // Re-entrant mode incurs 1 MBR delay, so to get 0th MBR, we have to ask for 1st MBR
  1626. cMBRow = ((U32) pID->WMP.cLinesCropped + pRect->Y + pRect->Height +
  1627. (pRect->Y + pRect->Height >= (I32) pID->WMP.wmiI.cROIHeight ? linesperMBRow - 1 : 0)) / // round up if last MBR
  1628. linesperMBRow + 1;
  1629. cMBRowStart = ((U32) pID->WMP.cLinesCropped + pRect->Y) / linesperMBRow + 1;
  1630. // if current request starts before current state, then rewind.
  1631. if (cMBRowStart < pID->WMP.DecoderCurrMBRow)
  1632. {
  1633. pID->WMP.DecoderCurrMBRow = 0;
  1634. pID->WMP.cLinesDecoded = 0;
  1635. pID->WMP.cLinesCropped = 0;
  1636. pID->WMP.fFirstNonZeroDecode = FALSE;
  1637. FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail);
  1638. Call(pID->WMP.wmiSCP.pWStream->SetPos(pID->WMP.wmiSCP.pWStream, pID->WMP.cMarker));
  1639. FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail);
  1640. }
  1641. // In "Low Memory mode", we don't have full frame buffer. We therefore cannot rotate the image.
  1642. // We can flip H, V and HV, but no rotations.
  1643. FailIf(pID->WMP.wmiI.oOrientation >= O_RCW, WMP_errFail);
  1644. // In low-memory mode, the full frame buffer is unavailable. This doesn't seem to
  1645. // matter in O_NONE and O_FLIPH, but for O_FLIPV and O_FLIPVH, outputMBRow tries to write to
  1646. // the bottom of full-frame buffer. Adjust the buffer pointer to compensate.
  1647. if (O_FLIPV == pID->WMP.wmiI.oOrientation || O_FLIPVH == pID->WMP.wmiI.oOrientation)
  1648. {
  1649. I32 iActualY2 = pRect->Y + pRect->Height;
  1650. pbLowMemAdj = pb - (pID->WMP.wmiI.cROIHeight - (iActualY2 - pID->WMP.cLinesCropped)) * cbStride;
  1651. }
  1652. else
  1653. {
  1654. pbLowMemAdj = pb - pRect->Y * cbStride;
  1655. }
  1656. wmiBI.pv = pbLowMemAdj;
  1657. for (i = (U32)pID->WMP.DecoderCurrMBRow; i < cMBRow; i++)
  1658. {
  1659. size_t cLinesDecoded;
  1660. wmiBI.uiFirstMBRow = i;
  1661. wmiBI.uiLastMBRow = i;
  1662. FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC, &wmiBI, &cLinesDecoded), WMP_errFail);
  1663. pID->WMP.cLinesDecoded = cLinesDecoded;
  1664. if (FALSE == pID->WMP.fFirstNonZeroDecode && cLinesDecoded > 0)
  1665. {
  1666. pID->WMP.cLinesCropped += (linesperMBRow - cLinesDecoded);
  1667. pID->WMP.fFirstNonZeroDecode = TRUE;
  1668. // update cMBRow if partial MB row cropped
  1669. cMBRow = ((U32) pID->WMP.cLinesCropped + pRect->Y + pRect->Height +
  1670. (pRect->Y + pRect->Height >= (I32) pID->WMP.wmiI.cROIHeight ? linesperMBRow - 1 : 0)) / // round up if last MBR
  1671. linesperMBRow + 1;
  1672. }
  1673. if (0 == cLinesDecoded && i > 0)
  1674. {
  1675. pID->WMP.cLinesCropped += linesperMBRow;
  1676. // update cMBRow if whole MB row cropped
  1677. cMBRow++;
  1678. }
  1679. }
  1680. wmiBI.pv = pbLowMemAdj;
  1681. // If we're past the top of the image, then we're done, so terminate.
  1682. if (linesperMBRow * (cMBRow - 1) >= (U32) pID->WMP.cLinesCropped + pID->WMP.wmiI.cROIHeight) {
  1683. FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail);
  1684. }
  1685. pID->WMP.DecoderCurrMBRow = cMBRow; // Set to next possible MBRow that is decodable
  1686. #else
  1687. FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail);
  1688. FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC, &wmiBI), WMP_errFail);
  1689. FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail);
  1690. #endif //REENTRANT_MODE
  1691. if(pID->WMP.bHasAlpha)//planar alpha
  1692. {
  1693. pID->WMP.wmiSCP.uAlphaMode = tempAlphaMode;
  1694. }
  1695. }
  1696. // if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode == 2)
  1697. // if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode != 1)
  1698. if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode != 0)
  1699. {
  1700. pID->WMP.wmiI_Alpha = pID->WMP.wmiI;
  1701. pID->WMP.wmiSCP_Alpha = pID->WMP.wmiSCP;
  1702. // assert(pID->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now!
  1703. pID->WMP.wmiI_Alpha.cfColorFormat = Y_ONLY;
  1704. switch (pID->WMP.wmiI.bdBitDepth)
  1705. {
  1706. case BD_8:
  1707. pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) - 1;
  1708. break;
  1709. case BD_16:
  1710. case BD_16S:
  1711. case BD_16F:
  1712. pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(U16) - 1;
  1713. break;
  1714. case BD_32:
  1715. case BD_32S:
  1716. case BD_32F:
  1717. pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(float) - 1;
  1718. break;
  1719. case BD_5:
  1720. case BD_10:
  1721. case BD_565:
  1722. default:
  1723. break;
  1724. }
  1725. pID->WMP.wmiSCP_Alpha.fMeasurePerf = TRUE;
  1726. Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uAlphaOffset));
  1727. #ifdef REENTRANT_MODE
  1728. if (0 == pID->WMP.DecoderCurrAlphaMBRow) // add this to WMP struct!
  1729. {
  1730. FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail);
  1731. }
  1732. // Re-entrant mode incurs 1 MBR delay, so to get 0th MBR, we have to ask for 1st MBR
  1733. cMBRow = ((U32) pID->WMP.cLinesCropped + pRect->Y + pRect->Height +
  1734. (pRect->Y + pRect->Height >= (I32) pID->WMP.wmiI.cROIHeight ? linesperMBRow - 1 : 0)) / // round up if last MBR
  1735. linesperMBRow + 1;
  1736. cMBRowStart = ((U32) pID->WMP.cLinesCropped + pRect->Y) / linesperMBRow + 1;
  1737. // if current request starts before current state, then rewind.
  1738. if (cMBRowStart < pID->WMP.DecoderCurrAlphaMBRow)
  1739. {
  1740. pID->WMP.DecoderCurrAlphaMBRow = 0;
  1741. FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail);
  1742. FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail);
  1743. }
  1744. for (i = (U32)pID->WMP.DecoderCurrAlphaMBRow; i < cMBRow; i++)
  1745. {
  1746. size_t cLinesDecoded;
  1747. wmiBI.uiFirstMBRow = i;
  1748. wmiBI.uiLastMBRow = i;
  1749. FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC_Alpha, &wmiBI, &cLinesDecoded), WMP_errFail);
  1750. }
  1751. // If we're past the top of the image, then we're done, so terminate
  1752. if (linesperMBRow * (cMBRow - 1) >= (U32) pID->WMP.cLinesCropped + pID->WMP.wmiI.cROIHeight) {
  1753. FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail);
  1754. }
  1755. pID->WMP.DecoderCurrAlphaMBRow = cMBRow; // Set to next possible MBRow that is decodable
  1756. wmiBI.pv = pb;
  1757. #else
  1758. FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail);
  1759. FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC_Alpha, &wmiBI), WMP_errFail);
  1760. FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail);
  1761. #endif //REENTRANT_MODE
  1762. }
  1763. pID->idxCurrentLine += pRect->Height;
  1764. Cleanup:
  1765. return err;
  1766. }
  1767. ERR PKImageDecode_GetMetadata_WMP(PKImageDecode *pID, U32 uOffset, U32 uByteCount, U8 *pbGot, U32 *pcbGot)
  1768. {
  1769. ERR err = WMP_errSuccess;
  1770. if (pbGot && uOffset)
  1771. {
  1772. struct WMPStream* pWS = pID->pStream;
  1773. size_t iCurrPos;
  1774. FailIf(*pcbGot < uByteCount, WMP_errBufferOverflow);
  1775. Call(pWS->GetPos(pWS, &iCurrPos));
  1776. Call(pWS->SetPos(pWS, uOffset));
  1777. Call(pWS->Read(pWS, pbGot, uByteCount));
  1778. Call(pWS->SetPos(pWS, iCurrPos));
  1779. }
  1780. Cleanup:
  1781. if (Failed(err))
  1782. *pcbGot = 0;
  1783. else
  1784. *pcbGot = uByteCount;
  1785. return err;
  1786. }
  1787. ERR PKImageDecode_GetColorContext_WMP(PKImageDecode *pID, U8 *pbColorContext, U32 *pcbColorContext)
  1788. {
  1789. return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uColorProfileOffset,
  1790. pID->WMP.wmiDEMisc.uColorProfileByteCount, pbColorContext, pcbColorContext);
  1791. }
  1792. ERR PKImageDecode_GetXMPMetadata_WMP(PKImageDecode *pID, U8 *pbXMPMetadata, U32 *pcbXMPMetadata)
  1793. {
  1794. return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uXMPMetadataOffset,
  1795. pID->WMP.wmiDEMisc.uXMPMetadataByteCount, pbXMPMetadata, pcbXMPMetadata);
  1796. }
  1797. ERR PKImageDecode_GetEXIFMetadata_WMP(PKImageDecode *pID, U8 *pbEXIFMetadata, U32 *pcbEXIFMetadata)
  1798. {
  1799. return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uEXIFMetadataOffset,
  1800. pID->WMP.wmiDEMisc.uEXIFMetadataByteCount, pbEXIFMetadata, pcbEXIFMetadata);
  1801. }
  1802. ERR PKImageDecode_GetGPSInfoMetadata_WMP(PKImageDecode *pID, U8 *pbGPSInfoMetadata, U32 *pcbGPSInfoMetadata)
  1803. {
  1804. return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uGPSInfoMetadataOffset,
  1805. pID->WMP.wmiDEMisc.uGPSInfoMetadataByteCount, pbGPSInfoMetadata, pcbGPSInfoMetadata);
  1806. }
  1807. ERR PKImageDecode_GetIPTCNAAMetadata_WMP(PKImageDecode *pID, U8 *pbIPTCNAAMetadata, U32 *pcbIPTCNAAMetadata)
  1808. {
  1809. return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uIPTCNAAMetadataOffset,
  1810. pID->WMP.wmiDEMisc.uIPTCNAAMetadataByteCount, pbIPTCNAAMetadata, pcbIPTCNAAMetadata);
  1811. }
  1812. ERR PKImageDecode_GetPhotoshopMetadata_WMP(PKImageDecode *pID, U8 *pbPhotoshopMetadata, U32 *pcbPhotoshopMetadata)
  1813. {
  1814. return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uPhotoshopMetadataOffset,
  1815. pID->WMP.wmiDEMisc.uPhotoshopMetadataByteCount, pbPhotoshopMetadata, pcbPhotoshopMetadata);
  1816. }
  1817. ERR PKImageDecode_GetDescriptiveMetadata_WMP(PKImageDecode *pID, DESCRIPTIVEMETADATA *pDescMetadata)
  1818. {
  1819. ERR err = WMP_errSuccess;
  1820. *pDescMetadata = pID->WMP.sDescMetadata;
  1821. return err;
  1822. }
  1823. ERR PKImageDecode_Release_WMP(PKImageDecode** ppID)
  1824. {
  1825. ERR err = WMP_errSuccess;
  1826. PKImageDecode *pID;
  1827. if (NULL == ppID)
  1828. goto Cleanup;
  1829. pID = *ppID;
  1830. // Free descriptive metadata
  1831. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarImageDescription);
  1832. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCameraMake);
  1833. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCameraModel);
  1834. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarSoftware);
  1835. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarDateTime);
  1836. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarArtist);
  1837. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCopyright);
  1838. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarRatingStars);
  1839. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarRatingValue);
  1840. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCaption);
  1841. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarDocumentName);
  1842. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarPageName);
  1843. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarPageNumber);
  1844. FreeDescMetadata(&pID->WMP.sDescMetadata.pvarHostComputer);
  1845. // Release base class
  1846. Call(PKImageDecode_Release(ppID));
  1847. Cleanup:
  1848. return err;
  1849. }
  1850. ERR PKImageDecode_Create_WMP(PKImageDecode** ppID)
  1851. {
  1852. ERR err = WMP_errSuccess;
  1853. PKImageDecode* pID = NULL;
  1854. Call(PKImageDecode_Create(ppID));
  1855. pID = *ppID;
  1856. pID->Initialize = PKImageDecode_Initialize_WMP;
  1857. pID->GetSize = PKImageDecode_GetSize_WMP;
  1858. pID->GetRawStream = PKImageDecode_GetRawStream_WMP;
  1859. pID->Copy = PKImageDecode_Copy_WMP;
  1860. pID->GetColorContext = PKImageDecode_GetColorContext_WMP;
  1861. pID->GetDescriptiveMetadata = PKImageDecode_GetDescriptiveMetadata_WMP;
  1862. pID->Release = PKImageDecode_Release_WMP;
  1863. Cleanup:
  1864. return err;
  1865. }