JXRGlue.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  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 <stdlib.h>
  29. #include <ctype.h>
  30. #define INITGUID
  31. #include <JXRGlue.h>
  32. //================================================================
  33. const PKIID IID_PKImageScanEncode = 1;
  34. const PKIID IID_PKImageFrameEncode = 2;
  35. const PKIID IID_PKImageUnsupported = 100;
  36. const PKIID IID_PKImageWmpEncode = 101;
  37. const PKIID IID_PKImageWmpDecode = 201;
  38. //================================================================
  39. // Misc supporting functions
  40. //================================================================
  41. ERR PKAlloc(void** ppv, size_t cb)
  42. {
  43. *ppv = calloc(1, cb);
  44. return *ppv ? WMP_errSuccess : WMP_errOutOfMemory;
  45. }
  46. ERR PKFree(void** ppv)
  47. {
  48. if (ppv)
  49. {
  50. free(*ppv);
  51. *ppv = NULL;
  52. }
  53. return WMP_errSuccess;
  54. }
  55. ERR PKAllocAligned(void** ppv, size_t cb, size_t iAlign)
  56. {
  57. U8 *pOrigPtr;
  58. U8 *pReturnedPtr;
  59. size_t iAlignmentCorrection;
  60. const size_t c_cbBlockSize = cb + sizeof(void*) + iAlign - 1;
  61. *ppv = NULL;
  62. pOrigPtr = calloc(1, c_cbBlockSize);
  63. if (NULL == pOrigPtr)
  64. return WMP_errOutOfMemory;
  65. iAlignmentCorrection = iAlign - ((size_t)pOrigPtr % iAlign);
  66. if (iAlignmentCorrection < sizeof(void*))
  67. // Alignment correction won't leave us enough space to store pOrigPtr - advance to next block
  68. iAlignmentCorrection += iAlign;
  69. assert(iAlignmentCorrection >= sizeof(void*)); // Alignment correction must have space for pOrigPtr
  70. assert(iAlignmentCorrection + cb <= c_cbBlockSize); // Don't exceed right edge of memory block
  71. pReturnedPtr = pOrigPtr + iAlignmentCorrection;
  72. *(void**)(pReturnedPtr - sizeof(void*)) = pOrigPtr;
  73. assert(0 == ((size_t)pReturnedPtr % iAlign)); // Are we in fact aligned?
  74. *ppv = pReturnedPtr;
  75. return WMP_errSuccess;
  76. }
  77. ERR PKFreeAligned(void** ppv)
  78. {
  79. if (ppv && *ppv)
  80. {
  81. U8 **ppOrigPtr = (U8**)((U8*)(*ppv) - sizeof(void*));
  82. assert(*ppOrigPtr <= (U8*)ppOrigPtr); // Something's wrong if pOrigPtr points forward
  83. free(*ppOrigPtr);
  84. *ppv = NULL;
  85. }
  86. return WMP_errSuccess;
  87. }
  88. int PKStrnicmp(const char* s1, const char* s2, size_t c)
  89. {
  90. for(; tolower(*s1) == tolower(*s2) && *s1 && *s2 && c; ++s1, ++s2, --c);
  91. return c ? *s1 - *s2 : 0;
  92. }
  93. static const PKPixelInfo pixelInfo[] =
  94. {
  95. {&GUID_PKPixelFormatDontCare, 1, Y_ONLY, BD_8, 8, PK_pixfmtNul, 0, 0, 0, 0},
  96. // Gray
  97. //{&GUID_PKPixelFormat2bppGray, 1, Y_ONLY, BD_8, 2, PK_pixfmtNul},
  98. //{&GUID_PKPixelFormat4bppGray, 1, Y_ONLY, BD_8, 4, PK_pixfmtNul},
  99. {&GUID_PKPixelFormatBlackWhite, 1, Y_ONLY, BD_1, 1, PK_pixfmtNul, 1, 1, 1, 1},//BlackIsZero is default for GUID_PKPixelFormatBlackWhite
  100. {&GUID_PKPixelFormatBlackWhite, 1, Y_ONLY, BD_1, 1, PK_pixfmtNul, 0, 1, 1, 1},//WhiteIsZero
  101. {&GUID_PKPixelFormat8bppGray, 1, Y_ONLY, BD_8, 8, PK_pixfmtNul, 1, 1, 8, 1},
  102. {&GUID_PKPixelFormat16bppGray, 1, Y_ONLY, BD_16, 16, PK_pixfmtNul, 1, 1, 16, 1},
  103. {&GUID_PKPixelFormat16bppGrayFixedPoint, 1, Y_ONLY, BD_16S, 16, PK_pixfmtNul, 1, 1, 16, 2},
  104. {&GUID_PKPixelFormat16bppGrayHalf, 1, Y_ONLY, BD_16F, 16, PK_pixfmtNul, 1, 1, 16, 3},
  105. //{&GUID_PKPixelFormat32bppGray, 1, Y_ONLY, BD_32, 32, PK_pixfmtNul, 1, 1, 32, 1},
  106. {&GUID_PKPixelFormat32bppGrayFixedPoint, 1, Y_ONLY, BD_32S, 32, PK_pixfmtNul, 1, 1, 32, 2},
  107. {&GUID_PKPixelFormat32bppGrayFloat, 1, Y_ONLY, BD_32F, 32, PK_pixfmtNul, 1, 1, 32, 3},
  108. // RGB
  109. {&GUID_PKPixelFormat24bppRGB, 3, CF_RGB, BD_8, 24, PK_pixfmtNul, 2, 3, 8, 1},
  110. {&GUID_PKPixelFormat24bppBGR, 3, CF_RGB, BD_8, 24, PK_pixfmtBGR, 2, 3, 8, 1},
  111. {&GUID_PKPixelFormat32bppRGB, 3, CF_RGB, BD_8, 32, PK_pixfmtNul, 2, 3, 8, 1},
  112. {&GUID_PKPixelFormat32bppBGR, 3, CF_RGB, BD_8, 32, PK_pixfmtBGR, 2, 3, 8, 1},
  113. {&GUID_PKPixelFormat48bppRGB, 3, CF_RGB, BD_16, 48, PK_pixfmtNul, 2, 3, 16, 1},
  114. {&GUID_PKPixelFormat48bppRGBFixedPoint, 3, CF_RGB, BD_16S, 48, PK_pixfmtNul, 2, 3, 16, 2},
  115. {&GUID_PKPixelFormat48bppRGBHalf, 3, CF_RGB, BD_16F, 48, PK_pixfmtNul, 2, 3, 16, 3},
  116. {&GUID_PKPixelFormat64bppRGBFixedPoint, 3, CF_RGB, BD_16S, 64, PK_pixfmtNul, 2, 3, 16, 2},
  117. {&GUID_PKPixelFormat64bppRGBHalf, 3, CF_RGB, BD_16F, 64, PK_pixfmtNul, 2, 3, 16, 3},
  118. //{&GUID_PKPixelFormat96bppRGB, 3, CF_RGB, BD_32, 96, PK_pixfmtNul, 2, 3, 32, 1},
  119. {&GUID_PKPixelFormat96bppRGBFixedPoint, 3, CF_RGB, BD_32S, 96, PK_pixfmtNul, 2, 3, 32, 2},
  120. {&GUID_PKPixelFormat96bppRGBFloat, 3, CF_RGB, BD_32F, 96, PK_pixfmtNul, 2, 3, 32, 3},
  121. {&GUID_PKPixelFormat128bppRGBFixedPoint, 3, CF_RGB, BD_32S, 128, PK_pixfmtNul, 2, 3, 32, 2},
  122. {&GUID_PKPixelFormat128bppRGBFloat, 3, CF_RGB, BD_32F, 128, PK_pixfmtNul, 2, 3, 32, 3},
  123. // RGBA
  124. {&GUID_PKPixelFormat32bppBGRA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha | PK_pixfmtBGR, 2, 4, 8, 1},
  125. {&GUID_PKPixelFormat32bppRGBA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha, 2, 4, 8, 1},
  126. {&GUID_PKPixelFormat64bppRGBA, 4, CF_RGB, BD_16, 64, PK_pixfmtHasAlpha, 2, 4, 16, 1},
  127. {&GUID_PKPixelFormat64bppRGBAFixedPoint, 4, CF_RGB, BD_16S, 64, PK_pixfmtHasAlpha, 2, 4, 16, 2},
  128. {&GUID_PKPixelFormat64bppRGBAHalf, 4, CF_RGB, BD_16F, 64, PK_pixfmtHasAlpha, 2, 4, 16, 3},
  129. //{&GUID_PKPixelFormat128bppRGBA, 4, CF_RGB, BD_32, 128, PK_pixfmtHasAlpha, 2, 4, 32, 1},
  130. {&GUID_PKPixelFormat128bppRGBAFixedPoint, 4, CF_RGB, BD_32S, 128, PK_pixfmtHasAlpha, 2, 4, 32, 2},
  131. {&GUID_PKPixelFormat128bppRGBAFloat, 4, CF_RGB, BD_32F, 128, PK_pixfmtHasAlpha, 2, 4, 32, 3},
  132. // PRGBA
  133. {&GUID_PKPixelFormat32bppPBGRA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha | PK_pixfmtPreMul | PK_pixfmtBGR, 2, 4, 8, 1},
  134. {&GUID_PKPixelFormat32bppPRGBA, 4, CF_RGB, BD_8, 32, PK_pixfmtHasAlpha | PK_pixfmtPreMul, 2, 4, 8, 1},
  135. {&GUID_PKPixelFormat64bppPRGBA, 4, CF_RGB, BD_16, 64, PK_pixfmtHasAlpha | PK_pixfmtPreMul, 2, 4, 16, 1},
  136. //{&GUID_PKPixelFormat64bppPRGBAFixedPoint, 4, CF_RGB, BD_16S, 64, PK_pixfmtHasAlpha, 2, 4, 16, 2},
  137. //{&GUID_PKPixelFormat64bppPRGBAHalf, 4, CF_RGB, BD_16F, 64, PK_pixfmtHasAlpha, 2, 4, 16, 3},
  138. //{&GUID_PKPixelFormat128bppPRGBAFixedPoint, 4, CF_RGB, BD_32S, 128, PK_pixfmtHasAlpha, 2, 4, 32, 2},
  139. {&GUID_PKPixelFormat128bppPRGBAFloat, 4, CF_RGB, BD_32F, 128, PK_pixfmtHasAlpha | PK_pixfmtPreMul, 2, 4, 32, 3},
  140. // Packed formats
  141. {&GUID_PKPixelFormat16bppRGB555, 3, CF_RGB, BD_5, 16, PK_pixfmtNul, 2, 3, 5, 1},
  142. {&GUID_PKPixelFormat16bppRGB565, 3, CF_RGB, BD_565, 16, PK_pixfmtNul, 2, 3, 6, 1},
  143. {&GUID_PKPixelFormat32bppRGB101010, 3, CF_RGB, BD_10, 32, PK_pixfmtNul, 2, 3, 10, 1},
  144. // CMYK
  145. {&GUID_PKPixelFormat32bppCMYK, 4, CMYK, BD_8, 32, PK_pixfmtNul, 5, 4, 8, 1},
  146. {&GUID_PKPixelFormat40bppCMYKAlpha, 5, CMYK, BD_8, 40, PK_pixfmtHasAlpha, 5, 5, 8, 1},
  147. {&GUID_PKPixelFormat64bppCMYK, 4, CMYK, BD_16, 64, PK_pixfmtNul, 5, 4, 16, 1},
  148. {&GUID_PKPixelFormat80bppCMYKAlpha, 5, CMYK, BD_16, 80, PK_pixfmtHasAlpha, 5, 5, 16, 1},
  149. // N_CHANNEL
  150. {&GUID_PKPixelFormat24bpp3Channels, 3, NCOMPONENT, BD_8, 24, PK_pixfmtNul, PK_PI_NCH, 3, 8, 1},//the N channel TIF by PS has PhotometricInterpretation of PK_PI_RGB
  151. {&GUID_PKPixelFormat32bpp4Channels, 4, NCOMPONENT, BD_8, 32, PK_pixfmtNul, PK_PI_NCH, 4, 8, 1},
  152. {&GUID_PKPixelFormat40bpp5Channels, 5, NCOMPONENT, BD_8, 40, PK_pixfmtNul, PK_PI_NCH, 5, 8, 1},
  153. {&GUID_PKPixelFormat48bpp6Channels, 6, NCOMPONENT, BD_8, 48, PK_pixfmtNul, PK_PI_NCH, 6, 8, 1},
  154. {&GUID_PKPixelFormat56bpp7Channels, 7, NCOMPONENT, BD_8, 56, PK_pixfmtNul, PK_PI_NCH, 7, 8, 1},
  155. {&GUID_PKPixelFormat64bpp8Channels, 8, NCOMPONENT, BD_8, 64, PK_pixfmtNul, PK_PI_NCH, 8, 8, 1},
  156. {&GUID_PKPixelFormat32bpp3ChannelsAlpha, 4, NCOMPONENT, BD_8, 32, PK_pixfmtHasAlpha, PK_PI_NCH, 4, 8, 1},
  157. {&GUID_PKPixelFormat40bpp4ChannelsAlpha, 5, NCOMPONENT, BD_8, 40, PK_pixfmtHasAlpha, PK_PI_NCH, 5, 8, 1},
  158. {&GUID_PKPixelFormat48bpp5ChannelsAlpha, 6, NCOMPONENT, BD_8, 48, PK_pixfmtHasAlpha, PK_PI_NCH, 6, 8, 1},
  159. {&GUID_PKPixelFormat56bpp6ChannelsAlpha, 7, NCOMPONENT, BD_8, 56, PK_pixfmtHasAlpha, PK_PI_NCH, 7, 8, 1},
  160. {&GUID_PKPixelFormat64bpp7ChannelsAlpha, 8, NCOMPONENT, BD_8, 64, PK_pixfmtHasAlpha, PK_PI_NCH, 8, 8, 1},
  161. {&GUID_PKPixelFormat72bpp8ChannelsAlpha, 9, NCOMPONENT, BD_8, 72, PK_pixfmtHasAlpha, PK_PI_NCH, 9, 8, 1},
  162. {&GUID_PKPixelFormat48bpp3Channels, 3, NCOMPONENT, BD_16, 48, PK_pixfmtNul, PK_PI_NCH, 3, 16, 1},
  163. {&GUID_PKPixelFormat64bpp4Channels, 4, NCOMPONENT, BD_16, 64, PK_pixfmtNul, PK_PI_NCH, 4, 16, 1},
  164. {&GUID_PKPixelFormat80bpp5Channels, 5, NCOMPONENT, BD_16, 80, PK_pixfmtNul, PK_PI_NCH, 5, 16, 1},
  165. {&GUID_PKPixelFormat96bpp6Channels, 6, NCOMPONENT, BD_16, 96, PK_pixfmtNul, PK_PI_NCH, 6, 16, 1},
  166. {&GUID_PKPixelFormat112bpp7Channels, 7, NCOMPONENT, BD_16, 112, PK_pixfmtNul, PK_PI_NCH, 7, 16, 1},
  167. {&GUID_PKPixelFormat128bpp8Channels, 8, NCOMPONENT, BD_16, 128, PK_pixfmtNul, PK_PI_NCH, 8, 16, 1},
  168. {&GUID_PKPixelFormat64bpp3ChannelsAlpha, 4, NCOMPONENT, BD_16, 64, PK_pixfmtHasAlpha, PK_PI_NCH, 4, 16, 1},
  169. {&GUID_PKPixelFormat80bpp4ChannelsAlpha, 5, NCOMPONENT, BD_16, 80, PK_pixfmtHasAlpha, PK_PI_NCH, 5, 16, 1},
  170. {&GUID_PKPixelFormat96bpp5ChannelsAlpha, 6, NCOMPONENT, BD_16, 96, PK_pixfmtHasAlpha, PK_PI_NCH, 6, 16, 1},
  171. {&GUID_PKPixelFormat112bpp6ChannelsAlpha, 7, NCOMPONENT, BD_16, 112, PK_pixfmtHasAlpha, PK_PI_NCH, 7, 16, 1},
  172. {&GUID_PKPixelFormat128bpp7ChannelsAlpha, 8, NCOMPONENT, BD_16, 128, PK_pixfmtHasAlpha, PK_PI_NCH, 8, 16, 1},
  173. {&GUID_PKPixelFormat144bpp8ChannelsAlpha, 9, NCOMPONENT, BD_16, 144, PK_pixfmtHasAlpha, PK_PI_NCH, 9, 16, 1},
  174. //RGBE
  175. {&GUID_PKPixelFormat32bppRGBE, 4, CF_RGBE, BD_8, 32, PK_pixfmtNul, PK_PI_RGBE, 4, 8, 1},
  176. //YUV
  177. {&GUID_PKPixelFormat12bppYUV420, 3, YUV_420, BD_8, 48, PK_pixfmtNul},
  178. {&GUID_PKPixelFormat16bppYUV422, 3, YUV_422, BD_8, 32, PK_pixfmtNul},
  179. {&GUID_PKPixelFormat24bppYUV444, 3, YUV_444, BD_8, 24, PK_pixfmtNul},
  180. };
  181. //----------------------------------------------------------------
  182. //ERR GetPixelInfo(PKPixelFormatGUID enPixelFormat, const PKPixelInfo** ppPI)
  183. ERR PixelFormatLookup(PKPixelInfo* pPI, U8 uLookupType)
  184. {
  185. ERR err = WMP_errSuccess;
  186. size_t i;
  187. for (i = 0; i < sizeof2(pixelInfo); ++i)
  188. {
  189. if (LOOKUP_FORWARD == uLookupType)
  190. {
  191. if (IsEqualGUID(pPI->pGUIDPixFmt, pixelInfo[i].pGUIDPixFmt))
  192. {
  193. *pPI = pixelInfo[i];
  194. goto Cleanup;
  195. }
  196. }
  197. else if (LOOKUP_BACKWARD_TIF == uLookupType)
  198. {
  199. if (pPI->uSamplePerPixel == pixelInfo[i].uSamplePerPixel &&
  200. pPI->uBitsPerSample == pixelInfo[i].uBitsPerSample &&
  201. pPI->uSampleFormat == pixelInfo[i].uSampleFormat &&
  202. pPI->uInterpretation == pixelInfo[i].uInterpretation)
  203. {
  204. // match alpha & premult
  205. if ((pPI->grBit & (PK_pixfmtHasAlpha | PK_pixfmtPreMul)) ==
  206. (pixelInfo[i].grBit & (PK_pixfmtHasAlpha | PK_pixfmtPreMul)))
  207. {
  208. *pPI = pixelInfo[i];
  209. goto Cleanup;
  210. }
  211. }
  212. }
  213. }
  214. Call(WMP_errUnsupportedFormat);
  215. Cleanup:
  216. return err;
  217. }
  218. const PKPixelFormatGUID* GetPixelFormatFromHash(const U8 uPFHash)
  219. {
  220. int i;
  221. for (i = 0; i < sizeof2(pixelInfo); i++)
  222. {
  223. if (pixelInfo[i].pGUIDPixFmt->Data4[7] == uPFHash)
  224. return pixelInfo[i].pGUIDPixFmt;
  225. }
  226. // If we reached this point, we did not find anything which matched the hash
  227. return NULL;
  228. }
  229. //----------------------------------------------------------------
  230. typedef struct tagPKIIDInfo
  231. {
  232. const char* szExt;
  233. const PKIID* pIIDEnc;
  234. const PKIID* pIIDDec;
  235. } PKIIDInfo;
  236. static ERR GetIIDInfo(const char* szExt, const PKIIDInfo** ppInfo)
  237. {
  238. ERR err = WMP_errSuccess;
  239. static PKIIDInfo iidInfo[] = {
  240. {".jxr", &IID_PKImageWmpEncode, &IID_PKImageWmpDecode},
  241. {".wdp", &IID_PKImageUnsupported, &IID_PKImageWmpDecode},
  242. {".hdp", &IID_PKImageUnsupported, &IID_PKImageWmpDecode},
  243. };
  244. size_t i = 0;
  245. *ppInfo = NULL;
  246. for (i = 0; i < sizeof2(iidInfo); ++i)
  247. {
  248. if (0 == PKStrnicmp(szExt, iidInfo[i].szExt, strlen(iidInfo[i].szExt)))
  249. {
  250. *ppInfo = &iidInfo[i];
  251. goto Cleanup;
  252. }
  253. }
  254. Call(WMP_errUnsupportedFormat);
  255. Cleanup:
  256. return err;
  257. }
  258. ERR GetImageEncodeIID(const char* szExt, const PKIID** ppIID)
  259. {
  260. ERR err = WMP_errSuccess;
  261. const PKIIDInfo* pInfo = NULL;
  262. Call(GetIIDInfo(szExt, &pInfo));
  263. *ppIID = pInfo->pIIDEnc;
  264. Cleanup:
  265. return err;
  266. }
  267. ERR GetImageDecodeIID(const char* szExt, const PKIID** ppIID)
  268. {
  269. ERR err = WMP_errSuccess;
  270. const PKIIDInfo* pInfo = NULL;
  271. Call(GetIIDInfo(szExt, &pInfo));
  272. *ppIID = pInfo->pIIDDec;
  273. Cleanup:
  274. return err;
  275. }
  276. //================================================================
  277. // PKFactory
  278. //================================================================
  279. ERR PKCreateFactory_CreateStream(PKStream** ppStream)
  280. {
  281. ERR err = WMP_errSuccess;
  282. Call(PKAlloc((void **) ppStream, sizeof(**ppStream)));
  283. Cleanup:
  284. return err;
  285. }
  286. ERR PKCreateFactory_Release(PKFactory** ppFactory)
  287. {
  288. ERR err = WMP_errSuccess;
  289. Call(PKFree((void **) ppFactory));
  290. Cleanup:
  291. return err;
  292. }
  293. //----------------------------------------------------------------
  294. ERR PKCreateFactory(PKFactory** ppFactory, U32 uVersion)
  295. {
  296. ERR err = WMP_errSuccess;
  297. PKFactory* pFactory = NULL;
  298. UNREFERENCED_PARAMETER( uVersion );
  299. Call(PKAlloc((void **) ppFactory, sizeof(**ppFactory)));
  300. pFactory = *ppFactory;
  301. pFactory->CreateStream = PKCreateFactory_CreateStream;
  302. pFactory->CreateStreamFromFilename = CreateWS_File;
  303. pFactory->CreateStreamFromMemory = CreateWS_Memory;
  304. pFactory->Release = PKCreateFactory_Release;
  305. Cleanup:
  306. return err;
  307. }
  308. //================================================================
  309. // PKCodecFactory
  310. //================================================================
  311. ERR PKCodecFactory_CreateCodec(const PKIID* iid, void** ppv)
  312. {
  313. ERR err = WMP_errSuccess;
  314. if (IID_PKImageWmpEncode == *iid)
  315. {
  316. Call(PKImageEncode_Create_WMP((PKImageEncode**)ppv));
  317. }
  318. else if (IID_PKImageWmpDecode == *iid)
  319. {
  320. Call(PKImageDecode_Create_WMP((PKImageDecode**)ppv));
  321. }
  322. else
  323. {
  324. Call(WMP_errUnsupportedFormat);
  325. }
  326. Cleanup:
  327. return err;
  328. }
  329. ERR PKCodecFactory_CreateDecoderFromFile(const char* szFilename, PKImageDecode** ppDecoder)
  330. {
  331. ERR err = WMP_errSuccess;
  332. char *pExt = NULL;
  333. const PKIID* pIID = NULL;
  334. struct WMPStream* pStream = NULL;
  335. PKImageDecode* pDecoder = NULL;
  336. // get file extension
  337. pExt = strrchr(szFilename, '.');
  338. FailIf(NULL == pExt, WMP_errUnsupportedFormat);
  339. // get decode PKIID
  340. Call(GetImageDecodeIID(pExt, &pIID));
  341. // create stream
  342. Call(CreateWS_File(&pStream, szFilename, "rb"));
  343. // Create decoder
  344. Call(PKCodecFactory_CreateCodec(pIID, (void **) ppDecoder));
  345. pDecoder = *ppDecoder;
  346. // attach stream to decoder
  347. Call(pDecoder->Initialize(pDecoder, pStream));
  348. pDecoder->fStreamOwner = !0;
  349. Cleanup:
  350. return err;
  351. }
  352. ERR PKCodecFactory_CreateFormatConverter(PKFormatConverter** ppFConverter)
  353. {
  354. ERR err = WMP_errSuccess;
  355. PKFormatConverter* pFC = NULL;
  356. Call(PKAlloc((void **) ppFConverter, sizeof(**ppFConverter)));
  357. pFC = *ppFConverter;
  358. pFC->Initialize = PKFormatConverter_Initialize;
  359. pFC->InitializeConvert = PKFormatConverter_InitializeConvert;
  360. pFC->GetPixelFormat = PKFormatConverter_GetPixelFormat;
  361. pFC->GetSourcePixelFormat = PKFormatConverter_GetSourcePixelFormat;
  362. pFC->GetSize = PKFormatConverter_GetSize;
  363. pFC->GetResolution = PKFormatConverter_GetResolution;
  364. pFC->Copy = PKFormatConverter_Copy;
  365. pFC->Convert = PKFormatConverter_Convert;
  366. pFC->Release = PKFormatConverter_Release;
  367. Cleanup:
  368. return err;
  369. }
  370. ERR PKCreateCodecFactory_Release(PKCodecFactory** ppCFactory)
  371. {
  372. ERR err = WMP_errSuccess;
  373. Call(PKFree((void **) ppCFactory));
  374. Cleanup:
  375. return err;
  376. }
  377. ERR PKCreateCodecFactory(PKCodecFactory** ppCFactory, U32 uVersion)
  378. {
  379. ERR err = WMP_errSuccess;
  380. PKCodecFactory* pCFactory = NULL;
  381. UNREFERENCED_PARAMETER( uVersion );
  382. Call(PKAlloc((void **) ppCFactory, sizeof(**ppCFactory)));
  383. pCFactory = *ppCFactory;
  384. pCFactory->CreateCodec = PKCodecFactory_CreateCodec;
  385. pCFactory->CreateDecoderFromFile = PKCodecFactory_CreateDecoderFromFile;
  386. pCFactory->CreateFormatConverter = PKCodecFactory_CreateFormatConverter;
  387. pCFactory->Release = PKCreateCodecFactory_Release;
  388. Cleanup:
  389. return err;
  390. }
  391. //================================================================
  392. // PKImageEncode
  393. //================================================================
  394. ERR PKImageEncode_Initialize(
  395. PKImageEncode* pIE,
  396. struct WMPStream* pStream,
  397. void* pvParam,
  398. size_t cbParam)
  399. {
  400. ERR err = WMP_errSuccess;
  401. UNREFERENCED_PARAMETER( pIE );
  402. UNREFERENCED_PARAMETER( pvParam );
  403. UNREFERENCED_PARAMETER( cbParam );
  404. pIE->pStream = pStream;
  405. pIE->guidPixFormat = GUID_PKPixelFormatDontCare;
  406. pIE->fResX = 96;
  407. pIE->fResY = 96;
  408. pIE->cFrame = 1;
  409. Call(pIE->pStream->GetPos(pIE->pStream, &pIE->offStart));
  410. Cleanup:
  411. return err;
  412. }
  413. ERR PKImageEncode_Terminate(
  414. PKImageEncode* pIE)
  415. {
  416. UNREFERENCED_PARAMETER( pIE );
  417. return WMP_errSuccess;
  418. }
  419. ERR PKImageEncode_SetPixelFormat(
  420. PKImageEncode* pIE,
  421. PKPixelFormatGUID enPixelFormat)
  422. {
  423. pIE->guidPixFormat = enPixelFormat;
  424. return WMP_errSuccess;
  425. }
  426. ERR PKImageEncode_SetSize(
  427. PKImageEncode* pIE,
  428. I32 iWidth,
  429. I32 iHeight)
  430. {
  431. ERR err = WMP_errSuccess;
  432. pIE->uWidth = (U32)iWidth;
  433. pIE->uHeight = (U32)iHeight;
  434. return err;
  435. }
  436. ERR PKImageEncode_SetResolution(
  437. PKImageEncode* pIE,
  438. Float fResX,
  439. Float fResY)
  440. {
  441. pIE->fResX = fResX;
  442. pIE->fResY = fResY;
  443. return WMP_errSuccess;
  444. }
  445. ERR PKImageEncode_SetColorContext(PKImageEncode *pIE,
  446. const U8 *pbColorContext,
  447. U32 cbColorContext)
  448. {
  449. UNREFERENCED_PARAMETER( pIE );
  450. UNREFERENCED_PARAMETER( pbColorContext );
  451. UNREFERENCED_PARAMETER( cbColorContext );
  452. return WMP_errNotYetImplemented;
  453. }
  454. ERR PKImageEncode_SetDescriptiveMetadata(PKImageEncode *pIE, const DESCRIPTIVEMETADATA *pDescMetadata)
  455. {
  456. UNREFERENCED_PARAMETER( pIE );
  457. UNREFERENCED_PARAMETER( pDescMetadata );
  458. return WMP_errNotYetImplemented;
  459. }
  460. ERR PKImageEncode_WritePixels(
  461. PKImageEncode* pIE,
  462. U32 cLine,
  463. U8* pbPixels,
  464. U32 cbStride)
  465. {
  466. UNREFERENCED_PARAMETER( pIE );
  467. UNREFERENCED_PARAMETER( cLine );
  468. UNREFERENCED_PARAMETER( pbPixels );
  469. UNREFERENCED_PARAMETER( cbStride );
  470. return WMP_errAbstractMethod;
  471. }
  472. ERR PKImageEncode_WriteSource(
  473. PKImageEncode* pIE,
  474. PKFormatConverter* pFC,
  475. PKRect* pRect)
  476. {
  477. ERR err = WMP_errSuccess;
  478. PKPixelFormatGUID enPFFrom = GUID_PKPixelFormatDontCare;
  479. PKPixelFormatGUID enPFTo = GUID_PKPixelFormatDontCare;
  480. PKPixelInfo pPIFrom;
  481. PKPixelInfo pPITo;
  482. U32 cbStrideTo = 0;
  483. U32 cbStrideFrom = 0;
  484. U32 cbStride = 0;
  485. U8* pb = NULL;
  486. // CWMTranscodingParam* pParam = NULL;
  487. // get pixel format
  488. Call(pFC->GetSourcePixelFormat(pFC, &enPFFrom));
  489. Call(pFC->GetPixelFormat(pFC, &enPFTo));
  490. FailIf(!IsEqualGUID(&pIE->guidPixFormat, &enPFTo), WMP_errUnsupportedFormat);
  491. // calc common stride
  492. // Call(GetPixelInfo(enPFFrom, &pPIFrom));
  493. pPIFrom.pGUIDPixFmt = &enPFFrom;
  494. PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD);
  495. // Call(GetPixelInfo(enPFTo, &pPITo));
  496. pPITo.pGUIDPixFmt = &enPFTo;
  497. PixelFormatLookup(&pPITo, LOOKUP_FORWARD);
  498. // cbStrideFrom = (pPIFrom->cbPixel * pRect->Width + pPIFrom->cbPixelDenom - 1) / pPIFrom->cbPixelDenom;
  499. cbStrideFrom = (BD_1 == pPIFrom.bdBitDepth ? ((pPIFrom.cbitUnit * pRect->Width + 7) >> 3) : (((pPIFrom.cbitUnit + 7) >> 3) * pRect->Width));
  500. if (&GUID_PKPixelFormat12bppYUV420 == pPIFrom.pGUIDPixFmt
  501. || &GUID_PKPixelFormat16bppYUV422 == pPIFrom.pGUIDPixFmt)
  502. cbStrideFrom >>= 1;
  503. // cbStrideTo = (pPITo->cbPixel * pIE->uWidth + pPITo->cbPixelDenom - 1) / pPITo->cbPixelDenom;
  504. cbStrideTo = (BD_1 == pPITo.bdBitDepth ? ((pPITo.cbitUnit * pIE->uWidth + 7) >> 3) : (((pPITo.cbitUnit + 7) >> 3) * pIE->uWidth));
  505. if (&GUID_PKPixelFormat12bppYUV420 == pPITo.pGUIDPixFmt
  506. || &GUID_PKPixelFormat16bppYUV422 == pPITo.pGUIDPixFmt)
  507. cbStrideTo >>= 1;
  508. cbStride = max(cbStrideFrom, cbStrideTo);
  509. // actual dec/enc with local buffer
  510. Call(PKAllocAligned((void **) &pb, cbStride * pRect->Height, 128));
  511. Call(pFC->Copy(pFC, pRect, pb, cbStride));
  512. Call(pIE->WritePixels(pIE, pRect->Height, pb, cbStride));
  513. Cleanup:
  514. PKFreeAligned((void **) &pb);
  515. return err;
  516. }
  517. ERR PKImageEncode_WritePixelsBandedBegin(PKImageEncode* pEncoder, struct WMPStream *pPATempFile)
  518. {
  519. UNREFERENCED_PARAMETER( pEncoder );
  520. UNREFERENCED_PARAMETER( pPATempFile );
  521. return WMP_errAbstractMethod;
  522. }
  523. ERR PKImageEncode_WritePixelsBanded(PKImageEncode* pEncoder, U32 cLines, U8* pbPixels, U32 cbStride, Bool fLastCall)
  524. {
  525. UNREFERENCED_PARAMETER( pEncoder );
  526. UNREFERENCED_PARAMETER( cLines );
  527. UNREFERENCED_PARAMETER( pbPixels );
  528. UNREFERENCED_PARAMETER( cbStride );
  529. UNREFERENCED_PARAMETER( fLastCall );
  530. return WMP_errAbstractMethod;
  531. }
  532. ERR PKImageEncode_WritePixelsBandedEnd(PKImageEncode* pEncoder)
  533. {
  534. UNREFERENCED_PARAMETER( pEncoder );
  535. return WMP_errAbstractMethod;
  536. }
  537. ERR PKImageEncode_Transcode(
  538. PKImageEncode* pIE,
  539. PKFormatConverter* pFC,
  540. PKRect* pRect)
  541. {
  542. ERR err = WMP_errSuccess;
  543. PKPixelFormatGUID enPFFrom = GUID_PKPixelFormatDontCare;
  544. PKPixelFormatGUID enPFTo = GUID_PKPixelFormatDontCare;
  545. PKPixelInfo pPIFrom;
  546. PKPixelInfo pPITo;
  547. U32 cbStrideTo = 0;
  548. U32 cbStrideFrom = 0;
  549. U32 cbStride = 0;
  550. U8* pb = NULL;
  551. CWMTranscodingParam cParam = {0};
  552. // get pixel format
  553. Call(pFC->GetSourcePixelFormat(pFC, &enPFFrom));
  554. Call(pFC->GetPixelFormat(pFC, &enPFTo));
  555. FailIf(!IsEqualGUID(&pIE->guidPixFormat, &enPFTo), WMP_errUnsupportedFormat);
  556. // calc common stride
  557. // Call(GetPixelInfo(enPFFrom, &pPIFrom));
  558. pPIFrom.pGUIDPixFmt = &enPFFrom;
  559. PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD);
  560. // Call(GetPixelInfo(enPFTo, &pPITo));
  561. pPITo.pGUIDPixFmt = &enPFTo;
  562. PixelFormatLookup(&pPITo, LOOKUP_FORWARD);
  563. // cbStrideFrom = (pPIFrom->cbPixel * pRect->Width + pPIFrom->cbPixelDenom - 1) / pPIFrom->cbPixelDenom;
  564. cbStrideFrom = (BD_1 == pPIFrom.bdBitDepth ? ((pPIFrom.cbitUnit * pRect->Width + 7) >> 3) : (((pPIFrom.cbitUnit + 7) >> 3) * pRect->Width));
  565. if (&GUID_PKPixelFormat12bppYUV420 == pPIFrom.pGUIDPixFmt
  566. || &GUID_PKPixelFormat16bppYUV422 == pPIFrom.pGUIDPixFmt)
  567. cbStrideFrom >>= 1;
  568. // cbStrideTo = (pPITo->cbPixel * pIE->uWidth + pPITo->cbPixelDenom - 1) / pPITo->cbPixelDenom;
  569. cbStrideTo = (BD_1 == pPITo.bdBitDepth ? ((pPITo.cbitUnit * pIE->uWidth + 7) >> 3) : (((pPITo.cbitUnit + 7) >> 3) * pIE->uWidth));
  570. if (&GUID_PKPixelFormat12bppYUV420 == pPITo.pGUIDPixFmt
  571. || &GUID_PKPixelFormat16bppYUV422 == pPITo.pGUIDPixFmt)
  572. cbStrideTo >>= 1;
  573. cbStride = max(cbStrideFrom, cbStrideTo);
  574. if(pIE->bWMP){
  575. cParam.cLeftX = pFC->pDecoder->WMP.wmiI.cROILeftX;
  576. cParam.cTopY = pFC->pDecoder->WMP.wmiI.cROITopY;
  577. cParam.cWidth = pFC->pDecoder->WMP.wmiI.cROIWidth;
  578. cParam.cHeight = pFC->pDecoder->WMP.wmiI.cROIHeight;
  579. cParam.oOrientation = pFC->pDecoder->WMP.wmiI.oOrientation;
  580. // cParam.cfColorFormat = pFC->pDecoder->WMP.wmiI.cfColorFormat;
  581. cParam.uAlphaMode = pFC->pDecoder->WMP.wmiSCP.uAlphaMode;
  582. cParam.bfBitstreamFormat = pFC->pDecoder->WMP.wmiSCP.bfBitstreamFormat;
  583. cParam.sbSubband = pFC->pDecoder->WMP.wmiSCP.sbSubband;
  584. cParam.bIgnoreOverlap = pFC->pDecoder->WMP.bIgnoreOverlap;
  585. Call(pIE->Transcode(pIE, pFC->pDecoder, &cParam));
  586. }
  587. else
  588. {
  589. // actual dec/enc with local buffer
  590. Call(PKAllocAligned((void **) &pb, cbStride * pRect->Height, 128));
  591. Call(pFC->Copy(pFC, pRect, pb, cbStride));
  592. Call(pIE->WritePixels(pIE, pRect->Height, pb, cbStride));
  593. }
  594. Cleanup:
  595. PKFreeAligned((void **) &pb);
  596. return err;
  597. }
  598. ERR PKImageEncode_CreateNewFrame(
  599. PKImageEncode* pIE,
  600. void* pvParam,
  601. size_t cbParam)
  602. {
  603. UNREFERENCED_PARAMETER( pIE );
  604. UNREFERENCED_PARAMETER( pvParam );
  605. UNREFERENCED_PARAMETER( cbParam );
  606. // NYI
  607. return WMP_errSuccess;
  608. }
  609. ERR PKImageEncode_Release(
  610. PKImageEncode** ppIE)
  611. {
  612. PKImageEncode *pIE = *ppIE;
  613. pIE->pStream->Close(&pIE->pStream);
  614. return PKFree((void **) ppIE);
  615. }
  616. ERR PKImageEncode_Create(PKImageEncode** ppIE)
  617. {
  618. ERR err = WMP_errSuccess;
  619. PKImageEncode* pIE = NULL;
  620. Call(PKAlloc((void **) ppIE, sizeof(**ppIE)));
  621. pIE = *ppIE;
  622. pIE->Initialize = PKImageEncode_Initialize;
  623. pIE->Terminate = PKImageEncode_Terminate;
  624. pIE->SetPixelFormat = PKImageEncode_SetPixelFormat;
  625. pIE->SetSize = PKImageEncode_SetSize;
  626. pIE->SetResolution = PKImageEncode_SetResolution;
  627. pIE->SetColorContext = PKImageEncode_SetColorContext;
  628. pIE->SetDescriptiveMetadata = PKImageEncode_SetDescriptiveMetadata;
  629. pIE->WritePixels = PKImageEncode_WritePixels;
  630. // pIE->WriteSource = PKImageEncode_WriteSource;
  631. pIE->WritePixelsBandedBegin = PKImageEncode_WritePixelsBandedBegin;
  632. pIE->WritePixelsBanded = PKImageEncode_WritePixelsBanded;
  633. pIE->WritePixelsBandedEnd = PKImageEncode_WritePixelsBandedEnd;
  634. pIE->CreateNewFrame = PKImageEncode_CreateNewFrame;
  635. pIE->Release = PKImageEncode_Release;
  636. pIE->bWMP = FALSE;
  637. Cleanup:
  638. return err;
  639. }
  640. //================================================================
  641. // PKImageDecode
  642. //================================================================
  643. ERR PKImageDecode_Initialize(
  644. PKImageDecode* pID,
  645. struct WMPStream* pStream)
  646. {
  647. ERR err = WMP_errSuccess;
  648. pID->pStream = pStream;
  649. pID->guidPixFormat = GUID_PKPixelFormatDontCare;
  650. pID->fResX = 96;
  651. pID->fResY = 96;
  652. pID->cFrame = 1;
  653. Call(pID->pStream->GetPos(pID->pStream, &pID->offStart));
  654. memset(&pID->WMP.wmiDEMisc, 0, sizeof(pID->WMP.wmiDEMisc));
  655. Cleanup:
  656. return WMP_errSuccess;
  657. }
  658. ERR PKImageDecode_GetPixelFormat(
  659. PKImageDecode* pID,
  660. PKPixelFormatGUID* pPF)
  661. {
  662. *pPF = pID->guidPixFormat;
  663. return WMP_errSuccess;
  664. }
  665. ERR PKImageDecode_GetSize(
  666. PKImageDecode* pID,
  667. I32* piWidth,
  668. I32* piHeight)
  669. {
  670. *piWidth = (I32)pID->uWidth;
  671. *piHeight = (I32)pID->uHeight;
  672. return WMP_errSuccess;
  673. }
  674. ERR PKImageDecode_GetResolution(
  675. PKImageDecode* pID,
  676. Float* pfResX,
  677. Float* pfResY)
  678. {
  679. *pfResX = pID->fResX;
  680. *pfResY = pID->fResY;
  681. return WMP_errSuccess;
  682. }
  683. ERR PKImageDecode_GetColorContext(PKImageDecode *pID, U8 *pbColorContext, U32 *pcbColorContext)
  684. {
  685. UNREFERENCED_PARAMETER( pID );
  686. UNREFERENCED_PARAMETER( pbColorContext );
  687. UNREFERENCED_PARAMETER( pcbColorContext );
  688. return WMP_errNotYetImplemented;
  689. }
  690. ERR PKImageDecode_GetDescriptiveMetadata(PKImageDecode *pIE, DESCRIPTIVEMETADATA *pDescMetadata)
  691. {
  692. UNREFERENCED_PARAMETER( pIE );
  693. UNREFERENCED_PARAMETER( pDescMetadata );
  694. return WMP_errNotYetImplemented;
  695. }
  696. ERR PKImageDecode_Copy(
  697. PKImageDecode* pID,
  698. const PKRect* pRect,
  699. U8* pb,
  700. U32 cbStride)
  701. {
  702. UNREFERENCED_PARAMETER( pID );
  703. UNREFERENCED_PARAMETER( pRect );
  704. UNREFERENCED_PARAMETER( pb );
  705. UNREFERENCED_PARAMETER( cbStride );
  706. return WMP_errAbstractMethod;
  707. }
  708. ERR PKImageDecode_GetFrameCount(
  709. PKImageDecode* pID,
  710. U32* puCount)
  711. {
  712. *puCount = pID->cFrame;
  713. return WMP_errSuccess;
  714. }
  715. ERR PKImageDecode_SelectFrame(
  716. PKImageDecode* pID,
  717. U32 uFrame)
  718. {
  719. UNREFERENCED_PARAMETER( pID );
  720. UNREFERENCED_PARAMETER( uFrame );
  721. // NYI
  722. return WMP_errSuccess;
  723. }
  724. ERR PKImageDecode_Release(
  725. PKImageDecode** ppID)
  726. {
  727. PKImageDecode* pID = *ppID;
  728. pID->fStreamOwner && pID->pStream->Close(&pID->pStream);
  729. return PKFree((void **) ppID);
  730. }
  731. ERR PKImageDecode_Create(
  732. PKImageDecode** ppID)
  733. {
  734. ERR err = WMP_errSuccess;
  735. PKImageDecode* pID = NULL;
  736. Call(PKAlloc((void **) ppID, sizeof(**ppID)));
  737. pID = *ppID;
  738. pID->Initialize = PKImageDecode_Initialize;
  739. pID->GetPixelFormat = PKImageDecode_GetPixelFormat;
  740. pID->GetSize = PKImageDecode_GetSize;
  741. pID->GetResolution = PKImageDecode_GetResolution;
  742. pID->GetColorContext = PKImageDecode_GetColorContext;
  743. pID->GetDescriptiveMetadata = PKImageDecode_GetDescriptiveMetadata;
  744. pID->Copy = PKImageDecode_Copy;
  745. pID->GetFrameCount = PKImageDecode_GetFrameCount;
  746. pID->SelectFrame = PKImageDecode_SelectFrame;
  747. pID->Release = PKImageDecode_Release;
  748. Cleanup:
  749. return err;
  750. }