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