2 //*@@@+++@@@@******************************************************************
4 // Copyright © Microsoft Corp.
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
10 // • Redistributions of source code must retain the above copyright notice,
11 // this list of conditions and the following disclaimer.
12 // • Redistributions in binary form must reproduce the above copyright notice,
13 // this list of conditions and the following disclaimer in the documentation
14 // and/or other materials provided with the distribution.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
28 //*@@@---@@@@******************************************************************
33 static const char szHDPhotoFormat
[] = "<dc:format>image/vnd.ms-photo</dc:format>";
34 const U32 IFDEntryTypeSizes
[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 };
35 const U32 SizeofIFDEntry
= sizeof(struct IFDEntry
);
38 void CalcMetadataSizeLPSTR(const DPKPROPVARIANT var
,
39 U16
*pcInactiveMetadata
,
43 if (DPKVT_EMPTY
!= var
.vt
)
45 U32 uiLenWithNull
= (U32
)strlen(var
.VT
.pszVal
) + 1; // +1 for NULL;
46 assert(DPKVT_LPSTR
== var
.vt
);
48 // We only use offset if size > 4
49 if (uiLenWithNull
> 4)
50 *pcbOffsetSize
+= uiLenWithNull
;
53 *pcbCount
= uiLenWithNull
;
56 *pcInactiveMetadata
+= 1;
59 void CalcMetadataSizeLPWSTR(const DPKPROPVARIANT var
,
60 U16
*pcInactiveMetadata
,
64 if (DPKVT_EMPTY
!= var
.vt
)
66 U32 uiCBWithNull
= sizeof(U16
) * ((U32
)wcslen((wchar_t *) var
.VT
.pwszVal
) + 1); // +1 for NULL term;
67 assert(DPKVT_LPWSTR
== var
.vt
);
69 // We only use offset if size > 4
71 *pcbOffsetSize
+= uiCBWithNull
;
74 *pcbCount
= uiCBWithNull
;
77 *pcInactiveMetadata
+= 1;
80 void CalcMetadataSizeUI2(const DPKPROPVARIANT var
,
81 U16
*pcInactiveMetadata
,
84 UNREFERENCED_PARAMETER( pcbMetadataSize
);
85 if (DPKVT_EMPTY
!= var
.vt
)
87 assert(DPKVT_UI2
== var
.vt
);
88 // This is a single UI2, so it will not be written via offset, but rather as value
91 *pcInactiveMetadata
+= 1;
94 void CalcMetadataSizeUI4(const DPKPROPVARIANT var
,
95 U16
*pcInactiveMetadata
,
98 UNREFERENCED_PARAMETER( pcbContainer
);
99 if (DPKVT_EMPTY
!= var
.vt
)
101 assert(DPKVT_UI4
== var
.vt
);
102 // This is a single UI4, so it will not be written via offset, but rather as value
105 *pcInactiveMetadata
+= 1;
108 ERR
CalcMetadataOffsetSize(PKImageEncode
* pIE
,
109 U16
*pcInactiveMetadata
,
110 U32
*pcbMetadataSize
)
112 ERR err
= WMP_errSuccess
;
114 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarImageDescription
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
115 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarCameraMake
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
116 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarCameraModel
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
117 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarSoftware
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
118 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarDateTime
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
119 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarArtist
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
120 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarCopyright
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
121 CalcMetadataSizeUI2(pIE
->sDescMetadata
.pvarRatingStars
, pcInactiveMetadata
, pcbMetadataSize
);
122 CalcMetadataSizeUI2(pIE
->sDescMetadata
.pvarRatingValue
, pcInactiveMetadata
, pcbMetadataSize
);
123 CalcMetadataSizeLPWSTR(pIE
->sDescMetadata
.pvarCaption
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
124 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarDocumentName
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
125 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarPageName
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
126 CalcMetadataSizeUI4(pIE
->sDescMetadata
.pvarPageNumber
, pcInactiveMetadata
, pcbMetadataSize
);
127 CalcMetadataSizeLPSTR(pIE
->sDescMetadata
.pvarHostComputer
, pcInactiveMetadata
, pcbMetadataSize
, NULL
);
133 ERR
CopyDescMetadata(DPKPROPVARIANT
*pvarDst
,
134 const DPKPROPVARIANT varSrc
)
136 ERR err
= WMP_errSuccess
;
139 pvarDst
->vt
= varSrc
.vt
;
143 pvarDst
->vt
= DPKVT_LPSTR
;
144 uiSize
= strlen(varSrc
.VT
.pszVal
) + 1;
145 Call(PKAlloc((void **) &pvarDst
->VT
.pszVal
, uiSize
));
146 memcpy(pvarDst
->VT
.pszVal
, varSrc
.VT
.pszVal
, uiSize
);
150 pvarDst
->vt
= DPKVT_LPWSTR
;
151 uiSize
= sizeof(U16
) * (wcslen((wchar_t *) varSrc
.VT
.pwszVal
) + 1); // +1 for NULL term
152 Call(PKAlloc((void **) &pvarDst
->VT
.pszVal
, uiSize
));
153 memcpy(pvarDst
->VT
.pwszVal
, varSrc
.VT
.pwszVal
, uiSize
);
157 pvarDst
->VT
.uiVal
= varSrc
.VT
.uiVal
;
161 pvarDst
->VT
.ulVal
= varSrc
.VT
.ulVal
;
165 assert(FALSE
); // This case is not handled
166 FailIf(TRUE
, WMP_errNotYetImplemented
);
168 // *** FALL THROUGH ***
171 memset(pvarDst
, 0, sizeof(*pvarDst
));
172 assert(DPKVT_EMPTY
== pvarDst
->vt
);
181 void FreeDescMetadata(DPKPROPVARIANT
*pvar
)
186 PKFree((void **) &pvar
->VT
.pszVal
);
190 PKFree((void **) &pvar
->VT
.pwszVal
);
194 assert(FALSE
); // This case is not handled
205 ERR
WriteDescMetadata(PKImageEncode
*pIE
,
206 const DPKPROPVARIANT var
,
208 U32
*puiCurrDescMetadataOffset
,
211 ERR err
= WMP_errSuccess
;
212 WmpDEMisc
* pDEMisc
= &pIE
->WMP
.wmiDEMisc
;
213 struct WMPStream
* pWS
= pIE
->pStream
;
214 U32 uiMetadataOffsetSize
= 0;
216 U32 uiDataWrittenToOffset
= 0;
219 if (0 == pDEMisc
->uDescMetadataOffset
|| 0 == pDEMisc
->uDescMetadataByteCount
)
220 goto Cleanup
; // Nothing to do here
222 // Sanity check before - can be equal due to remaining metadata being DPKVT_EMPTY
223 assert(*puiCurrDescMetadataOffset
<= pDEMisc
->uDescMetadataByteCount
);
231 CalcMetadataSizeLPSTR(var
, &uiTemp
, &uiMetadataOffsetSize
, &uiCount
);
232 pwmpDE
->uCount
= uiCount
;
233 pwmpDE
->uValueOrOffset
= pDEMisc
->uDescMetadataOffset
+ *puiCurrDescMetadataOffset
;
234 Call(WriteWmpDE(pWS
, poffPos
, pwmpDE
, (U8
*)var
.VT
.pszVal
, &uiDataWrittenToOffset
));
238 CalcMetadataSizeLPWSTR(var
, &uiTemp
, &uiMetadataOffsetSize
, &uiCount
);
239 pwmpDE
->uCount
= uiCount
;
240 pwmpDE
->uValueOrOffset
= pDEMisc
->uDescMetadataOffset
+ *puiCurrDescMetadataOffset
;
241 Call(WriteWmpDE(pWS
, poffPos
, pwmpDE
, (U8
*)var
.VT
.pwszVal
, &uiDataWrittenToOffset
));
245 CalcMetadataSizeUI2(var
, &uiTemp
, &uiMetadataOffsetSize
);
247 pwmpDE
->uValueOrOffset
= var
.VT
.uiVal
;
248 Call(WriteWmpDE(pWS
, poffPos
, pwmpDE
, NULL
, NULL
));
252 CalcMetadataSizeUI4(var
, &uiTemp
, &uiMetadataOffsetSize
);
254 pwmpDE
->uValueOrOffset
= var
.VT
.ulVal
;
255 Call(WriteWmpDE(pWS
, poffPos
, pwmpDE
, NULL
, NULL
));
259 assert(FALSE
); // This case is not handled
260 FailIf(TRUE
, WMP_errNotYetImplemented
);
264 *puiCurrDescMetadataOffset
+= uiDataWrittenToOffset
;
266 // Sanity check after
267 assert(*puiCurrDescMetadataOffset
<= pDEMisc
->uDescMetadataByteCount
); // Can be equal
275 //================================================================
277 //================================================================
278 ERR
WriteContainerPre(
281 ERR err
= WMP_errSuccess
;
282 const U32 OFFSET_OF_PFD
= 0x20;
283 struct WMPStream
* pWS
= pIE
->pStream
;
284 WmpDEMisc
* pDEMisc
= &pIE
->WMP
.wmiDEMisc
;
288 U8 IIMM
[2] = {'\x49', '\x49'};
289 // const U32 cbWmpDEMisc = OFFSET_OF_PFD;
290 U32 cbMetadataOffsetSize
= 0;
291 U16 cInactiveMetadata
= 0;
292 U32 uiCurrDescMetadataOffset
= 0;
294 static WmpDE wmpDEs
[] =
296 {WMP_tagDocumentName
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
297 {WMP_tagImageDescription
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
298 {WMP_tagCameraMake
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
299 {WMP_tagCameraModel
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
300 {WMP_tagPageName
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
301 {WMP_tagPageNumber
, WMP_typSHORT
, 2, (U32
) -1}, // Descriptive metadata
302 {WMP_tagSoftware
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
303 {WMP_tagDateTime
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
304 {WMP_tagArtist
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
305 {WMP_tagHostComputer
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
306 {WMP_tagRatingStars
, WMP_typSHORT
, 1, (U32
) -1}, // Descriptive metadata
307 {WMP_tagRatingValue
, WMP_typSHORT
, 1, (U32
) -1}, // Descriptive metadata
308 {WMP_tagCopyright
, WMP_typASCII
, 1, (U32
) -1}, // Descriptive metadata
309 {WMP_tagCaption
, WMP_typBYTE
, 1, (U32
) -1}, // Descriptive metadata
311 {WMP_tagXMPMetadata
, WMP_typBYTE
, 1, (U32
) -1},
312 {WMP_tagIPTCNAAMetadata
, WMP_typBYTE
, 1, (U32
) -1},
313 {WMP_tagPhotoshopMetadata
, WMP_typBYTE
, 1, (U32
) -1},
314 {WMP_tagEXIFMetadata
, WMP_typLONG
, 1, (U32
) -1},
315 {WMP_tagIccProfile
, WMP_typUNDEFINED
, 1, (U32
) -1},
316 {WMP_tagGPSInfoMetadata
, WMP_typLONG
, 1, (U32
) -1},
318 {WMP_tagPixelFormat
, WMP_typBYTE
, 16, (U32
) -1},
319 {WMP_tagTransformation
, WMP_typLONG
, 1, (U32
) -1},
320 {WMP_tagImageWidth
, WMP_typLONG
, 1, (U32
) -1},
321 {WMP_tagImageHeight
, WMP_typLONG
, 1, (U32
) -1},
322 {WMP_tagWidthResolution
, WMP_typFLOAT
, 1, (U32
) -1},
323 {WMP_tagHeightResolution
, WMP_typFLOAT
, 1, (U32
) -1},
324 {WMP_tagImageOffset
, WMP_typLONG
, 1, (U32
) -1},
325 {WMP_tagImageByteCount
, WMP_typLONG
, 1, (U32
) -1},
326 {WMP_tagAlphaOffset
, WMP_typLONG
, 1, (U32
) -1},
327 {WMP_tagAlphaByteCount
, WMP_typLONG
, 1, (U32
) -1},
329 U16 cWmpDEs
= sizeof(wmpDEs
) / sizeof(wmpDEs
[0]);
333 U8
* pbEXIFMetadata
= NULL
;
334 U8
* pbGPSInfoMetadata
= NULL
;
336 // const unsigned char Zero[0x20] = { 0 };
337 const unsigned char Zero
[sizeof(struct IFDEntry
) * sizeof(wmpDEs
) / sizeof(wmpDEs
[0]) + sizeof(U32
)] = { 0 };
338 assert(SizeofIFDEntry
* sizeof(wmpDEs
) / sizeof(wmpDEs
[0]) + sizeof(U32
) > 0x20);
341 Call(pWS
->GetPos(pWS
, &offPos
));
342 FailIf(0 != offPos
, WMP_errUnsupportedFormat
);
346 Call(pWS
->Write(pWS
, IIMM
, sizeof(IIMM
))); offPos
+= 2;
347 Call(PutUShort(pWS
, offPos
, 0x01bc)); offPos
+= 2;
348 Call(PutULong(pWS
, offPos
, (U32
)OFFSET_OF_PFD
)); offPos
+= 4;
351 // Write overflow area
352 pDEMisc
->uOffPixelFormat
= (U32
)offPos
;
353 PI
.pGUIDPixFmt
= &pIE
->guidPixFormat
;
354 PixelFormatLookup(&PI
, LOOKUP_FORWARD
);
356 //Call(pWS->Write(pWS, PI.pGUIDPixFmt, sizeof(*PI.pGUIDPixFmt))); offPos += 16;
357 /** following code is endian-agnostic **/
359 unsigned char *pGuid
= (unsigned char *) &pIE
->guidPixFormat
;
360 Call(PutULong(pWS
, offPos
, ((U32
*)pGuid
)[0]));
361 Call(PutUShort(pWS
, offPos
+ 4, ((U16
*)(pGuid
+ 4))[0]));
362 Call(PutUShort(pWS
, offPos
+ 6, ((U16
*)(pGuid
+ 6))[0]));
363 Call(pWS
->Write(pWS
, pGuid
+ 8, 8));
368 // Tally up space required for descriptive metadata
369 Call(CalcMetadataOffsetSize(pIE
, &cInactiveMetadata
, &cbMetadataOffsetSize
));
370 cWmpDEs
-= cInactiveMetadata
;
374 assert (offPos
<= OFFSET_OF_PFD
); // otherwise stuff is overwritten
375 if (offPos
< OFFSET_OF_PFD
)
376 Call(pWS
->Write(pWS
, Zero
, OFFSET_OF_PFD
- offPos
));
377 offPos
= (size_t)OFFSET_OF_PFD
;
379 if (!pIE
->WMP
.bHasAlpha
|| pIE
->WMP
.wmiSCP
.uAlphaMode
!= 2) //no planar alpha
382 if (0 == pIE
->cbXMPMetadataByteCount
)
383 cWmpDEs
-= 1; // No XMP metadata
385 if (0 == pIE
->cbIPTCNAAMetadataByteCount
)
386 cWmpDEs
-= 1; // No IPTCNAA metadata
388 if (0 == pIE
->cbPhotoshopMetadataByteCount
)
389 cWmpDEs
-= 1; // No Photoshop metadata
391 if (0 == pIE
->cbEXIFMetadataByteCount
)
392 cWmpDEs
-= 1; // No EXIF metadata
394 if (0 == pIE
->cbColorContext
)
395 cWmpDEs
-= 1; // No color context
397 if (0 == pIE
->cbGPSInfoMetadataByteCount
)
398 cWmpDEs
-= 1; // No GPSInfo metadata
400 pDEMisc
->uImageOffset
= (U32
)(offPos
+ sizeof(U16
) + SizeofIFDEntry
* cWmpDEs
+ sizeof(U32
));
402 if (cbMetadataOffsetSize
> 0)
404 pDEMisc
->uDescMetadataByteCount
= cbMetadataOffsetSize
;
405 pDEMisc
->uDescMetadataOffset
= pDEMisc
->uImageOffset
;
406 pDEMisc
->uImageOffset
+= cbMetadataOffsetSize
;
409 if (pIE
->cbXMPMetadataByteCount
> 0)
411 pDEMisc
->uXMPMetadataOffset
= pDEMisc
->uImageOffset
;
412 pDEMisc
->uImageOffset
+= pIE
->cbXMPMetadataByteCount
;
415 if (pIE
->cbIPTCNAAMetadataByteCount
> 0)
417 pDEMisc
->uIPTCNAAMetadataOffset
= pDEMisc
->uImageOffset
;
418 pDEMisc
->uImageOffset
+= pIE
->cbIPTCNAAMetadataByteCount
;
421 if (pIE
->cbPhotoshopMetadataByteCount
> 0)
423 pDEMisc
->uPhotoshopMetadataOffset
= pDEMisc
->uImageOffset
;
424 pDEMisc
->uImageOffset
+= pIE
->cbPhotoshopMetadataByteCount
;
427 if (pIE
->cbEXIFMetadataByteCount
> 0)
429 pDEMisc
->uEXIFMetadataOffset
= pDEMisc
->uImageOffset
;
430 pDEMisc
->uImageOffset
+= (pDEMisc
->uImageOffset
& 1);
431 pDEMisc
->uImageOffset
+= pIE
->cbEXIFMetadataByteCount
;
434 if (pIE
->cbColorContext
> 0)
436 pDEMisc
->uColorProfileOffset
= pDEMisc
->uImageOffset
;
437 pDEMisc
->uImageOffset
+= pIE
->cbColorContext
;
440 if (pIE
->cbGPSInfoMetadataByteCount
> 0)
442 pDEMisc
->uGPSInfoMetadataOffset
= pDEMisc
->uImageOffset
;
443 pDEMisc
->uImageOffset
+= (pDEMisc
->uImageOffset
& 1);
444 pDEMisc
->uImageOffset
+= pIE
->cbGPSInfoMetadataByteCount
;
447 Call(PutUShort(pWS
, offPos
, cWmpDEs
)); offPos
+= 2;
448 Call(pWS
->Write(pWS
, Zero
, SizeofIFDEntry
* cWmpDEs
+ sizeof(U32
)));
452 assert(WMP_tagDocumentName
== wmpDE
.uTag
);
453 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarDocumentName
, &wmpDE
,
454 &uiCurrDescMetadataOffset
, &offPos
));
457 assert(WMP_tagImageDescription
== wmpDE
.uTag
);
458 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarImageDescription
, &wmpDE
,
459 &uiCurrDescMetadataOffset
, &offPos
));
462 assert(WMP_tagCameraMake
== wmpDE
.uTag
);
463 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarCameraMake
, &wmpDE
,
464 &uiCurrDescMetadataOffset
, &offPos
));
467 assert(WMP_tagCameraModel
== wmpDE
.uTag
);
468 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarCameraModel
, &wmpDE
,
469 &uiCurrDescMetadataOffset
, &offPos
));
472 assert(WMP_tagPageName
== wmpDE
.uTag
);
473 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarPageName
, &wmpDE
,
474 &uiCurrDescMetadataOffset
, &offPos
));
477 assert(WMP_tagPageNumber
== wmpDE
.uTag
);
478 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarPageNumber
, &wmpDE
,
479 &uiCurrDescMetadataOffset
, &offPos
));
482 assert(WMP_tagSoftware
== wmpDE
.uTag
);
483 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarSoftware
, &wmpDE
,
484 &uiCurrDescMetadataOffset
, &offPos
));
487 assert(WMP_tagDateTime
== wmpDE
.uTag
);
488 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarDateTime
, &wmpDE
,
489 &uiCurrDescMetadataOffset
, &offPos
));
492 assert(WMP_tagArtist
== wmpDE
.uTag
);
493 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarArtist
, &wmpDE
,
494 &uiCurrDescMetadataOffset
, &offPos
));
497 assert(WMP_tagHostComputer
== wmpDE
.uTag
);
498 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarHostComputer
, &wmpDE
,
499 &uiCurrDescMetadataOffset
, &offPos
));
502 assert(WMP_tagRatingStars
== wmpDE
.uTag
);
503 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarRatingStars
, &wmpDE
,
504 &uiCurrDescMetadataOffset
, &offPos
));
507 assert(WMP_tagRatingValue
== wmpDE
.uTag
);
508 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarRatingValue
, &wmpDE
,
509 &uiCurrDescMetadataOffset
, &offPos
));
512 assert(WMP_tagCopyright
== wmpDE
.uTag
);
513 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarCopyright
, &wmpDE
,
514 &uiCurrDescMetadataOffset
, &offPos
));
517 assert(WMP_tagCaption
== wmpDE
.uTag
);
518 Call(WriteDescMetadata(pIE
, pIE
->sDescMetadata
.pvarCaption
, &wmpDE
,
519 &uiCurrDescMetadataOffset
, &offPos
));
523 assert(WMP_tagXMPMetadata
== wmpDE
.uTag
);
524 if (pIE
->cbXMPMetadataByteCount
> 0)
527 wmpDE
.uCount
= pIE
->cbXMPMetadataByteCount
;
528 wmpDE
.uValueOrOffset
= pDEMisc
->uXMPMetadataOffset
;
529 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, pIE
->pbXMPMetadata
, &uiTemp
));
534 assert(WMP_tagIPTCNAAMetadata
== wmpDE
.uTag
);
535 if (pIE
->cbIPTCNAAMetadataByteCount
> 0)
538 wmpDE
.uCount
= pIE
->cbIPTCNAAMetadataByteCount
;
539 wmpDE
.uValueOrOffset
= pDEMisc
->uIPTCNAAMetadataOffset
;
540 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, pIE
->pbIPTCNAAMetadata
, &uiTemp
));
543 // Photoshop Metadata
545 assert(WMP_tagPhotoshopMetadata
== wmpDE
.uTag
);
546 if (pIE
->cbPhotoshopMetadataByteCount
> 0)
549 wmpDE
.uCount
= pIE
->cbPhotoshopMetadataByteCount
;
550 wmpDE
.uValueOrOffset
= pDEMisc
->uPhotoshopMetadataOffset
;
551 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, pIE
->pbPhotoshopMetadata
, &uiTemp
));
556 assert(WMP_tagEXIFMetadata
== wmpDE
.uTag
);
557 if (pIE
->cbEXIFMetadataByteCount
> 0)
560 if ((pDEMisc
->uEXIFMetadataOffset
& 1) != 0)
562 Call(pWS
->SetPos(pWS
, pDEMisc
->uEXIFMetadataOffset
));
563 Call(pWS
->Write(pWS
, Zero
, 1));
565 pDEMisc
->uEXIFMetadataOffset
+= (pDEMisc
->uEXIFMetadataOffset
& 1);
566 wmpDE
.uValueOrOffset
= pDEMisc
->uEXIFMetadataOffset
;
567 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
569 Call(PKAlloc((void **) &pbEXIFMetadata
, pIE
->cbEXIFMetadataByteCount
));
570 uiTemp
= pDEMisc
->uEXIFMetadataOffset
;
571 Call(BufferCopyIFD(pIE
->pbEXIFMetadata
, pIE
->cbEXIFMetadataByteCount
, 0, WMP_INTEL_ENDIAN
,
572 pbEXIFMetadata
- uiTemp
, uiTemp
+ pIE
->cbEXIFMetadataByteCount
, &uiTemp
));
573 Call(pWS
->SetPos(pWS
, pDEMisc
->uEXIFMetadataOffset
));
574 Call(pWS
->Write(pWS
, pbEXIFMetadata
, pIE
->cbEXIFMetadataByteCount
));
579 assert(WMP_tagIccProfile
== wmpDE
.uTag
);
580 if (pIE
->cbColorContext
> 0)
583 wmpDE
.uCount
= pIE
->cbColorContext
;
584 wmpDE
.uValueOrOffset
= pDEMisc
->uColorProfileOffset
;
585 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, pIE
->pbColorContext
, &uiTemp
));
590 assert(WMP_tagGPSInfoMetadata
== wmpDE
.uTag
);
591 if (pIE
->cbGPSInfoMetadataByteCount
> 0)
594 if ((pDEMisc
->uGPSInfoMetadataOffset
& 1) != 0)
596 Call(pWS
->SetPos(pWS
, pDEMisc
->uGPSInfoMetadataOffset
));
597 Call(pWS
->Write(pWS
, Zero
, 1));
599 pDEMisc
->uGPSInfoMetadataOffset
+= (pDEMisc
->uGPSInfoMetadataOffset
& 1);
600 wmpDE
.uValueOrOffset
= pDEMisc
->uGPSInfoMetadataOffset
;
601 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
603 Call(PKAlloc((void **) &pbGPSInfoMetadata
, pIE
->cbGPSInfoMetadataByteCount
));
604 uiTemp
= pDEMisc
->uGPSInfoMetadataOffset
;
605 Call(BufferCopyIFD(pIE
->pbGPSInfoMetadata
, pIE
->cbGPSInfoMetadataByteCount
, 0, WMP_INTEL_ENDIAN
,
606 pbGPSInfoMetadata
- uiTemp
, uiTemp
+ pIE
->cbGPSInfoMetadataByteCount
, &uiTemp
));
607 Call(pWS
->SetPos(pWS
, pDEMisc
->uGPSInfoMetadataOffset
));
608 Call(pWS
->Write(pWS
, pbGPSInfoMetadata
, pIE
->cbGPSInfoMetadataByteCount
));
612 assert(WMP_tagPixelFormat
== wmpDE
.uTag
);
613 wmpDE
.uValueOrOffset
= pDEMisc
->uOffPixelFormat
;
614 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
617 assert(WMP_tagTransformation
== wmpDE
.uTag
);
618 wmpDE
.uValueOrOffset
= pIE
->WMP
.oOrientation
;
619 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
622 assert(WMP_tagImageWidth
== wmpDE
.uTag
);
623 wmpDE
.uValueOrOffset
= pIE
->uWidth
;
624 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
627 assert(WMP_tagImageHeight
== wmpDE
.uTag
);
628 wmpDE
.uValueOrOffset
= pIE
->uHeight
;
629 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
632 assert(WMP_tagWidthResolution
== wmpDE
.uTag
);
633 *((float *) &wmpDE
.uValueOrOffset
) = pIE
->fResX
;
634 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
637 assert(WMP_tagHeightResolution
== wmpDE
.uTag
);
638 *((float *) &wmpDE
.uValueOrOffset
) = pIE
->fResY
;
639 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
642 assert(WMP_tagImageOffset
== wmpDE
.uTag
);
643 wmpDE
.uValueOrOffset
= pDEMisc
->uImageOffset
;
644 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
646 // fix up in WriteContainerPost()
648 assert(WMP_tagImageByteCount
== wmpDE
.uTag
);
649 pDEMisc
->uOffImageByteCount
= (U32
)offPos
;
650 wmpDE
.uValueOrOffset
= 0;
651 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
653 if (pIE
->WMP
.bHasAlpha
&& pIE
->WMP
.wmiSCP
.uAlphaMode
== 2)
655 // fix up in WriteContainerPost()
657 assert(WMP_tagAlphaOffset
== wmpDE
.uTag
);
658 pDEMisc
->uOffAlphaOffset
= (U32
)offPos
;
659 wmpDE
.uValueOrOffset
= 0;
660 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
662 // fix up in WriteContainerPost()
664 assert(WMP_tagAlphaByteCount
== wmpDE
.uTag
);
665 pDEMisc
->uOffAlphaByteCount
= (U32
)offPos
;
666 wmpDE
.uValueOrOffset
= 0;
667 Call(WriteWmpDE(pWS
, &offPos
, &wmpDE
, NULL
, NULL
));
671 Call(PutULong(pWS
, offPos
, 0)); offPos
+= 4;
673 assert(0 == (offPos
& 1));
674 if (pDEMisc
->uColorProfileOffset
> 0 || pDEMisc
->uDescMetadataOffset
> 0 ||
675 pDEMisc
->uXMPMetadataOffset
> 0 || pDEMisc
->uIPTCNAAMetadataOffset
> 0 ||
676 pDEMisc
->uPhotoshopMetadataOffset
> 0 || pDEMisc
->uEXIFMetadataOffset
> 0 ||
677 pDEMisc
->uGPSInfoMetadataOffset
> 0)
679 assert(pDEMisc
->uColorProfileOffset
== offPos
||
680 pDEMisc
->uDescMetadataOffset
== offPos
||
681 pDEMisc
->uXMPMetadataOffset
== offPos
||
682 pDEMisc
->uIPTCNAAMetadataOffset
== offPos
||
683 pDEMisc
->uPhotoshopMetadataOffset
== offPos
||
684 pDEMisc
->uEXIFMetadataOffset
== offPos
||
685 pDEMisc
->uGPSInfoMetadataOffset
== offPos
);
687 // OK, now skip to image offset
688 Call(pWS
->SetPos(pWS
, pDEMisc
->uImageOffset
));
689 offPos
= pDEMisc
->uImageOffset
;
691 assert(pDEMisc
->uImageOffset
== offPos
);
694 if (pbEXIFMetadata
!= NULL
)
695 PKFree((void **) &pbEXIFMetadata
);
696 if (pbGPSInfoMetadata
!= NULL
)
697 PKFree((void **) &pbGPSInfoMetadata
);
703 ERR
WriteContainerPost(
706 ERR err
= WMP_errSuccess
;
708 struct WMPStream
* pWS
= pIE
->pStream
;
709 WmpDEMisc
* pDEMisc
= &pIE
->WMP
.wmiDEMisc
;
712 WmpDE deImageByteCount
= {WMP_tagImageByteCount
, WMP_typLONG
, 1, 0};
713 WmpDE deAlphaOffset
= {WMP_tagAlphaOffset
, WMP_typLONG
, 1, 0};
714 WmpDE deAlphaByteCount
= {WMP_tagAlphaByteCount
, WMP_typLONG
, 1, 0};
716 deImageByteCount
.uValueOrOffset
= pIE
->WMP
.nCbImage
;
717 offPos
= pDEMisc
->uOffImageByteCount
;
718 Call(WriteWmpDE(pWS
, &offPos
, &deImageByteCount
, NULL
, NULL
));
721 if (pIE
->WMP
.bHasAlpha
&& pIE
->WMP
.wmiSCP
.uAlphaMode
== 2)
723 deAlphaOffset
.uValueOrOffset
= pIE
->WMP
.nOffAlpha
;
724 offPos
= pDEMisc
->uOffAlphaOffset
;
725 Call(WriteWmpDE(pWS
, &offPos
, &deAlphaOffset
, NULL
, NULL
));
727 deAlphaByteCount
.uValueOrOffset
= pIE
->WMP
.nCbAlpha
+ pIE
->WMP
.nOffAlpha
;
728 offPos
= pDEMisc
->uOffAlphaByteCount
;
729 Call(WriteWmpDE(pWS
, &offPos
, &deAlphaByteCount
, NULL
, NULL
));
737 //================================================
738 ERR
PKImageEncode_Initialize_WMP(
740 struct WMPStream
* pStream
,
744 ERR err
= WMP_errSuccess
;
746 FailIf(sizeof(pIE
->WMP
.wmiSCP
) != cbParam
, WMP_errInvalidArgument
);
748 pIE
->WMP
.wmiSCP
= *(CWMIStrCodecParam
*)pvParam
;
749 pIE
->WMP
.wmiSCP_Alpha
= *(CWMIStrCodecParam
*)pvParam
;
750 pIE
->pStream
= pStream
;
752 pIE
->WMP
.wmiSCP
.pWStream
= pIE
->pStream
;
753 pIE
->WMP
.wmiSCP_Alpha
.pWStream
= pIE
->pStream
;
759 ERR
PKImageEncode_Terminate_WMP(
762 ERR err
= WMP_errSuccess
;
763 UNREFERENCED_PARAMETER( pIE
);
768 ERR
PKImageEncode_EncodeContent_Init(
775 ERR err
= WMP_errSuccess
;
778 pIE
->WMP
.wmiI
.cWidth
= pIE
->uWidth
;
779 pIE
->WMP
.wmiI
.cHeight
= pIE
->uHeight
;
780 pIE
->WMP
.wmiI
.bdBitDepth
= PI
.bdBitDepth
;
781 pIE
->WMP
.wmiI
.cBitsPerUnit
= PI
.cbitUnit
;
782 pIE
->WMP
.wmiI
.bRGB
= !(PI
.grBit
& PK_pixfmtBGR
);
783 pIE
->WMP
.wmiI
.cfColorFormat
= PI
.cfColorFormat
;
784 pIE
->WMP
.wmiI
.oOrientation
= pIE
->WMP
.oOrientation
;
786 // Set the fPaddedUserBuffer if the following conditions are met
787 if (0 == ((size_t)pbPixels
% 128) && // Frame buffer is aligned to 128-byte boundary
788 0 == (pIE
->uWidth
% 16) && // Horizontal resolution is multiple of 16
789 0 == (cLine
% 16) && // Vertical resolution is multiple of 16
790 0 == (cbStride
% 128)) // Stride is a multiple of 128 bytes
792 pIE
->WMP
.wmiI
.fPaddedUserBuffer
= TRUE
;
793 // Note that there are additional conditions in strenc_x86.c's strEncOpt
794 // which could prevent optimization from being engaged
797 //if (pIE->WMP.bHasAlpha)
799 // pIE->WMP.wmiSCP.cChannel = PI.cChannel - 1;
800 // pIE->WMP.wmiI.cfColorFormat = PI.cfStripAlpha;
804 if(PI
.cfColorFormat
== NCOMPONENT
&& (!(PI
.grBit
& PK_pixfmtHasAlpha
)))//N-channel without Alpha
805 pIE
->WMP
.wmiSCP
.cChannel
= PI
.cChannel
;
807 pIE
->WMP
.wmiSCP
.cChannel
= PI
.cChannel
- 1;//other formats and (N-channel + Alpha)
809 pIE
->idxCurrentLine
= 0;
811 pIE
->WMP
.wmiSCP
.fMeasurePerf
= TRUE
;
812 FailIf(ICERR_OK
!= ImageStrEncInit(&pIE
->WMP
.wmiI
, &pIE
->WMP
.wmiSCP
, &pIE
->WMP
.ctxSC
), WMP_errFail
);
818 ERR
PKImageEncode_EncodeContent_Encode(
824 ERR err
= WMP_errSuccess
;
827 //================================
828 for (i
= 0; i
< cLine
; i
+= 16)
830 Bool f420
= ( pIE
->WMP
.wmiI
.cfColorFormat
== YUV_420
||
831 (pIE
->WMP
.wmiSCP
.bYUVData
&& pIE
->WMP
.wmiSCP
.cfColorFormat
==YUV_420
) );
832 CWMImageBufferInfo wmiBI
= { 0 };
833 wmiBI
.pv
= pbPixels
+ cbStride
* i
/ (f420
? 2 : 1);
834 wmiBI
.cLine
= min(16, cLine
- i
);
835 wmiBI
.cbStride
= cbStride
;
836 FailIf(ICERR_OK
!= ImageStrEncEncode(pIE
->WMP
.ctxSC
, &wmiBI
), WMP_errFail
);
838 pIE
->idxCurrentLine
+= cLine
;
844 ERR
PKImageEncode_EncodeContent_Term(PKImageEncode
* pIE
)
846 ERR err
= WMP_errSuccess
;
848 FailIf(ICERR_OK
!= ImageStrEncTerm(pIE
->WMP
.ctxSC
), WMP_errFail
);
854 ERR
PKImageEncode_EncodeContent(
861 ERR err
= WMP_errSuccess
;
864 Call(pIE
->pStream
->GetPos(pIE
->pStream
, &offPos
));
865 pIE
->WMP
.nOffImage
= (Long
)offPos
;
867 Call(PKImageEncode_EncodeContent_Init(pIE
, PI
, cLine
, pbPixels
, cbStride
));
868 Call(PKImageEncode_EncodeContent_Encode(pIE
, cLine
, pbPixels
, cbStride
));
869 Call(PKImageEncode_EncodeContent_Term(pIE
));
871 Call(pIE
->pStream
->GetPos(pIE
->pStream
, &offPos
));
872 pIE
->WMP
.nCbImage
= (Long
)offPos
- pIE
->WMP
.nOffImage
;
879 ERR
PKImageEncode_EncodeAlpha_Init(
886 ERR err
= WMP_errSuccess
;
888 UNREFERENCED_PARAMETER( cLine
);
889 UNREFERENCED_PARAMETER( pbPixels
);
890 UNREFERENCED_PARAMETER( cbStride
);
892 pIE
->WMP
.wmiI_Alpha
= pIE
->WMP
.wmiI
;
894 pIE
->WMP
.wmiI_Alpha
.cWidth
= pIE
->uWidth
;
895 pIE
->WMP
.wmiI_Alpha
.cHeight
= pIE
->uHeight
;
896 pIE
->WMP
.wmiI_Alpha
.bdBitDepth
= PI
.bdBitDepth
;
897 pIE
->WMP
.wmiI_Alpha
.cBitsPerUnit
= PI
.cbitUnit
;
898 pIE
->WMP
.wmiI_Alpha
.bRGB
= !(PI
.grBit
& PK_pixfmtBGR
);
899 pIE
->WMP
.wmiI
.oOrientation
= pIE
->WMP
.oOrientation
;
900 // pIE->WMP.wmiI_Alpha.cLeadingPadding += pIE->WMP.wmiSCP.cChannel;
901 // pIE->WMP.wmiI_Alpha.cLeadingPadding += PI.cChannel - 1;
903 switch (pIE
->WMP
.wmiI
.bdBitDepth
)
906 pIE
->WMP
.wmiI_Alpha
.cLeadingPadding
+= (pIE
->WMP
.wmiI
.cBitsPerUnit
>> 3) - 1;
912 pIE
->WMP
.wmiI_Alpha
.cLeadingPadding
+= (pIE
->WMP
.wmiI
.cBitsPerUnit
>> 3) / sizeof(U16
) - 1;
918 pIE
->WMP
.wmiI_Alpha
.cLeadingPadding
+= (pIE
->WMP
.wmiI
.cBitsPerUnit
>> 3) / sizeof(float) - 1;
928 // pIE->WMP.wmiSCP_Alpha.uAlphaMode = 1;
931 //assert(pIE->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now!
932 pIE
->WMP
.wmiI_Alpha
.cfColorFormat
= Y_ONLY
;
934 pIE
->WMP
.wmiSCP_Alpha
.cfColorFormat
= Y_ONLY
;
936 pIE
->idxCurrentLine
= 0;
937 pIE
->WMP
.wmiSCP_Alpha
.fMeasurePerf
= TRUE
;
938 FailIf(ICERR_OK
!= ImageStrEncInit(&pIE
->WMP
.wmiI_Alpha
, &pIE
->WMP
.wmiSCP_Alpha
, &pIE
->WMP
.ctxSC_Alpha
), WMP_errFail
);
944 ERR
PKImageEncode_EncodeAlpha_Encode(
950 ERR err
= WMP_errSuccess
;
953 //================================
954 for (i
= 0; i
< cLine
; i
+= 16)
956 CWMImageBufferInfo wmiBI
= { 0 };
957 wmiBI
.pv
= pbPixels
+ cbStride
* i
;
958 wmiBI
.cLine
= min(16, cLine
- i
);
959 wmiBI
.cbStride
= cbStride
;
960 FailIf(ICERR_OK
!= ImageStrEncEncode(pIE
->WMP
.ctxSC_Alpha
, &wmiBI
), WMP_errFail
);
962 pIE
->idxCurrentLine
+= cLine
;
968 ERR
PKImageEncode_EncodeAlpha_Term(PKImageEncode
* pIE
)
970 ERR err
= WMP_errSuccess
;
972 FailIf(ICERR_OK
!= ImageStrEncTerm(pIE
->WMP
.ctxSC_Alpha
), WMP_errFail
);
978 ERR
PKImageEncode_EncodeAlpha(
985 ERR err
= WMP_errSuccess
;
988 Call(pIE
->pStream
->GetPos(pIE
->pStream
, &offPos
));
989 if ((offPos
& 1) != 0)
991 // Make the mark even if it is odd by inserting a pad byte
993 Call(pIE
->pStream
->Write(pIE
->pStream
, &zero
, 1));
996 pIE
->WMP
.nOffAlpha
= (Long
)offPos
;
998 Call(PKImageEncode_EncodeAlpha_Init(pIE
, PI
, cLine
, pbPixels
, cbStride
));
999 Call(PKImageEncode_EncodeAlpha_Encode(pIE
, cLine
, pbPixels
, cbStride
));
1000 Call(PKImageEncode_EncodeAlpha_Term(pIE
));
1002 Call(pIE
->pStream
->GetPos(pIE
->pStream
, &offPos
));
1003 pIE
->WMP
.nCbAlpha
= (Long
)offPos
- pIE
->WMP
.nOffAlpha
;
1011 static ERR
SetMetadata(PKImageEncode
*pIE
, const U8
*pbMetadata
, U32 cbMetadata
, U8
** pbSet
, U32
* pcbSet
)
1013 ERR err
= WMP_errSuccess
;
1015 // Fail if the caller called us after we've already written the header out
1016 if (pIE
->fHeaderDone
)
1018 assert(FALSE
); // Message to programmer
1019 err
= WMP_errOutOfSequence
;
1023 // Make a copy of the metadata
1024 PKFree((void **) pbSet
);
1027 Call(PKAlloc((void **) pbSet
, cbMetadata
));
1028 memcpy(*pbSet
, pbMetadata
, cbMetadata
);
1029 *pcbSet
= cbMetadata
;
1037 ERR
PKImageEncode_SetColorContext_WMP(PKImageEncode
*pIE
,
1038 const U8
*pbColorContext
,
1041 return SetMetadata(pIE
, pbColorContext
, cbColorContext
, &pIE
->pbColorContext
, &pIE
->cbColorContext
);
1046 ERR
PKImageEncode_SetXMPMetadata_WMP(PKImageEncode
*pIE
, const U8
*pbXMPMetadata
, U32 cbXMPMetadata
)
1047 { // same as the other Set's, but make sure dc:format is <dc:format>image/vnd.ms-photo</dc:format>
1048 ERR err
= WMP_errSuccess
;
1051 char* pszFormatBegin
;
1052 // const char* pszXMPMetadata = (const char*)pbXMPMetadata;
1055 // Fail if the caller called us after we've already written the header out
1056 FailIf(pIE
->fHeaderDone
, WMP_errOutOfSequence
);
1058 // Free any previously set XMP metadata
1059 PKFree((void **) &pIE
->pbXMPMetadata
);
1060 pIE
->cbXMPMetadataByteCount
= 0;
1062 // allocate a block big enough for data passed in plus added trailing null plus added HD Photo dc:format
1063 // there may already be a trailing null (but ps doesn't seem to)
1064 // there may already be a dc:format we will replace with HD Photo's
1065 // but anyway this block will be large enough guaranteed
1066 cbBuffer
= cbXMPMetadata
+ 1 + sizeof("<dc:format>") - 1 + sizeof("</dc:format>") - 1 + sizeof(szHDPhotoFormat
) - 1;
1067 Call(PKAlloc((void **) &pbTemp
, cbBuffer
));
1068 memcpy(pbTemp
, pbXMPMetadata
, cbXMPMetadata
); // Make a copy of the metadata
1069 pbTemp
[cbXMPMetadata
] = '\0';
1070 cbXMPMetadata
= (U32
)strlen(pbTemp
);
1071 pszFormatBegin
= strstr(pbTemp
, "<dc:format>");
1072 if ( pszFormatBegin
!= 0 )
1075 const char* pszLessThan
;
1077 pszFormatEnd
= strstr(pszFormatBegin
, "</dc:format>");
1078 FailIf(pszFormatEnd
== 0, WMP_errFail
);
1079 pszLessThan
= strchr(pszFormatBegin
+ sizeof("<dc:format>") - 1, '<');
1080 FailIf(pszLessThan
!= pszFormatEnd
, WMP_errFail
);
1081 pszFormatEnd
+= sizeof("</dc:format>") - 1;
1083 // photoshop doesn't put a trailing null, so we don't either
1084 // hd and tiff don't put a trailing null, so we don't either
1085 cbTemp
= cbXMPMetadata
- (U32
) ( pszFormatEnd
- pszFormatBegin
) + sizeof(szHDPhotoFormat
) - 1;
1086 assert(cbTemp
<= cbBuffer
);
1087 FailIf(0 != STRCPY_SAFE(pszFormatBegin
,
1088 cbBuffer
- (pszFormatBegin
- pbTemp
),
1090 WMP_errBufferOverflow
);
1091 memcpy(pszFormatBegin
+ sizeof(szHDPhotoFormat
) - 1, pbXMPMetadata
+ ( pszFormatEnd
- pbTemp
),
1092 cbXMPMetadata
- ( pszFormatEnd
- pbTemp
));
1096 cbTemp
= cbXMPMetadata
;
1099 pIE
->pbXMPMetadata
= (U8
*) pbTemp
;
1100 pIE
->cbXMPMetadataByteCount
= cbTemp
;
1104 PKFree((void **) &pbTemp
);
1105 pIE
->cbXMPMetadataByteCount
= 0;
1111 ERR
PKImageEncode_SetEXIFMetadata_WMP(PKImageEncode
*pIE
, const U8
*pbEXIFMetadata
, U32 cbEXIFMetadata
)
1113 return SetMetadata(pIE
, pbEXIFMetadata
, cbEXIFMetadata
,
1114 &pIE
->pbEXIFMetadata
, &pIE
->cbEXIFMetadataByteCount
);
1119 ERR
PKImageEncode_SetGPSInfoMetadata_WMP(PKImageEncode
*pIE
, const U8
*pbGPSInfoMetadata
, U32 cbGPSInfoMetadata
)
1121 return SetMetadata(pIE
, pbGPSInfoMetadata
, cbGPSInfoMetadata
,
1122 &pIE
->pbGPSInfoMetadata
, &pIE
->cbGPSInfoMetadataByteCount
);
1127 ERR
PKImageEncode_SetIPTCNAAMetadata_WMP(PKImageEncode
*pIE
, const U8
*pbIPTCNAAMetadata
, U32 cbIPTCNAAMetadata
)
1129 return SetMetadata(pIE
, pbIPTCNAAMetadata
, cbIPTCNAAMetadata
,
1130 &pIE
->pbIPTCNAAMetadata
, &pIE
->cbIPTCNAAMetadataByteCount
);
1135 ERR
PKImageEncode_SetPhotoshopMetadata_WMP(PKImageEncode
*pIE
, const U8
*pbPhotoshopMetadata
, U32 cbPhotoshopMetadata
)
1137 return SetMetadata(pIE
, pbPhotoshopMetadata
, cbPhotoshopMetadata
,
1138 &pIE
->pbPhotoshopMetadata
, &pIE
->cbPhotoshopMetadataByteCount
);
1143 ERR
PKImageEncode_SetDescriptiveMetadata_WMP(PKImageEncode
*pIE
, const DESCRIPTIVEMETADATA
*pSrcMeta
)
1145 ERR err
= WMP_errSuccess
;
1146 DESCRIPTIVEMETADATA
*pDstMeta
= &pIE
->sDescMetadata
;
1148 // Fail if the caller called us after we've already written the header out
1149 if (pIE
->fHeaderDone
)
1151 assert(FALSE
); // Message to programmer
1152 FailIf(TRUE
, WMP_errOutOfSequence
);
1155 // Make a copy of the descriptive metadata
1156 Call(CopyDescMetadata(&pDstMeta
->pvarImageDescription
, pSrcMeta
->pvarImageDescription
));
1157 Call(CopyDescMetadata(&pDstMeta
->pvarCameraMake
, pSrcMeta
->pvarCameraMake
));
1158 Call(CopyDescMetadata(&pDstMeta
->pvarCameraModel
, pSrcMeta
->pvarCameraModel
));
1159 Call(CopyDescMetadata(&pDstMeta
->pvarSoftware
, pSrcMeta
->pvarSoftware
));
1160 Call(CopyDescMetadata(&pDstMeta
->pvarDateTime
, pSrcMeta
->pvarDateTime
));
1161 Call(CopyDescMetadata(&pDstMeta
->pvarArtist
, pSrcMeta
->pvarArtist
));
1162 Call(CopyDescMetadata(&pDstMeta
->pvarCopyright
, pSrcMeta
->pvarCopyright
));
1163 Call(CopyDescMetadata(&pDstMeta
->pvarRatingStars
, pSrcMeta
->pvarRatingStars
));
1164 Call(CopyDescMetadata(&pDstMeta
->pvarRatingValue
, pSrcMeta
->pvarRatingValue
));
1165 Call(CopyDescMetadata(&pDstMeta
->pvarCaption
, pSrcMeta
->pvarCaption
));
1166 Call(CopyDescMetadata(&pDstMeta
->pvarDocumentName
, pSrcMeta
->pvarDocumentName
));
1167 Call(CopyDescMetadata(&pDstMeta
->pvarPageName
, pSrcMeta
->pvarPageName
));
1168 Call(CopyDescMetadata(&pDstMeta
->pvarPageNumber
, pSrcMeta
->pvarPageNumber
));
1169 Call(CopyDescMetadata(&pDstMeta
->pvarHostComputer
, pSrcMeta
->pvarHostComputer
));
1177 ERR
PKImageEncode_WritePixels_WMP(
1183 ERR err
= WMP_errSuccess
;
1187 // Performing non-banded encode
1188 assert(BANDEDENCSTATE_UNINITIALIZED
== pIE
->WMP
.eBandedEncState
);
1189 pIE
->WMP
.eBandedEncState
= BANDEDENCSTATE_NONBANDEDENCODE
;
1191 PI
.pGUIDPixFmt
= &pIE
->guidPixFormat
;
1192 PixelFormatLookup(&PI
, LOOKUP_FORWARD
);
1193 pIE
->WMP
.bHasAlpha
= !!(PI
.grBit
& PK_pixfmtHasAlpha
);
1195 if (!pIE
->fHeaderDone
)
1198 Call(WriteContainerPre(pIE
));
1200 pIE
->fHeaderDone
= !FALSE
;
1203 /* if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2){
1204 pIE->WMP.wmiSCP_Alpha = pIE->WMP.wmiSCP;
1207 Call(PKImageEncode_EncodeContent(pIE
, PI
, cLine
, pbPixels
, cbStride
));
1208 if (pIE
->WMP
.bHasAlpha
&& pIE
->WMP
.wmiSCP
.uAlphaMode
== 2){//planar alpha
1209 Call(PKImageEncode_EncodeAlpha(pIE
, PI
, cLine
, pbPixels
, cbStride
));
1212 Call(WriteContainerPost(pIE
));
1219 ERR
PKImageEncode_WritePixelsBandedBegin_WMP(PKImageEncode
* pIE
, struct WMPStream
*pPATempFile
)
1221 ERR err
= WMP_errSuccess
;
1223 // Just make sure that we are in the correct state to begin a banded decode
1224 assert(BANDEDENCSTATE_UNINITIALIZED
== pIE
->WMP
.eBandedEncState
);
1225 pIE
->WMP
.eBandedEncState
= BANDEDENCSTATE_INIT
;
1227 // Save the planar alpha tempfile for future use
1228 pIE
->WMP
.pPATempFile
= pPATempFile
;
1234 ERR
PKImageEncode_WritePixelsBanded_WMP(PKImageEncode
* pIE
, U32 cLine
, U8
* pbPixels
, U32 cbStride
, Bool fLastCall
)
1236 ERR err
= WMP_errSuccess
;
1237 PKPixelInfo PI
= {0};
1239 BANDEDENCSTATE eEncStateOrig
= pIE
->WMP
.eBandedEncState
;
1240 struct WMPStream
*pPATempFile
= pIE
->WMP
.pPATempFile
;
1242 // Unless this is the last call, reject inputs which are not multiples of 16
1243 FailIf(!fLastCall
&& 0 != cLine
% 16, WMP_errMustBeMultipleOf16LinesUntilLastCall
);
1245 if (!pIE
->fHeaderDone
|| BANDEDENCSTATE_INIT
== pIE
->WMP
.eBandedEncState
)
1247 PI
.pGUIDPixFmt
= &pIE
->guidPixFormat
;
1248 PixelFormatLookup(&PI
, LOOKUP_FORWARD
);
1249 pIE
->WMP
.bHasAlpha
= !!(PI
.grBit
& PK_pixfmtHasAlpha
);
1252 // Check if this is planar alpha: banded encode requires temp file
1253 if (pIE
->WMP
.bHasAlpha
&& pIE
->WMP
.wmiSCP
.uAlphaMode
== 2)
1255 FailIf(NULL
== pPATempFile
, WMP_errPlanarAlphaBandedEncRequiresTempFile
);
1259 if (!pIE
->fHeaderDone
)
1263 Call(WriteContainerPre(pIE
));
1264 pIE
->fHeaderDone
= !FALSE
;
1267 if (BANDEDENCSTATE_INIT
== pIE
->WMP
.eBandedEncState
)
1269 // Record start of main content for future call to WriteContainerPost
1271 Call(pIE
->pStream
->GetPos(pIE
->pStream
, &offPos
));
1272 pIE
->WMP
.nOffImage
= (Long
)offPos
;
1275 Call(PKImageEncode_EncodeContent_Init(pIE
, PI
, cLine
, pbPixels
, cbStride
));
1276 pIE
->WMP
.eBandedEncState
= BANDEDENCSTATE_ENCODING
;
1279 Call(PKImageEncode_EncodeContent_Encode(pIE
, cLine
, pbPixels
, cbStride
));
1280 if (pIE
->WMP
.bHasAlpha
&& pIE
->WMP
.wmiSCP
.uAlphaMode
== 2)
1283 if (BANDEDENCSTATE_INIT
== eEncStateOrig
)
1287 // We assume the following which allows us to avoid saving state
1288 Call(pPATempFile
->GetPos(pPATempFile
, &offStart
));
1289 assert(0 == offStart
);
1290 assert(pIE
->WMP
.wmiSCP_Alpha
.pWStream
== pIE
->WMP
.wmiSCP
.pWStream
);
1292 // For planar alpha, we write the file to a temp file
1293 pIE
->WMP
.wmiSCP_Alpha
.pWStream
= pPATempFile
;
1294 Call(PKImageEncode_EncodeAlpha_Init(pIE
, PI
, cLine
, pbPixels
, cbStride
));
1297 Call(PKImageEncode_EncodeAlpha_Encode(pIE
, cLine
, pbPixels
, cbStride
));
1304 ERR
PKImageEncode_WritePixelsBandedEnd_WMP(PKImageEncode
* pIE
)
1306 ERR err
= WMP_errSuccess
;
1307 struct WMPStream
*pMainStream
= pIE
->WMP
.wmiSCP
.pWStream
;
1310 assert(BANDEDENCSTATE_ENCODING
== pIE
->WMP
.eBandedEncState
);
1312 // Finish off main content, update its length ptr for WriteContainerPost
1313 Call(PKImageEncode_EncodeContent_Term(pIE
));
1314 Call(pMainStream
->GetPos(pIE
->pStream
, &offAlpha
));
1315 pIE
->WMP
.nCbImage
= (Long
)offAlpha
- pIE
->WMP
.nOffImage
;
1317 if (pIE
->WMP
.bHasAlpha
&& pIE
->WMP
.wmiSCP
.uAlphaMode
== 2)
1320 size_t cbBytesCopied
;
1321 struct WMPStream
*pAlphaStream
= pIE
->WMP
.wmiSCP_Alpha
.pWStream
;
1323 assert(pAlphaStream
!= pMainStream
); // Otherwise we didn't use a temp file
1325 // Close it up - this causes write to temp file
1326 Call(PKImageEncode_EncodeAlpha_Term(pIE
));
1328 // Calculate size of alpha bitstream and its new offset
1329 Call(pAlphaStream
->GetPos(pAlphaStream
, &cbAlpha
));
1331 // Copy alpha bitstream to end of main stream
1333 Call(pAlphaStream
->SetPos(pAlphaStream
, 0));
1334 while (cbBytesCopied
< cbAlpha
)
1336 char rgbBuf
[TEMPFILE_COPYBUF_SIZE
];
1339 cbCopy
= min(sizeof(rgbBuf
), cbAlpha
- cbBytesCopied
);
1340 Call(pAlphaStream
->Read(pAlphaStream
, rgbBuf
, cbCopy
));
1341 Call(pMainStream
->Write(pMainStream
, rgbBuf
, cbCopy
));
1343 cbBytesCopied
+= cbCopy
;
1345 assert(cbBytesCopied
== cbAlpha
);
1347 // Update alpha offset/length for WriteContainerPost
1348 pIE
->WMP
.nOffAlpha
= (Long
)offAlpha
;
1349 pIE
->WMP
.nCbAlpha
= (Long
)cbAlpha
;
1352 Call(WriteContainerPost(pIE
));
1359 ERR
PKImageEncode_Transcode_WMP(
1362 CWMTranscodingParam
* pParam
)
1364 ERR err
= WMP_errSuccess
;
1365 Float fResX
= 0, fResY
= 0;
1366 PKPixelFormatGUID pixGUID
= {0};
1367 CWMTranscodingParam tcParamAlpha
;
1372 struct WMPStream
* pWSDec
= NULL
;
1373 struct WMPStream
* pWSEnc
= pIE
->pStream
;
1375 // pass through metadata
1376 Call(pID
->GetPixelFormat(pID
, &pixGUID
));
1377 Call(pIE
->SetPixelFormat(pIE
, pixGUID
));
1379 Call(pIE
->SetSize(pIE
, (I32
)pParam
->cWidth
, (I32
)pParam
->cHeight
));
1381 Call(pID
->GetResolution(pID
, &fResX
, &fResY
));
1382 Call(pIE
->SetResolution(pIE
, fResX
, fResY
));
1384 PI
.pGUIDPixFmt
= &pIE
->guidPixFormat
;
1385 PixelFormatLookup(&PI
, LOOKUP_FORWARD
);
1386 pIE
->WMP
.bHasAlpha
= !!(PI
.grBit
& PK_pixfmtHasAlpha
) && (2 == pParam
->uAlphaMode
);
1387 assert(0 == pIE
->WMP
.bHasAlpha
|| (pParam
->uAlphaMode
== 2)); // Decode alpha mode does not match encode alpha mode!
1389 // Check for any situations where transcoder is being asked to convert alpha - we can't do this
1390 // NOTE: Decoder's bHasAlpha parameter really means, "has PLANAR alpha"
1391 PI
.pGUIDPixFmt
= &pixGUID
;
1392 PixelFormatLookup(&PI
, LOOKUP_FORWARD
);
1393 FailIf(0 == (PI
.grBit
& PK_pixfmtHasAlpha
) && pParam
->uAlphaMode
!= 0,
1394 WMP_errAlphaModeCannotBeTranscoded
); // Destination is planar/interleaved, src has no alpha
1395 FailIf(!!(PI
.grBit
& PK_pixfmtHasAlpha
) && 2 == pParam
->uAlphaMode
&&
1396 FALSE
== pID
->WMP
.bHasAlpha
, WMP_errAlphaModeCannotBeTranscoded
); // Destination is planar, src is interleaved
1397 FailIf(!!(PI
.grBit
& PK_pixfmtHasAlpha
) && 3 == pParam
->uAlphaMode
&&
1398 pID
->WMP
.bHasAlpha
, WMP_errAlphaModeCannotBeTranscoded
); // Destination is interleaved, src is planar
1399 assert(/*pParam->uAlphaMode >= 0 &&*/ pParam
->uAlphaMode
<= 3); // All the above statements make this assumption
1401 fPlanarAlpha
= pIE
->WMP
.bHasAlpha
&& (2 == pParam
->uAlphaMode
);
1404 Call(WriteContainerPre(pIE
));
1406 // Copy transcoding params for alpha (codec changes the struct)
1408 tcParamAlpha
= *pParam
;
1410 // write compressed bitstream
1411 Call(pID
->GetRawStream(pID
, &pWSDec
));
1413 FailIf(ICERR_OK
!= WMPhotoTranscode(pWSDec
, pWSEnc
, pParam
), WMP_errFail
);
1414 Call(pIE
->pStream
->GetPos(pIE
->pStream
, &offPos
));
1415 pIE
->WMP
.nCbImage
= (Long
)offPos
- pIE
->WMP
.nOffImage
;
1419 pIE
->WMP
.nOffAlpha
= (Long
)offPos
;
1421 // Cue the stream to alpha block
1422 assert(pID
->WMP
.wmiDEMisc
.uAlphaOffset
> 0);
1423 Call(pWSDec
->SetPos(pWSDec
, pID
->WMP
.wmiDEMisc
.uAlphaOffset
));
1425 FailIf(ICERR_OK
!= WMPhotoTranscode(pWSDec
, pWSEnc
, &tcParamAlpha
), WMP_errFail
);
1426 Call(pIE
->pStream
->GetPos(pIE
->pStream
, &offPos
));
1427 pIE
->WMP
.nCbAlpha
= (Long
)offPos
- pIE
->WMP
.nOffAlpha
;
1431 Call(WriteContainerPost(pIE
));
1437 ERR
PKImageEncode_CreateNewFrame_WMP(
1442 ERR err
= WMP_errSuccess
;
1444 UNREFERENCED_PARAMETER( pIE
);
1445 UNREFERENCED_PARAMETER( pvParam
);
1446 UNREFERENCED_PARAMETER( cbParam
);
1448 Call(WMP_errNotYetImplemented
);
1454 ERR
PKImageEncode_Release_WMP(
1455 PKImageEncode
** ppIE
)
1457 ERR err
= WMP_errSuccess
;
1459 PKImageEncode
*pIE
= *ppIE
;
1460 pIE
->pStream
->Close(&pIE
->pStream
);
1462 PKFree((void **) &pIE
->pbColorContext
);
1463 pIE
->cbColorContext
= 0;
1464 PKFree((void **) &pIE
->pbXMPMetadata
);
1465 pIE
->cbXMPMetadataByteCount
= 0;
1466 PKFree((void **) &pIE
->pbEXIFMetadata
);
1467 pIE
->cbEXIFMetadataByteCount
= 0;
1468 PKFree((void **) &pIE
->pbGPSInfoMetadata
);
1469 pIE
->cbGPSInfoMetadataByteCount
= 0;
1470 PKFree((void **) &pIE
->pbIPTCNAAMetadata
);
1471 pIE
->cbIPTCNAAMetadataByteCount
= 0;
1472 PKFree((void **) &pIE
->pbPhotoshopMetadata
);
1473 pIE
->cbPhotoshopMetadataByteCount
= 0;
1475 // Free descriptive metadata
1476 FreeDescMetadata(&pIE
->sDescMetadata
.pvarImageDescription
);
1477 FreeDescMetadata(&pIE
->sDescMetadata
.pvarCameraMake
);
1478 FreeDescMetadata(&pIE
->sDescMetadata
.pvarCameraModel
);
1479 FreeDescMetadata(&pIE
->sDescMetadata
.pvarSoftware
);
1480 FreeDescMetadata(&pIE
->sDescMetadata
.pvarDateTime
);
1481 FreeDescMetadata(&pIE
->sDescMetadata
.pvarArtist
);
1482 FreeDescMetadata(&pIE
->sDescMetadata
.pvarCopyright
);
1483 FreeDescMetadata(&pIE
->sDescMetadata
.pvarRatingStars
);
1484 FreeDescMetadata(&pIE
->sDescMetadata
.pvarRatingValue
);
1485 FreeDescMetadata(&pIE
->sDescMetadata
.pvarCaption
);
1486 FreeDescMetadata(&pIE
->sDescMetadata
.pvarDocumentName
);
1487 FreeDescMetadata(&pIE
->sDescMetadata
.pvarPageName
);
1488 FreeDescMetadata(&pIE
->sDescMetadata
.pvarPageNumber
);
1489 FreeDescMetadata(&pIE
->sDescMetadata
.pvarHostComputer
);
1491 Call(PKFree((void **) ppIE
));
1497 //----------------------------------------------------------------
1498 ERR
PKImageEncode_Create_WMP(PKImageEncode
** ppIE
)
1500 ERR err
= WMP_errSuccess
;
1502 PKImageEncode
* pIE
= NULL
;
1504 Call(PKImageEncode_Create(ppIE
));
1507 pIE
->Initialize
= PKImageEncode_Initialize_WMP
;
1508 pIE
->Terminate
= PKImageEncode_Terminate_WMP
;
1509 pIE
->SetColorContext
= PKImageEncode_SetColorContext_WMP
;
1510 pIE
->SetDescriptiveMetadata
= PKImageEncode_SetDescriptiveMetadata_WMP
;
1511 pIE
->WritePixels
= PKImageEncode_WritePixels_WMP
;
1513 pIE
->WritePixelsBandedBegin
= PKImageEncode_WritePixelsBandedBegin_WMP
;
1514 pIE
->WritePixelsBanded
= PKImageEncode_WritePixelsBanded_WMP
;
1515 pIE
->WritePixelsBandedEnd
= PKImageEncode_WritePixelsBandedEnd_WMP
;
1517 pIE
->Transcode
= PKImageEncode_Transcode_WMP
;
1518 pIE
->CreateNewFrame
= PKImageEncode_CreateNewFrame_WMP
;
1519 pIE
->Release
= PKImageEncode_Release_WMP
;
1527 //================================================================
1528 // PKImageDecode_WMP
1529 //================================================================
1537 ERR err
= WMP_errSuccess
;
1538 ERR errTmp
= WMP_errSuccess
;
1540 struct WMPStream
* pWS
= pID
->pStream
;
1541 // size_t offPos = 0;
1548 //================================
1551 case WMP_tagPixelFormat
:
1553 unsigned char *pGuid
= (unsigned char *) &pID
->guidPixFormat
;
1554 /** following code is endian-agnostic **/
1555 Call(GetULong(pWS
, uValue
, (U32
*)pGuid
));
1556 Call(GetUShort(pWS
, uValue
+ 4, (unsigned short *)(pGuid
+ 4)));
1557 Call(GetUShort(pWS
, uValue
+ 6, (unsigned short *)(pGuid
+ 6)));
1558 Call(pWS
->Read(pWS
, pGuid
+ 8, 8));
1560 PI
.pGUIDPixFmt
= &pID
->guidPixFormat
;
1561 PixelFormatLookup(&PI
, LOOKUP_FORWARD
);
1563 pID
->WMP
.bHasAlpha
= !!(PI
.grBit
& PK_pixfmtHasAlpha
);
1564 pID
->WMP
.wmiI
.cBitsPerUnit
= PI
.cbitUnit
;
1565 pID
->WMP
.wmiI
.bRGB
= !(PI
.grBit
& PK_pixfmtBGR
);
1570 case WMP_tagTransformation
:
1571 FailIf(1 != uCount
, WMP_errUnsupportedFormat
);
1572 assert(uValue
< O_MAX
);
1573 pID
->WMP
.fOrientationFromContainer
= TRUE
;
1574 pID
->WMP
.oOrientationFromContainer
= uValue
;
1577 case WMP_tagImageWidth
:
1578 FailIf(0 == uValue
, WMP_errUnsupportedFormat
);
1581 case WMP_tagImageHeight
:
1582 FailIf(0 == uValue
, WMP_errUnsupportedFormat
);
1585 case WMP_tagImageOffset
:
1586 FailIf(1 != uCount
, WMP_errUnsupportedFormat
);
1587 pID
->WMP
.wmiDEMisc
.uImageOffset
= uValue
;
1590 case WMP_tagImageByteCount
:
1591 FailIf(1 != uCount
, WMP_errUnsupportedFormat
);
1592 pID
->WMP
.wmiDEMisc
.uImageByteCount
= uValue
;
1595 case WMP_tagAlphaOffset
:
1596 FailIf(1 != uCount
, WMP_errUnsupportedFormat
);
1597 pID
->WMP
.wmiDEMisc
.uAlphaOffset
= uValue
;
1600 case WMP_tagAlphaByteCount
:
1601 FailIf(1 != uCount
, WMP_errUnsupportedFormat
);
1602 pID
->WMP
.wmiDEMisc
.uAlphaByteCount
= uValue
;
1605 case WMP_tagWidthResolution
:
1606 FailIf(1 != uCount
, WMP_errUnsupportedFormat
);
1607 ufValue
.uVal
= uValue
;
1608 pID
->fResX
= ufValue
.fVal
;
1611 case WMP_tagHeightResolution
:
1612 FailIf(1 != uCount
, WMP_errUnsupportedFormat
);
1613 ufValue
.uVal
= uValue
;
1614 pID
->fResY
= ufValue
.fVal
;
1617 case WMP_tagIccProfile
:
1618 pID
->WMP
.wmiDEMisc
.uColorProfileByteCount
= uCount
;
1619 pID
->WMP
.wmiDEMisc
.uColorProfileOffset
= uValue
;
1622 case WMP_tagXMPMetadata
:
1623 pID
->WMP
.wmiDEMisc
.uXMPMetadataByteCount
= uCount
;
1624 pID
->WMP
.wmiDEMisc
.uXMPMetadataOffset
= uValue
;
1627 case WMP_tagEXIFMetadata
:
1628 pID
->WMP
.wmiDEMisc
.uEXIFMetadataOffset
= uValue
;
1629 CallIgnoreError(errTmp
, StreamCalcIFDSize(pWS
, uValue
, &pID
->WMP
.wmiDEMisc
.uEXIFMetadataByteCount
));
1632 case WMP_tagGPSInfoMetadata
:
1633 pID
->WMP
.wmiDEMisc
.uGPSInfoMetadataOffset
= uValue
;
1634 CallIgnoreError(errTmp
, StreamCalcIFDSize(pWS
, uValue
, &pID
->WMP
.wmiDEMisc
.uGPSInfoMetadataByteCount
));
1637 case WMP_tagIPTCNAAMetadata
:
1638 pID
->WMP
.wmiDEMisc
.uIPTCNAAMetadataByteCount
= uCount
;
1639 pID
->WMP
.wmiDEMisc
.uIPTCNAAMetadataOffset
= uValue
;
1642 case WMP_tagPhotoshopMetadata
:
1643 pID
->WMP
.wmiDEMisc
.uPhotoshopMetadataByteCount
= uCount
;
1644 pID
->WMP
.wmiDEMisc
.uPhotoshopMetadataOffset
= uValue
;
1647 case WMP_tagCompression
:
1648 case WMP_tagImageType
:
1649 case WMP_tagImageDataDiscard
:
1650 case WMP_tagAlphaDataDiscard
:
1653 // Descriptive Metadata
1654 case WMP_tagImageDescription
:
1655 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1656 &pID
->WMP
.sDescMetadata
.pvarImageDescription
));
1657 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarImageDescription
.vt
);
1660 case WMP_tagCameraMake
:
1661 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1662 &pID
->WMP
.sDescMetadata
.pvarCameraMake
));
1663 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarCameraMake
.vt
);
1666 case WMP_tagCameraModel
:
1667 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1668 &pID
->WMP
.sDescMetadata
.pvarCameraModel
));
1669 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarCameraModel
.vt
);
1672 case WMP_tagSoftware
:
1673 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1674 &pID
->WMP
.sDescMetadata
.pvarSoftware
));
1675 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarSoftware
.vt
);
1678 case WMP_tagDateTime
:
1679 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1680 &pID
->WMP
.sDescMetadata
.pvarDateTime
));
1681 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarDateTime
.vt
);
1685 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1686 &pID
->WMP
.sDescMetadata
.pvarArtist
));
1687 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarArtist
.vt
);
1690 case WMP_tagCopyright
:
1691 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1692 &pID
->WMP
.sDescMetadata
.pvarCopyright
));
1693 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarCopyright
.vt
);
1696 case WMP_tagRatingStars
:
1697 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1698 &pID
->WMP
.sDescMetadata
.pvarRatingStars
));
1699 assert(DPKVT_UI2
== pID
->WMP
.sDescMetadata
.pvarRatingStars
.vt
);
1702 case WMP_tagRatingValue
:
1703 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1704 &pID
->WMP
.sDescMetadata
.pvarRatingValue
));
1705 assert(DPKVT_UI2
== pID
->WMP
.sDescMetadata
.pvarRatingValue
.vt
);
1708 case WMP_tagCaption
:
1709 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1710 &pID
->WMP
.sDescMetadata
.pvarCaption
));
1711 assert((DPKVT_BYREF
| DPKVT_UI1
) == pID
->WMP
.sDescMetadata
.pvarCaption
.vt
);
1713 // Change type from C-style byte array to LPWSTR
1714 assert((U8
*)pID
->WMP
.sDescMetadata
.pvarCaption
.VT
.pwszVal
==
1715 pID
->WMP
.sDescMetadata
.pvarCaption
.VT
.pbVal
);
1716 assert(0 == pID
->WMP
.sDescMetadata
.pvarCaption
.VT
.pwszVal
[uCount
/sizeof(U16
) - 1]); // Confirm null-term
1717 // make sure null term (ReadPropvar allocated enough space for this)
1718 pID
->WMP
.sDescMetadata
.pvarCaption
.VT
.pwszVal
[uCount
/sizeof(U16
)] = 0;
1719 pID
->WMP
.sDescMetadata
.pvarCaption
.vt
= DPKVT_LPWSTR
;
1722 case WMP_tagDocumentName
:
1723 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1724 &pID
->WMP
.sDescMetadata
.pvarDocumentName
));
1725 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarDocumentName
.vt
);
1728 case WMP_tagPageName
:
1729 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1730 &pID
->WMP
.sDescMetadata
.pvarPageName
));
1731 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarPageName
.vt
);
1734 case WMP_tagPageNumber
:
1735 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1736 &pID
->WMP
.sDescMetadata
.pvarPageNumber
));
1737 assert(DPKVT_UI4
== pID
->WMP
.sDescMetadata
.pvarPageNumber
.vt
);
1740 case WMP_tagHostComputer
:
1741 CallIgnoreError(errTmp
, ReadPropvar(pWS
, uType
, uCount
, uValue
,
1742 &pID
->WMP
.sDescMetadata
.pvarHostComputer
));
1743 assert(DPKVT_LPSTR
== pID
->WMP
.sDescMetadata
.pvarHostComputer
.vt
);
1747 fprintf(stderr
, "Unrecognized WMPTag: %d(%#x), %d, %d, %#x" CRLF
,
1748 (int)uTag
, (int)uTag
, (int)uType
, (int)uCount
, (int)uValue
);
1761 ERR err
= WMP_errSuccess
;
1762 struct WMPStream
* pWS
= pID
->pStream
;
1765 for (i
= 0; i
< cEntry
; ++i
)
1772 Call(GetUShort(pWS
, offPos
, &uTag
)); offPos
+= 2;
1773 Call(GetUShort(pWS
, offPos
, &uType
)); offPos
+= 2;
1774 Call(GetULong(pWS
, offPos
, &uCount
)); offPos
+= 4;
1775 Call(GetULong(pWS
, offPos
, &uValue
)); offPos
+= 4;
1777 Call(ParsePFDEntry(pID
, uTag
, uType
, uCount
, uValue
));
1780 pID
->WMP
.bHasAlpha
= ((pID
->WMP
.bHasAlpha
) && (pID
->WMP
.wmiDEMisc
.uAlphaOffset
!= 0) && (pID
->WMP
.wmiDEMisc
.uAlphaByteCount
!= 0));//has planar alpha
1789 ERR err
= WMP_errSuccess
;
1791 struct WMPStream
* pWS
= pID
->pStream
;
1794 char szSig
[2] = {0};
1800 //================================
1801 Call(pWS
->GetPos(pWS
, &offPos
));
1802 FailIf(0 != offPos
, WMP_errUnsupportedFormat
);
1804 //================================
1806 Call(pWS
->Read(pWS
, szSig
, sizeof(szSig
))); offPos
+= 2;
1807 FailIf(szSig
!= strstr(szSig
, "II"), WMP_errUnsupportedFormat
);
1809 Call(GetUShort(pWS
, offPos
, &uWmpID
)); offPos
+= 2;
1810 FailIf(WMP_valWMPhotoID
!= (0x00FF & uWmpID
), WMP_errUnsupportedFormat
);
1812 // We accept version 00 and version 01 bitstreams - all others rejected
1813 bVersion
= (0xFF00 & uWmpID
) >> 8;
1814 FailIf(bVersion
!= 0 && bVersion
!= 1, WMP_errUnsupportedFormat
);
1816 Call(GetULong(pWS
, offPos
, &offPFD
)); offPos
+= 4;
1818 //================================
1820 offPos
= (size_t)offPFD
;
1821 Call(GetUShort(pWS
, offPos
, &cPFDEntry
)); offPos
+= 2;
1822 FailIf(0 == cPFDEntry
|| USHRT_MAX
== cPFDEntry
, WMP_errUnsupportedFormat
);
1823 Call(ParsePFD(pID
, offPos
, cPFDEntry
));
1825 //================================
1826 Call(pWS
->SetPos(pWS
, pID
->WMP
.wmiDEMisc
.uImageOffset
));
1833 //================================================
1834 ERR
PKImageDecode_Initialize_WMP(
1836 struct WMPStream
* pWS
)
1838 ERR err
= WMP_errSuccess
;
1840 CWMImageInfo
* pII
= NULL
;
1842 //================================
1843 Call(PKImageDecode_Initialize(pID
, pWS
));
1845 //================================
1846 Call(ReadContainer(pID
));
1848 //================================
1849 pID
->WMP
.wmiSCP
.pWStream
= pWS
;
1850 pID
->WMP
.DecoderCurrMBRow
= 0;
1851 pID
->WMP
.cLinesDecoded
= 0;
1852 pID
->WMP
.cLinesCropped
= 0;
1853 pID
->WMP
.fFirstNonZeroDecode
= FALSE
;
1855 FailIf(ICERR_OK
!= ImageStrDecGetInfo(&pID
->WMP
.wmiI
, &pID
->WMP
.wmiSCP
), WMP_errFail
);
1856 assert(Y_ONLY
<= pID
->WMP
.wmiSCP
.cfColorFormat
&& pID
->WMP
.wmiSCP
.cfColorFormat
< CFT_MAX
);
1857 assert(BD_SHORT
== pID
->WMP
.wmiSCP
.bdBitDepth
|| BD_LONG
== pID
->WMP
.wmiSCP
.bdBitDepth
);
1859 // If HD Photo container provided an orientation, this should override bitstream orientation
1860 // If container did NOT provide an orientation, force O_NONE. This is to be consistent with
1861 // Vista behaviour, which is to ignore bitstream orientation (only looks at container).
1862 if (pID
->WMP
.fOrientationFromContainer
)
1864 pID
->WMP
.wmiI
.oOrientation
= pID
->WMP
.oOrientationFromContainer
;
1868 // Force to O_NONE to match Vista decode behaviour
1869 pID
->WMP
.wmiI
.oOrientation
= O_NONE
;
1872 pII
= &pID
->WMP
.wmiI
;
1873 pID
->uWidth
= (U32
)pII
->cWidth
;
1874 pID
->uHeight
= (U32
)pII
->cHeight
;
1881 ERR
PKImageDecode_GetSize_WMP(
1886 if (pID
->WMP
.wmiI
.oOrientation
>= O_RCW
)
1888 *piWidth
= (I32
)pID
->uHeight
;
1889 *piHeight
= (I32
)pID
->uWidth
;
1893 *piWidth
= (I32
)pID
->uWidth
;
1894 *piHeight
= (I32
)pID
->uHeight
;
1896 return WMP_errSuccess
;
1900 ERR
PKImageDecode_GetRawStream_WMP(
1902 struct WMPStream
** ppWS
)
1904 ERR err
= WMP_errSuccess
;
1905 struct WMPStream
* pWS
= pID
->pStream
;
1908 Call(pWS
->SetPos(pWS
, pID
->WMP
.wmiDEMisc
.uImageOffset
));
1915 ERR
PKImageDecode_Copy_WMP(
1917 const PKRect
* pRect
,
1921 ERR err
= WMP_errSuccess
;
1922 U32 cThumbnailScale
;
1924 CWMImageBufferInfo wmiBI
= { 0 };
1925 #ifdef REENTRANT_MODE
1926 U8
*pbLowMemAdj
= NULL
;
1929 #endif // REENTRANT_MODE
1930 struct WMPStream
* pWS
= pID
->pStream
;
1931 U8 tempAlphaMode
= 0;
1933 wmiBI
.cLine
= pRect
->Height
;
1934 wmiBI
.cbStride
= cbStride
;
1935 #ifdef REENTRANT_MODE
1936 // In REENTRANT_MODE, we allow rectangles with any top left corner (not just (0,0))
1938 FailIf(0 != pRect
->X
, WMP_errInvalidParameter
);
1939 FailIf(0 != pRect
->Y
, WMP_errInvalidParameter
);
1940 #endif // REENTRANT_MODE
1942 cThumbnailScale
= 1;
1943 if (pID
->WMP
.wmiI
.cThumbnailWidth
> 0)
1945 while(cThumbnailScale
* pID
->WMP
.wmiI
.cThumbnailWidth
< pID
->uWidth
)
1946 cThumbnailScale
<<= 1;
1948 // note the following implementation can't handle fractional linesperMBRow limiting
1949 // us to >= 1/256 thumbnail which is unfortunate, but all the PS plugin needs is 1/256
1950 // and I didn't care to get into floating point or a bunch of conditional tests or
1951 // other rewrite for a case not needed nor tested by PS plugin. sorry.
1952 linesperMBRow
= 16 / cThumbnailScale
;
1954 #ifdef REENTRANT_MODE
1955 if (0 == pID
->WMP
.DecoderCurrMBRow
)
1957 #endif // REENTRANT_MODE
1958 // Set the fPaddedUserBuffer if the following conditions are met
1959 if (0 == ((size_t)pb
% 128) && // Frame buffer is aligned to 128-byte boundary
1960 0 == (pRect
->Height
% 16) && // Horizontal resolution is multiple of 16
1961 0 == (pRect
->Width
% 16) && // Vertical resolution is multiple of 16
1962 0 == (cbStride
% 128)) // Stride is a multiple of 128 bytes
1964 pID
->WMP
.wmiI
.fPaddedUserBuffer
= TRUE
;
1965 // Note that there are additional conditions in strdec_x86.c's strDecOpt
1966 // which could prevent optimization from being engaged
1968 #ifdef REENTRANT_MODE
1970 #endif // REENTRANT_MODE
1971 //if(pID->WMP.wmiSCP.uAlphaMode != 1)
1972 if((!pID
->WMP
.bHasAlpha
) || (pID
->WMP
.wmiSCP
.uAlphaMode
!= 1))
1974 if(pID
->WMP
.bHasAlpha
)//planar alpha
1976 tempAlphaMode
= pID
->WMP
.wmiSCP
.uAlphaMode
;
1977 pID
->WMP
.wmiSCP
.uAlphaMode
= 0;
1979 pID
->WMP
.wmiSCP
.fMeasurePerf
= TRUE
;
1980 #ifdef REENTRANT_MODE
1981 if (0 == pID
->WMP
.DecoderCurrMBRow
)
1983 Call(pID
->WMP
.wmiSCP
.pWStream
->GetPos(pID
->WMP
.wmiSCP
.pWStream
, &(pID
->WMP
.cMarker
)));
1984 FailIf(ICERR_OK
!= ImageStrDecInit(&pID
->WMP
.wmiI
, &pID
->WMP
.wmiSCP
, &pID
->WMP
.ctxSC
), WMP_errFail
);
1986 // Re-entrant mode incurs 1 MBR delay, so to get 0th MBR, we have to ask for 1st MBR
1987 cMBRow
= ((U32
) pID
->WMP
.cLinesCropped
+ pRect
->Y
+ pRect
->Height
+
1988 (pRect
->Y
+ pRect
->Height
>= (I32
) pID
->WMP
.wmiI
.cROIHeight
? linesperMBRow
- 1 : 0)) / // round up if last MBR
1990 cMBRowStart
= ((U32
) pID
->WMP
.cLinesCropped
+ pRect
->Y
) / linesperMBRow
+ 1;
1991 // if current request starts before current state, then rewind.
1992 if (cMBRowStart
< pID
->WMP
.DecoderCurrMBRow
)
1994 pID
->WMP
.DecoderCurrMBRow
= 0;
1995 pID
->WMP
.cLinesDecoded
= 0;
1996 pID
->WMP
.cLinesCropped
= 0;
1997 pID
->WMP
.fFirstNonZeroDecode
= FALSE
;
1998 FailIf(ICERR_OK
!= ImageStrDecTerm(pID
->WMP
.ctxSC
), WMP_errFail
);
1999 Call(pID
->WMP
.wmiSCP
.pWStream
->SetPos(pID
->WMP
.wmiSCP
.pWStream
, pID
->WMP
.cMarker
));
2000 FailIf(ICERR_OK
!= ImageStrDecInit(&pID
->WMP
.wmiI
, &pID
->WMP
.wmiSCP
, &pID
->WMP
.ctxSC
), WMP_errFail
);
2003 // In "Low Memory mode", we don't have full frame buffer. We therefore cannot rotate the image.
2004 // We can flip H, V and HV, but no rotations.
2005 FailIf(pID
->WMP
.wmiI
.oOrientation
>= O_RCW
, WMP_errFail
);
2007 // In low-memory mode, the full frame buffer is unavailable. This doesn't seem to
2008 // matter in O_NONE and O_FLIPH, but for O_FLIPV and O_FLIPVH, outputMBRow tries to write to
2009 // the bottom of full-frame buffer. Adjust the buffer pointer to compensate.
2010 if (O_FLIPV
== pID
->WMP
.wmiI
.oOrientation
|| O_FLIPVH
== pID
->WMP
.wmiI
.oOrientation
)
2012 I32 iActualY2
= pRect
->Y
+ pRect
->Height
;
2013 pbLowMemAdj
= pb
- (pID
->WMP
.wmiI
.cROIHeight
- (iActualY2
- pID
->WMP
.cLinesCropped
)) * cbStride
;
2017 pbLowMemAdj
= pb
- pRect
->Y
* cbStride
;
2019 wmiBI
.pv
= pbLowMemAdj
;
2021 for (i
= (U32
)pID
->WMP
.DecoderCurrMBRow
; i
< cMBRow
; i
++)
2023 size_t cLinesDecoded
;
2024 wmiBI
.uiFirstMBRow
= i
;
2025 wmiBI
.uiLastMBRow
= i
;
2026 FailIf(ICERR_OK
!= ImageStrDecDecode(pID
->WMP
.ctxSC
, &wmiBI
, &cLinesDecoded
), WMP_errFail
);
2027 pID
->WMP
.cLinesDecoded
= cLinesDecoded
;
2028 if (FALSE
== pID
->WMP
.fFirstNonZeroDecode
&& cLinesDecoded
> 0)
2030 pID
->WMP
.cLinesCropped
+= (linesperMBRow
- cLinesDecoded
);
2031 pID
->WMP
.fFirstNonZeroDecode
= TRUE
;
2032 // update cMBRow if partial MB row cropped
2033 cMBRow
= ((U32
) pID
->WMP
.cLinesCropped
+ pRect
->Y
+ pRect
->Height
+
2034 (pRect
->Y
+ pRect
->Height
>= (I32
) pID
->WMP
.wmiI
.cROIHeight
? linesperMBRow
- 1 : 0)) / // round up if last MBR
2038 if (0 == cLinesDecoded
&& i
> 0)
2040 pID
->WMP
.cLinesCropped
+= linesperMBRow
;
2041 // update cMBRow if whole MB row cropped
2045 wmiBI
.pv
= pbLowMemAdj
;
2047 // If we're past the top of the image, then we're done, so terminate.
2048 if (linesperMBRow
* (cMBRow
- 1) >= (U32
) pID
->WMP
.cLinesCropped
+ pID
->WMP
.wmiI
.cROIHeight
) {
2049 FailIf(ICERR_OK
!= ImageStrDecTerm(pID
->WMP
.ctxSC
), WMP_errFail
);
2051 pID
->WMP
.DecoderCurrMBRow
= cMBRow
; // Set to next possible MBRow that is decodable
2054 FailIf(ICERR_OK
!= ImageStrDecInit(&pID
->WMP
.wmiI
, &pID
->WMP
.wmiSCP
, &pID
->WMP
.ctxSC
), WMP_errFail
);
2055 FailIf(ICERR_OK
!= ImageStrDecDecode(pID
->WMP
.ctxSC
, &wmiBI
), WMP_errFail
);
2056 FailIf(ICERR_OK
!= ImageStrDecTerm(pID
->WMP
.ctxSC
), WMP_errFail
);
2057 #endif //REENTRANT_MODE
2059 if(pID
->WMP
.bHasAlpha
)//planar alpha
2061 pID
->WMP
.wmiSCP
.uAlphaMode
= tempAlphaMode
;
2065 // if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode == 2)
2066 // if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode != 1)
2067 if(pID
->WMP
.bHasAlpha
&& pID
->WMP
.wmiSCP
.uAlphaMode
!= 0)
2069 pID
->WMP
.wmiI_Alpha
= pID
->WMP
.wmiI
;
2070 pID
->WMP
.wmiSCP_Alpha
= pID
->WMP
.wmiSCP
;
2072 // assert(pID->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now!
2073 pID
->WMP
.wmiI_Alpha
.cfColorFormat
= Y_ONLY
;
2075 switch (pID
->WMP
.wmiI
.bdBitDepth
)
2078 pID
->WMP
.wmiI_Alpha
.cLeadingPadding
+= (pID
->WMP
.wmiI
.cBitsPerUnit
>> 3) - 1;
2084 pID
->WMP
.wmiI_Alpha
.cLeadingPadding
+= (pID
->WMP
.wmiI
.cBitsPerUnit
>> 3) / sizeof(U16
) - 1;
2090 pID
->WMP
.wmiI_Alpha
.cLeadingPadding
+= (pID
->WMP
.wmiI
.cBitsPerUnit
>> 3) / sizeof(float) - 1;
2100 pID
->WMP
.wmiSCP_Alpha
.fMeasurePerf
= TRUE
;
2101 Call(pWS
->SetPos(pWS
, pID
->WMP
.wmiDEMisc
.uAlphaOffset
));
2102 #ifdef REENTRANT_MODE
2103 if (0 == pID
->WMP
.DecoderCurrAlphaMBRow
) // add this to WMP struct!
2105 FailIf(ICERR_OK
!= ImageStrDecInit(&pID
->WMP
.wmiI_Alpha
, &pID
->WMP
.wmiSCP_Alpha
, &pID
->WMP
.ctxSC_Alpha
), WMP_errFail
);
2108 // Re-entrant mode incurs 1 MBR delay, so to get 0th MBR, we have to ask for 1st MBR
2109 cMBRow
= ((U32
) pID
->WMP
.cLinesCropped
+ pRect
->Y
+ pRect
->Height
+
2110 (pRect
->Y
+ pRect
->Height
>= (I32
) pID
->WMP
.wmiI
.cROIHeight
? linesperMBRow
- 1 : 0)) / // round up if last MBR
2112 cMBRowStart
= ((U32
) pID
->WMP
.cLinesCropped
+ pRect
->Y
) / linesperMBRow
+ 1;
2113 // if current request starts before current state, then rewind.
2114 if (cMBRowStart
< pID
->WMP
.DecoderCurrAlphaMBRow
)
2116 pID
->WMP
.DecoderCurrAlphaMBRow
= 0;
2117 FailIf(ICERR_OK
!= ImageStrDecTerm(pID
->WMP
.ctxSC_Alpha
), WMP_errFail
);
2118 FailIf(ICERR_OK
!= ImageStrDecInit(&pID
->WMP
.wmiI_Alpha
, &pID
->WMP
.wmiSCP_Alpha
, &pID
->WMP
.ctxSC_Alpha
), WMP_errFail
);
2121 for (i
= (U32
)pID
->WMP
.DecoderCurrAlphaMBRow
; i
< cMBRow
; i
++)
2123 size_t cLinesDecoded
;
2124 wmiBI
.uiFirstMBRow
= i
;
2125 wmiBI
.uiLastMBRow
= i
;
2126 FailIf(ICERR_OK
!= ImageStrDecDecode(pID
->WMP
.ctxSC_Alpha
, &wmiBI
, &cLinesDecoded
), WMP_errFail
);
2129 // If we're past the top of the image, then we're done, so terminate
2130 if (linesperMBRow
* (cMBRow
- 1) >= (U32
) pID
->WMP
.cLinesCropped
+ pID
->WMP
.wmiI
.cROIHeight
) {
2131 FailIf(ICERR_OK
!= ImageStrDecTerm(pID
->WMP
.ctxSC_Alpha
), WMP_errFail
);
2133 pID
->WMP
.DecoderCurrAlphaMBRow
= cMBRow
; // Set to next possible MBRow that is decodable
2136 FailIf(ICERR_OK
!= ImageStrDecInit(&pID
->WMP
.wmiI_Alpha
, &pID
->WMP
.wmiSCP_Alpha
, &pID
->WMP
.ctxSC_Alpha
), WMP_errFail
);
2137 FailIf(ICERR_OK
!= ImageStrDecDecode(pID
->WMP
.ctxSC_Alpha
, &wmiBI
), WMP_errFail
);
2138 FailIf(ICERR_OK
!= ImageStrDecTerm(pID
->WMP
.ctxSC_Alpha
), WMP_errFail
);
2139 #endif //REENTRANT_MODE
2142 pID
->idxCurrentLine
+= pRect
->Height
;
2149 ERR
PKImageDecode_GetMetadata_WMP(PKImageDecode
*pID
, U32 uOffset
, U32 uByteCount
, U8
*pbGot
, U32
*pcbGot
)
2151 ERR err
= WMP_errSuccess
;
2153 if (pbGot
&& uOffset
)
2155 struct WMPStream
* pWS
= pID
->pStream
;
2158 FailIf(*pcbGot
< uByteCount
, WMP_errBufferOverflow
);
2159 Call(pWS
->GetPos(pWS
, &iCurrPos
));
2160 Call(pWS
->SetPos(pWS
, uOffset
));
2161 Call(pWS
->Read(pWS
, pbGot
, uByteCount
));
2162 Call(pWS
->SetPos(pWS
, iCurrPos
));
2169 *pcbGot
= uByteCount
;
2176 ERR
PKImageDecode_GetColorContext_WMP(PKImageDecode
*pID
, U8
*pbColorContext
, U32
*pcbColorContext
)
2178 return PKImageDecode_GetMetadata_WMP(pID
, pID
->WMP
.wmiDEMisc
.uColorProfileOffset
,
2179 pID
->WMP
.wmiDEMisc
.uColorProfileByteCount
, pbColorContext
, pcbColorContext
);
2183 ERR
PKImageDecode_GetXMPMetadata_WMP(PKImageDecode
*pID
, U8
*pbXMPMetadata
, U32
*pcbXMPMetadata
)
2185 return PKImageDecode_GetMetadata_WMP(pID
, pID
->WMP
.wmiDEMisc
.uXMPMetadataOffset
,
2186 pID
->WMP
.wmiDEMisc
.uXMPMetadataByteCount
, pbXMPMetadata
, pcbXMPMetadata
);
2190 ERR
PKImageDecode_GetEXIFMetadata_WMP(PKImageDecode
*pID
, U8
*pbEXIFMetadata
, U32
*pcbEXIFMetadata
)
2192 return PKImageDecode_GetMetadata_WMP(pID
, pID
->WMP
.wmiDEMisc
.uEXIFMetadataOffset
,
2193 pID
->WMP
.wmiDEMisc
.uEXIFMetadataByteCount
, pbEXIFMetadata
, pcbEXIFMetadata
);
2197 ERR
PKImageDecode_GetGPSInfoMetadata_WMP(PKImageDecode
*pID
, U8
*pbGPSInfoMetadata
, U32
*pcbGPSInfoMetadata
)
2199 return PKImageDecode_GetMetadata_WMP(pID
, pID
->WMP
.wmiDEMisc
.uGPSInfoMetadataOffset
,
2200 pID
->WMP
.wmiDEMisc
.uGPSInfoMetadataByteCount
, pbGPSInfoMetadata
, pcbGPSInfoMetadata
);
2204 ERR
PKImageDecode_GetIPTCNAAMetadata_WMP(PKImageDecode
*pID
, U8
*pbIPTCNAAMetadata
, U32
*pcbIPTCNAAMetadata
)
2206 return PKImageDecode_GetMetadata_WMP(pID
, pID
->WMP
.wmiDEMisc
.uIPTCNAAMetadataOffset
,
2207 pID
->WMP
.wmiDEMisc
.uIPTCNAAMetadataByteCount
, pbIPTCNAAMetadata
, pcbIPTCNAAMetadata
);
2211 ERR
PKImageDecode_GetPhotoshopMetadata_WMP(PKImageDecode
*pID
, U8
*pbPhotoshopMetadata
, U32
*pcbPhotoshopMetadata
)
2213 return PKImageDecode_GetMetadata_WMP(pID
, pID
->WMP
.wmiDEMisc
.uPhotoshopMetadataOffset
,
2214 pID
->WMP
.wmiDEMisc
.uPhotoshopMetadataByteCount
, pbPhotoshopMetadata
, pcbPhotoshopMetadata
);
2218 ERR
PKImageDecode_GetDescriptiveMetadata_WMP(PKImageDecode
*pID
, DESCRIPTIVEMETADATA
*pDescMetadata
)
2220 ERR err
= WMP_errSuccess
;
2221 *pDescMetadata
= pID
->WMP
.sDescMetadata
;
2226 ERR
PKImageDecode_Release_WMP(PKImageDecode
** ppID
)
2228 ERR err
= WMP_errSuccess
;
2236 // Free descriptive metadata
2237 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarImageDescription
);
2238 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarCameraMake
);
2239 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarCameraModel
);
2240 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarSoftware
);
2241 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarDateTime
);
2242 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarArtist
);
2243 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarCopyright
);
2244 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarRatingStars
);
2245 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarRatingValue
);
2246 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarCaption
);
2247 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarDocumentName
);
2248 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarPageName
);
2249 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarPageNumber
);
2250 FreeDescMetadata(&pID
->WMP
.sDescMetadata
.pvarHostComputer
);
2252 // Release base class
2253 Call(PKImageDecode_Release(ppID
));
2261 ERR
PKImageDecode_Create_WMP(PKImageDecode
** ppID
)
2263 ERR err
= WMP_errSuccess
;
2264 PKImageDecode
* pID
= NULL
;
2266 Call(PKImageDecode_Create(ppID
));
2269 pID
->Initialize
= PKImageDecode_Initialize_WMP
;
2270 pID
->GetSize
= PKImageDecode_GetSize_WMP
;
2271 pID
->GetRawStream
= PKImageDecode_GetRawStream_WMP
;
2272 pID
->Copy
= PKImageDecode_Copy_WMP
;
2273 pID
->GetColorContext
= PKImageDecode_GetColorContext_WMP
;
2274 pID
->GetDescriptiveMetadata
= PKImageDecode_GetDescriptiveMetadata_WMP
;
2275 pID
->Release
= PKImageDecode_Release_WMP
;