github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/jxr/jxrlib/jxrgluelib/JXRGlueJxr.c (about) 1 2 //*@@@+++@@@@****************************************************************** 3 // 4 // Copyright Microsoft Corp. 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 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. 15 // 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. 27 // 28 //*@@@---@@@@****************************************************************** 29 #include <limits.h> 30 #include <JXRGlue.h> 31 32 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); 36 37 38 void CalcMetadataSizeLPSTR(const DPKPROPVARIANT var, 39 U16 *pcInactiveMetadata, 40 U32 *pcbOffsetSize, 41 U32 *pcbCount) 42 { 43 if (DPKVT_EMPTY != var.vt) 44 { 45 U32 uiLenWithNull = (U32)strlen(var.VT.pszVal) + 1; // +1 for NULL; 46 assert(DPKVT_LPSTR == var.vt); 47 48 // We only use offset if size > 4 49 if (uiLenWithNull > 4) 50 *pcbOffsetSize += uiLenWithNull; 51 52 if (pcbCount) 53 *pcbCount = uiLenWithNull; 54 } 55 else 56 *pcInactiveMetadata += 1; 57 } 58 59 void CalcMetadataSizeLPWSTR(const DPKPROPVARIANT var, 60 U16 *pcInactiveMetadata, 61 U32 *pcbOffsetSize, 62 U32 *pcbCount) 63 { 64 if (DPKVT_EMPTY != var.vt) 65 { 66 U32 uiCBWithNull = sizeof(U16) * ((U32)wcslen((wchar_t *) var.VT.pwszVal) + 1); // +1 for NULL term; 67 assert(DPKVT_LPWSTR == var.vt); 68 69 // We only use offset if size > 4 70 if (uiCBWithNull > 4) 71 *pcbOffsetSize += uiCBWithNull; 72 73 if (pcbCount) 74 *pcbCount = uiCBWithNull; 75 } 76 else 77 *pcInactiveMetadata += 1; 78 } 79 80 void CalcMetadataSizeUI2(const DPKPROPVARIANT var, 81 U16 *pcInactiveMetadata, 82 U32 *pcbMetadataSize) 83 { 84 UNREFERENCED_PARAMETER( pcbMetadataSize ); 85 if (DPKVT_EMPTY != var.vt) 86 { 87 assert(DPKVT_UI2 == var.vt); 88 // This is a single UI2, so it will not be written via offset, but rather as value 89 } 90 else 91 *pcInactiveMetadata += 1; 92 } 93 94 void CalcMetadataSizeUI4(const DPKPROPVARIANT var, 95 U16 *pcInactiveMetadata, 96 U32 *pcbContainer) 97 { 98 UNREFERENCED_PARAMETER( pcbContainer ); 99 if (DPKVT_EMPTY != var.vt) 100 { 101 assert(DPKVT_UI4 == var.vt); 102 // This is a single UI4, so it will not be written via offset, but rather as value 103 } 104 else 105 *pcInactiveMetadata += 1; 106 } 107 108 ERR CalcMetadataOffsetSize(PKImageEncode* pIE, 109 U16 *pcInactiveMetadata, 110 U32 *pcbMetadataSize) 111 { 112 ERR err = WMP_errSuccess; 113 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); 128 129 return err; 130 } 131 132 133 ERR CopyDescMetadata(DPKPROPVARIANT *pvarDst, 134 const DPKPROPVARIANT varSrc) 135 { 136 ERR err = WMP_errSuccess; 137 size_t uiSize; 138 139 pvarDst->vt = varSrc.vt; 140 switch (varSrc.vt) 141 { 142 case DPKVT_LPSTR: 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); 147 break; 148 149 case DPKVT_LPWSTR: 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); 154 break; 155 156 case DPKVT_UI2: 157 pvarDst->VT.uiVal = varSrc.VT.uiVal; 158 break; 159 160 case DPKVT_UI4: 161 pvarDst->VT.ulVal = varSrc.VT.ulVal; 162 break; 163 164 default: 165 assert(FALSE); // This case is not handled 166 FailIf(TRUE, WMP_errNotYetImplemented); 167 168 // *** FALL THROUGH *** 169 170 case DPKVT_EMPTY: 171 memset(pvarDst, 0, sizeof(*pvarDst)); 172 assert(DPKVT_EMPTY == pvarDst->vt); 173 break; 174 } 175 176 Cleanup: 177 return err; 178 } 179 180 181 void FreeDescMetadata(DPKPROPVARIANT *pvar) 182 { 183 switch (pvar->vt) 184 { 185 case DPKVT_LPSTR: 186 PKFree((void **) &pvar->VT.pszVal); 187 break; 188 189 case DPKVT_LPWSTR: 190 PKFree((void **) &pvar->VT.pwszVal); 191 break; 192 193 default: 194 assert(FALSE); // This case is not handled 195 break; 196 197 case DPKVT_EMPTY: 198 case DPKVT_UI2: 199 case DPKVT_UI4: 200 break; 201 } 202 } 203 204 205 ERR WriteDescMetadata(PKImageEncode *pIE, 206 const DPKPROPVARIANT var, 207 WmpDE *pwmpDE, 208 U32 *puiCurrDescMetadataOffset, 209 size_t *poffPos) 210 { 211 ERR err = WMP_errSuccess; 212 WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc; 213 struct WMPStream* pWS = pIE->pStream; 214 U32 uiMetadataOffsetSize = 0; 215 U32 uiCount = 0; 216 U32 uiDataWrittenToOffset = 0; 217 U16 uiTemp = 0; 218 219 if (0 == pDEMisc->uDescMetadataOffset || 0 == pDEMisc->uDescMetadataByteCount) 220 goto Cleanup; // Nothing to do here 221 222 // Sanity check before - can be equal due to remaining metadata being DPKVT_EMPTY 223 assert(*puiCurrDescMetadataOffset <= pDEMisc->uDescMetadataByteCount); 224 225 switch (var.vt) 226 { 227 case DPKVT_EMPTY: 228 break; 229 230 case DPKVT_LPSTR: 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)); 235 break; 236 237 case DPKVT_LPWSTR: 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)); 242 break; 243 244 case DPKVT_UI2: 245 CalcMetadataSizeUI2(var, &uiTemp, &uiMetadataOffsetSize); 246 pwmpDE->uCount = 1; 247 pwmpDE->uValueOrOffset = var.VT.uiVal; 248 Call(WriteWmpDE(pWS, poffPos, pwmpDE, NULL, NULL)); 249 break; 250 251 case DPKVT_UI4: 252 CalcMetadataSizeUI4(var, &uiTemp, &uiMetadataOffsetSize); 253 pwmpDE->uCount = 1; 254 pwmpDE->uValueOrOffset = var.VT.ulVal; 255 Call(WriteWmpDE(pWS, poffPos, pwmpDE, NULL, NULL)); 256 break; 257 258 default: 259 assert(FALSE); // This case is not handled 260 FailIf(TRUE, WMP_errNotYetImplemented); 261 break; 262 } 263 264 *puiCurrDescMetadataOffset += uiDataWrittenToOffset; 265 266 // Sanity check after 267 assert(*puiCurrDescMetadataOffset <= pDEMisc->uDescMetadataByteCount); // Can be equal 268 269 Cleanup: 270 return err; 271 } 272 273 274 275 //================================================================ 276 // PKImageEncode_WMP 277 //================================================================ 278 ERR WriteContainerPre( 279 PKImageEncode* pIE) 280 { 281 ERR err = WMP_errSuccess; 282 const U32 OFFSET_OF_PFD = 0x20; 283 struct WMPStream* pWS = pIE->pStream; 284 WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc; 285 PKPixelInfo PI; 286 size_t offPos = 0; 287 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; 293 294 static WmpDE wmpDEs[] = 295 { 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 310 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}, 317 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}, 328 }; 329 U16 cWmpDEs = sizeof(wmpDEs) / sizeof(wmpDEs[0]); 330 WmpDE wmpDE = {0}; 331 size_t i = 0; 332 333 U8* pbEXIFMetadata = NULL; 334 U8* pbGPSInfoMetadata = NULL; 335 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); 339 340 //================ 341 Call(pWS->GetPos(pWS, &offPos)); 342 FailIf(0 != offPos, WMP_errUnsupportedFormat); 343 344 //================ 345 // Header (8 bytes) 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; 349 350 //================ 351 // Write overflow area 352 pDEMisc->uOffPixelFormat = (U32)offPos; 353 PI.pGUIDPixFmt = &pIE->guidPixFormat; 354 PixelFormatLookup(&PI, LOOKUP_FORWARD); 355 356 //Call(pWS->Write(pWS, PI.pGUIDPixFmt, sizeof(*PI.pGUIDPixFmt))); offPos += 16; 357 /** following code is endian-agnostic **/ 358 { 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)); 364 offPos += 16; 365 } 366 367 //================ 368 // Tally up space required for descriptive metadata 369 Call(CalcMetadataOffsetSize(pIE, &cInactiveMetadata, &cbMetadataOffsetSize)); 370 cWmpDEs -= cInactiveMetadata; 371 372 //================ 373 // PFD 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; 378 379 if (!pIE->WMP.bHasAlpha || pIE->WMP.wmiSCP.uAlphaMode != 2) //no planar alpha 380 cWmpDEs -= 2; 381 382 if (0 == pIE->cbXMPMetadataByteCount) 383 cWmpDEs -= 1; // No XMP metadata 384 385 if (0 == pIE->cbIPTCNAAMetadataByteCount) 386 cWmpDEs -= 1; // No IPTCNAA metadata 387 388 if (0 == pIE->cbPhotoshopMetadataByteCount) 389 cWmpDEs -= 1; // No Photoshop metadata 390 391 if (0 == pIE->cbEXIFMetadataByteCount) 392 cWmpDEs -= 1; // No EXIF metadata 393 394 if (0 == pIE->cbColorContext) 395 cWmpDEs -= 1; // No color context 396 397 if (0 == pIE->cbGPSInfoMetadataByteCount) 398 cWmpDEs -= 1; // No GPSInfo metadata 399 400 pDEMisc->uImageOffset = (U32)(offPos + sizeof(U16) + SizeofIFDEntry * cWmpDEs + sizeof(U32)); 401 402 if (cbMetadataOffsetSize > 0) 403 { 404 pDEMisc->uDescMetadataByteCount = cbMetadataOffsetSize; 405 pDEMisc->uDescMetadataOffset = pDEMisc->uImageOffset; 406 pDEMisc->uImageOffset += cbMetadataOffsetSize; 407 } 408 409 if (pIE->cbXMPMetadataByteCount > 0) 410 { 411 pDEMisc->uXMPMetadataOffset = pDEMisc->uImageOffset; 412 pDEMisc->uImageOffset += pIE->cbXMPMetadataByteCount; 413 } 414 415 if (pIE->cbIPTCNAAMetadataByteCount > 0) 416 { 417 pDEMisc->uIPTCNAAMetadataOffset = pDEMisc->uImageOffset; 418 pDEMisc->uImageOffset += pIE->cbIPTCNAAMetadataByteCount; 419 } 420 421 if (pIE->cbPhotoshopMetadataByteCount > 0) 422 { 423 pDEMisc->uPhotoshopMetadataOffset = pDEMisc->uImageOffset; 424 pDEMisc->uImageOffset += pIE->cbPhotoshopMetadataByteCount; 425 } 426 427 if (pIE->cbEXIFMetadataByteCount > 0) 428 { 429 pDEMisc->uEXIFMetadataOffset = pDEMisc->uImageOffset; 430 pDEMisc->uImageOffset += (pDEMisc->uImageOffset & 1); 431 pDEMisc->uImageOffset += pIE->cbEXIFMetadataByteCount; 432 } 433 434 if (pIE->cbColorContext > 0) 435 { 436 pDEMisc->uColorProfileOffset = pDEMisc->uImageOffset; 437 pDEMisc->uImageOffset += pIE->cbColorContext; 438 } 439 440 if (pIE->cbGPSInfoMetadataByteCount > 0) 441 { 442 pDEMisc->uGPSInfoMetadataOffset = pDEMisc->uImageOffset; 443 pDEMisc->uImageOffset += (pDEMisc->uImageOffset & 1); 444 pDEMisc->uImageOffset += pIE->cbGPSInfoMetadataByteCount; 445 } 446 447 Call(PutUShort(pWS, offPos, cWmpDEs)); offPos += 2; 448 Call(pWS->Write(pWS, Zero, SizeofIFDEntry * cWmpDEs + sizeof(U32))); 449 450 //================ 451 wmpDE = wmpDEs[i++]; 452 assert(WMP_tagDocumentName == wmpDE.uTag); 453 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarDocumentName, &wmpDE, 454 &uiCurrDescMetadataOffset, &offPos)); 455 456 wmpDE = wmpDEs[i++]; 457 assert(WMP_tagImageDescription == wmpDE.uTag); 458 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarImageDescription, &wmpDE, 459 &uiCurrDescMetadataOffset, &offPos)); 460 461 wmpDE = wmpDEs[i++]; 462 assert(WMP_tagCameraMake == wmpDE.uTag); 463 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCameraMake, &wmpDE, 464 &uiCurrDescMetadataOffset, &offPos)); 465 466 wmpDE = wmpDEs[i++]; 467 assert(WMP_tagCameraModel == wmpDE.uTag); 468 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCameraModel, &wmpDE, 469 &uiCurrDescMetadataOffset, &offPos)); 470 471 wmpDE = wmpDEs[i++]; 472 assert(WMP_tagPageName == wmpDE.uTag); 473 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarPageName, &wmpDE, 474 &uiCurrDescMetadataOffset, &offPos)); 475 476 wmpDE = wmpDEs[i++]; 477 assert(WMP_tagPageNumber == wmpDE.uTag); 478 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarPageNumber, &wmpDE, 479 &uiCurrDescMetadataOffset, &offPos)); 480 481 wmpDE = wmpDEs[i++]; 482 assert(WMP_tagSoftware == wmpDE.uTag); 483 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarSoftware, &wmpDE, 484 &uiCurrDescMetadataOffset, &offPos)); 485 486 wmpDE = wmpDEs[i++]; 487 assert(WMP_tagDateTime == wmpDE.uTag); 488 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarDateTime, &wmpDE, 489 &uiCurrDescMetadataOffset, &offPos)); 490 491 wmpDE = wmpDEs[i++]; 492 assert(WMP_tagArtist == wmpDE.uTag); 493 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarArtist, &wmpDE, 494 &uiCurrDescMetadataOffset, &offPos)); 495 496 wmpDE = wmpDEs[i++]; 497 assert(WMP_tagHostComputer == wmpDE.uTag); 498 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarHostComputer, &wmpDE, 499 &uiCurrDescMetadataOffset, &offPos)); 500 501 wmpDE = wmpDEs[i++]; 502 assert(WMP_tagRatingStars == wmpDE.uTag); 503 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarRatingStars, &wmpDE, 504 &uiCurrDescMetadataOffset, &offPos)); 505 506 wmpDE = wmpDEs[i++]; 507 assert(WMP_tagRatingValue == wmpDE.uTag); 508 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarRatingValue, &wmpDE, 509 &uiCurrDescMetadataOffset, &offPos)); 510 511 wmpDE = wmpDEs[i++]; 512 assert(WMP_tagCopyright == wmpDE.uTag); 513 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCopyright, &wmpDE, 514 &uiCurrDescMetadataOffset, &offPos)); 515 516 wmpDE = wmpDEs[i++]; 517 assert(WMP_tagCaption == wmpDE.uTag); 518 Call(WriteDescMetadata(pIE, pIE->sDescMetadata.pvarCaption, &wmpDE, 519 &uiCurrDescMetadataOffset, &offPos)); 520 521 // XMP Metadata 522 wmpDE = wmpDEs[i++]; 523 assert(WMP_tagXMPMetadata == wmpDE.uTag); 524 if (pIE->cbXMPMetadataByteCount > 0) 525 { 526 U32 uiTemp; 527 wmpDE.uCount = pIE->cbXMPMetadataByteCount; 528 wmpDE.uValueOrOffset = pDEMisc->uXMPMetadataOffset; 529 Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbXMPMetadata, &uiTemp)); 530 } 531 532 // IPTCNAA Metadata 533 wmpDE = wmpDEs[i++]; 534 assert(WMP_tagIPTCNAAMetadata == wmpDE.uTag); 535 if (pIE->cbIPTCNAAMetadataByteCount > 0) 536 { 537 U32 uiTemp; 538 wmpDE.uCount = pIE->cbIPTCNAAMetadataByteCount; 539 wmpDE.uValueOrOffset = pDEMisc->uIPTCNAAMetadataOffset; 540 Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbIPTCNAAMetadata, &uiTemp)); 541 } 542 543 // Photoshop Metadata 544 wmpDE = wmpDEs[i++]; 545 assert(WMP_tagPhotoshopMetadata == wmpDE.uTag); 546 if (pIE->cbPhotoshopMetadataByteCount > 0) 547 { 548 U32 uiTemp; 549 wmpDE.uCount = pIE->cbPhotoshopMetadataByteCount; 550 wmpDE.uValueOrOffset = pDEMisc->uPhotoshopMetadataOffset; 551 Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbPhotoshopMetadata, &uiTemp)); 552 } 553 554 // EXIF Metadata 555 wmpDE = wmpDEs[i++]; 556 assert(WMP_tagEXIFMetadata == wmpDE.uTag); 557 if (pIE->cbEXIFMetadataByteCount > 0) 558 { 559 U32 uiTemp; 560 if ((pDEMisc->uEXIFMetadataOffset & 1) != 0) 561 { 562 Call(pWS->SetPos(pWS, pDEMisc->uEXIFMetadataOffset)); 563 Call(pWS->Write(pWS, Zero, 1)); 564 } 565 pDEMisc->uEXIFMetadataOffset += (pDEMisc->uEXIFMetadataOffset & 1); 566 wmpDE.uValueOrOffset = pDEMisc->uEXIFMetadataOffset; 567 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 568 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)); 575 } 576 577 // ICC Profile 578 wmpDE = wmpDEs[i++]; 579 assert(WMP_tagIccProfile == wmpDE.uTag); 580 if (pIE->cbColorContext > 0) 581 { 582 U32 uiTemp; 583 wmpDE.uCount = pIE->cbColorContext; 584 wmpDE.uValueOrOffset = pDEMisc->uColorProfileOffset; 585 Call(WriteWmpDE(pWS, &offPos, &wmpDE, pIE->pbColorContext, &uiTemp)); 586 } 587 588 // GPSInfo Metadata 589 wmpDE = wmpDEs[i++]; 590 assert(WMP_tagGPSInfoMetadata == wmpDE.uTag); 591 if (pIE->cbGPSInfoMetadataByteCount > 0) 592 { 593 U32 uiTemp; 594 if ((pDEMisc->uGPSInfoMetadataOffset & 1) != 0) 595 { 596 Call(pWS->SetPos(pWS, pDEMisc->uGPSInfoMetadataOffset)); 597 Call(pWS->Write(pWS, Zero, 1)); 598 } 599 pDEMisc->uGPSInfoMetadataOffset += (pDEMisc->uGPSInfoMetadataOffset & 1); 600 wmpDE.uValueOrOffset = pDEMisc->uGPSInfoMetadataOffset; 601 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 602 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)); 609 } 610 611 wmpDE = wmpDEs[i++]; 612 assert(WMP_tagPixelFormat == wmpDE.uTag); 613 wmpDE.uValueOrOffset = pDEMisc->uOffPixelFormat; 614 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 615 616 wmpDE = wmpDEs[i++]; 617 assert(WMP_tagTransformation == wmpDE.uTag); 618 wmpDE.uValueOrOffset = pIE->WMP.oOrientation; 619 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 620 621 wmpDE = wmpDEs[i++]; 622 assert(WMP_tagImageWidth == wmpDE.uTag); 623 wmpDE.uValueOrOffset = pIE->uWidth; 624 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 625 626 wmpDE = wmpDEs[i++]; 627 assert(WMP_tagImageHeight == wmpDE.uTag); 628 wmpDE.uValueOrOffset = pIE->uHeight; 629 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 630 631 wmpDE = wmpDEs[i++]; 632 assert(WMP_tagWidthResolution == wmpDE.uTag); 633 *((float *) &wmpDE.uValueOrOffset) = pIE->fResX; 634 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 635 636 wmpDE = wmpDEs[i++]; 637 assert(WMP_tagHeightResolution == wmpDE.uTag); 638 *((float *) &wmpDE.uValueOrOffset) = pIE->fResY; 639 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 640 641 wmpDE = wmpDEs[i++]; 642 assert(WMP_tagImageOffset == wmpDE.uTag); 643 wmpDE.uValueOrOffset = pDEMisc->uImageOffset; 644 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 645 646 // fix up in WriteContainerPost() 647 wmpDE = wmpDEs[i++]; 648 assert(WMP_tagImageByteCount == wmpDE.uTag); 649 pDEMisc->uOffImageByteCount = (U32)offPos; 650 wmpDE.uValueOrOffset = 0; 651 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 652 653 if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) 654 { 655 // fix up in WriteContainerPost() 656 wmpDE = wmpDEs[i++]; 657 assert(WMP_tagAlphaOffset == wmpDE.uTag); 658 pDEMisc->uOffAlphaOffset = (U32)offPos; 659 wmpDE.uValueOrOffset = 0; 660 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 661 662 // fix up in WriteContainerPost() 663 wmpDE = wmpDEs[i++]; 664 assert(WMP_tagAlphaByteCount == wmpDE.uTag); 665 pDEMisc->uOffAlphaByteCount = (U32)offPos; 666 wmpDE.uValueOrOffset = 0; 667 Call(WriteWmpDE(pWS, &offPos, &wmpDE, NULL, NULL)); 668 } 669 670 //================ 671 Call(PutULong(pWS, offPos, 0)); offPos += 4; 672 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) 678 { 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); 686 687 // OK, now skip to image offset 688 Call(pWS->SetPos(pWS, pDEMisc->uImageOffset)); 689 offPos = pDEMisc->uImageOffset; 690 } 691 assert(pDEMisc->uImageOffset == offPos); 692 693 Cleanup: 694 if (pbEXIFMetadata != NULL) 695 PKFree((void **) &pbEXIFMetadata); 696 if (pbGPSInfoMetadata != NULL) 697 PKFree((void **) &pbGPSInfoMetadata); 698 return err; 699 } 700 701 702 703 ERR WriteContainerPost( 704 PKImageEncode* pIE) 705 { 706 ERR err = WMP_errSuccess; 707 708 struct WMPStream* pWS = pIE->pStream; 709 WmpDEMisc* pDEMisc = &pIE->WMP.wmiDEMisc; 710 size_t offPos; 711 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}; 715 716 deImageByteCount.uValueOrOffset = pIE->WMP.nCbImage; 717 offPos = pDEMisc->uOffImageByteCount; 718 Call(WriteWmpDE(pWS, &offPos, &deImageByteCount, NULL, NULL)); 719 720 //Alpha 721 if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) 722 { 723 deAlphaOffset.uValueOrOffset = pIE->WMP.nOffAlpha; 724 offPos = pDEMisc->uOffAlphaOffset; 725 Call(WriteWmpDE(pWS, &offPos, &deAlphaOffset, NULL, NULL)); 726 727 deAlphaByteCount.uValueOrOffset = pIE->WMP.nCbAlpha + pIE->WMP.nOffAlpha; 728 offPos = pDEMisc->uOffAlphaByteCount; 729 Call(WriteWmpDE(pWS, &offPos, &deAlphaByteCount, NULL, NULL)); 730 } 731 732 Cleanup: 733 return err; 734 } 735 736 737 //================================================ 738 ERR PKImageEncode_Initialize_WMP( 739 PKImageEncode* pIE, 740 struct WMPStream* pStream, 741 void* pvParam, 742 size_t cbParam) 743 { 744 ERR err = WMP_errSuccess; 745 746 FailIf(sizeof(pIE->WMP.wmiSCP) != cbParam, WMP_errInvalidArgument); 747 748 pIE->WMP.wmiSCP = *(CWMIStrCodecParam*)pvParam; 749 pIE->WMP.wmiSCP_Alpha = *(CWMIStrCodecParam*)pvParam; 750 pIE->pStream = pStream; 751 752 pIE->WMP.wmiSCP.pWStream = pIE->pStream; 753 pIE->WMP.wmiSCP_Alpha.pWStream = pIE->pStream; 754 755 Cleanup: 756 return err; 757 } 758 759 ERR PKImageEncode_Terminate_WMP( 760 PKImageEncode* pIE) 761 { 762 ERR err = WMP_errSuccess; 763 UNREFERENCED_PARAMETER( pIE ); 764 return err; 765 } 766 767 768 ERR PKImageEncode_EncodeContent_Init( 769 PKImageEncode* pIE, 770 PKPixelInfo PI, 771 U32 cLine, 772 U8* pbPixels, 773 U32 cbStride) 774 { 775 ERR err = WMP_errSuccess; 776 777 // init codec 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; 785 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 791 { 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 795 } 796 797 //if (pIE->WMP.bHasAlpha) 798 //{ 799 // pIE->WMP.wmiSCP.cChannel = PI.cChannel - 1; 800 // pIE->WMP.wmiI.cfColorFormat = PI.cfStripAlpha; 801 //} 802 //else 803 804 if(PI.cfColorFormat == NCOMPONENT && (!(PI.grBit & PK_pixfmtHasAlpha)))//N-channel without Alpha 805 pIE->WMP.wmiSCP.cChannel = PI.cChannel; 806 else 807 pIE->WMP.wmiSCP.cChannel = PI.cChannel - 1;//other formats and (N-channel + Alpha) 808 809 pIE->idxCurrentLine = 0; 810 811 pIE->WMP.wmiSCP.fMeasurePerf = TRUE; 812 FailIf(ICERR_OK != ImageStrEncInit(&pIE->WMP.wmiI, &pIE->WMP.wmiSCP, &pIE->WMP.ctxSC), WMP_errFail); 813 814 Cleanup: 815 return err; 816 } 817 818 ERR PKImageEncode_EncodeContent_Encode( 819 PKImageEncode* pIE, 820 U32 cLine, 821 U8* pbPixels, 822 U32 cbStride) 823 { 824 ERR err = WMP_errSuccess; 825 U32 i = 0; 826 827 //================================ 828 for (i = 0; i < cLine; i += 16) 829 { 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); 837 } 838 pIE->idxCurrentLine += cLine; 839 840 Cleanup: 841 return err; 842 } 843 844 ERR PKImageEncode_EncodeContent_Term(PKImageEncode* pIE) 845 { 846 ERR err = WMP_errSuccess; 847 848 FailIf(ICERR_OK != ImageStrEncTerm(pIE->WMP.ctxSC), WMP_errFail); 849 850 Cleanup: 851 return err; 852 } 853 854 ERR PKImageEncode_EncodeContent( 855 PKImageEncode* pIE, 856 PKPixelInfo PI, 857 U32 cLine, 858 U8* pbPixels, 859 U32 cbStride) 860 { 861 ERR err = WMP_errSuccess; 862 size_t offPos = 0; 863 864 Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); 865 pIE->WMP.nOffImage = (Long)offPos; 866 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)); 870 871 Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); 872 pIE->WMP.nCbImage = (Long)offPos - pIE->WMP.nOffImage; 873 874 Cleanup: 875 return err; 876 } 877 878 879 ERR PKImageEncode_EncodeAlpha_Init( 880 PKImageEncode* pIE, 881 PKPixelInfo PI, 882 U32 cLine, 883 U8* pbPixels, 884 U32 cbStride) 885 { 886 ERR err = WMP_errSuccess; 887 888 UNREFERENCED_PARAMETER( cLine ); 889 UNREFERENCED_PARAMETER( pbPixels ); 890 UNREFERENCED_PARAMETER( cbStride ); 891 892 pIE->WMP.wmiI_Alpha = pIE->WMP.wmiI; 893 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; 902 903 switch (pIE->WMP.wmiI.bdBitDepth) 904 { 905 case BD_8: 906 pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) - 1; 907 break; 908 909 case BD_16: 910 case BD_16S: 911 case BD_16F: 912 pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(U16) - 1; 913 break; 914 915 case BD_32: 916 case BD_32S: 917 case BD_32F: 918 pIE->WMP.wmiI_Alpha.cLeadingPadding += (pIE->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(float) - 1; 919 break; 920 921 case BD_5: 922 case BD_10: 923 case BD_565: 924 default: 925 break; 926 } 927 928 // pIE->WMP.wmiSCP_Alpha.uAlphaMode = 1; 929 930 931 //assert(pIE->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now! 932 pIE->WMP.wmiI_Alpha.cfColorFormat = Y_ONLY; 933 934 pIE->WMP.wmiSCP_Alpha.cfColorFormat = Y_ONLY; 935 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); 939 940 Cleanup: 941 return err; 942 } 943 944 ERR PKImageEncode_EncodeAlpha_Encode( 945 PKImageEncode* pIE, 946 U32 cLine, 947 U8* pbPixels, 948 U32 cbStride) 949 { 950 ERR err = WMP_errSuccess; 951 U32 i = 0; 952 953 //================================ 954 for (i = 0; i < cLine; i += 16) 955 { 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); 961 } 962 pIE->idxCurrentLine += cLine; 963 964 Cleanup: 965 return err; 966 } 967 968 ERR PKImageEncode_EncodeAlpha_Term(PKImageEncode* pIE) 969 { 970 ERR err = WMP_errSuccess; 971 972 FailIf(ICERR_OK != ImageStrEncTerm(pIE->WMP.ctxSC_Alpha), WMP_errFail); 973 974 Cleanup: 975 return err; 976 } 977 978 ERR PKImageEncode_EncodeAlpha( 979 PKImageEncode* pIE, 980 PKPixelInfo PI, 981 U32 cLine, 982 U8* pbPixels, 983 U32 cbStride) 984 { 985 ERR err = WMP_errSuccess; 986 size_t offPos = 0; 987 988 Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); 989 if ((offPos & 1) != 0) 990 { 991 // Make the mark even if it is odd by inserting a pad byte 992 char zero = 0; 993 Call(pIE->pStream->Write(pIE->pStream, &zero, 1)); 994 offPos++; 995 } 996 pIE->WMP.nOffAlpha = (Long)offPos; 997 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)); 1001 1002 Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); 1003 pIE->WMP.nCbAlpha = (Long)offPos - pIE->WMP.nOffAlpha; 1004 1005 Cleanup: 1006 return err; 1007 } 1008 1009 1010 1011 static ERR SetMetadata(PKImageEncode *pIE, const U8 *pbMetadata, U32 cbMetadata, U8** pbSet, U32* pcbSet) 1012 { 1013 ERR err = WMP_errSuccess; 1014 1015 // Fail if the caller called us after we've already written the header out 1016 if (pIE->fHeaderDone) 1017 { 1018 assert(FALSE); // Message to programmer 1019 err = WMP_errOutOfSequence; 1020 goto Cleanup; 1021 } 1022 1023 // Make a copy of the metadata 1024 PKFree((void **) pbSet); 1025 *pcbSet = 0; 1026 1027 Call(PKAlloc((void **) pbSet, cbMetadata)); 1028 memcpy(*pbSet, pbMetadata, cbMetadata); 1029 *pcbSet = cbMetadata; 1030 1031 Cleanup: 1032 return err; 1033 } 1034 1035 1036 1037 ERR PKImageEncode_SetColorContext_WMP(PKImageEncode *pIE, 1038 const U8 *pbColorContext, 1039 U32 cbColorContext) 1040 { 1041 return SetMetadata(pIE, pbColorContext, cbColorContext, &pIE->pbColorContext, &pIE->cbColorContext); 1042 } 1043 1044 1045 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; 1049 char* pbTemp = 0; 1050 U32 cbTemp; 1051 char* pszFormatBegin; 1052 // const char* pszXMPMetadata = (const char*)pbXMPMetadata; 1053 size_t cbBuffer; 1054 1055 // Fail if the caller called us after we've already written the header out 1056 FailIf(pIE->fHeaderDone, WMP_errOutOfSequence); 1057 1058 // Free any previously set XMP metadata 1059 PKFree((void **) &pIE->pbXMPMetadata); 1060 pIE->cbXMPMetadataByteCount = 0; 1061 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 ) 1073 { 1074 char* pszFormatEnd; 1075 const char* pszLessThan; 1076 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; 1082 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), 1089 szHDPhotoFormat), 1090 WMP_errBufferOverflow); 1091 memcpy(pszFormatBegin + sizeof(szHDPhotoFormat) - 1, pbXMPMetadata + ( pszFormatEnd - pbTemp ), 1092 cbXMPMetadata - ( pszFormatEnd - pbTemp )); 1093 } 1094 else 1095 { 1096 cbTemp = cbXMPMetadata; 1097 } 1098 1099 pIE->pbXMPMetadata = (U8 *) pbTemp; 1100 pIE->cbXMPMetadataByteCount = cbTemp; 1101 return ( err ); 1102 1103 Cleanup: 1104 PKFree((void **) &pbTemp); 1105 pIE->cbXMPMetadataByteCount = 0; 1106 return err; 1107 } 1108 1109 1110 1111 ERR PKImageEncode_SetEXIFMetadata_WMP(PKImageEncode *pIE, const U8 *pbEXIFMetadata, U32 cbEXIFMetadata) 1112 { 1113 return SetMetadata(pIE, pbEXIFMetadata, cbEXIFMetadata, 1114 &pIE->pbEXIFMetadata, &pIE->cbEXIFMetadataByteCount); 1115 } 1116 1117 1118 1119 ERR PKImageEncode_SetGPSInfoMetadata_WMP(PKImageEncode *pIE, const U8 *pbGPSInfoMetadata, U32 cbGPSInfoMetadata) 1120 { 1121 return SetMetadata(pIE, pbGPSInfoMetadata, cbGPSInfoMetadata, 1122 &pIE->pbGPSInfoMetadata, &pIE->cbGPSInfoMetadataByteCount); 1123 } 1124 1125 1126 1127 ERR PKImageEncode_SetIPTCNAAMetadata_WMP(PKImageEncode *pIE, const U8 *pbIPTCNAAMetadata, U32 cbIPTCNAAMetadata) 1128 { 1129 return SetMetadata(pIE, pbIPTCNAAMetadata, cbIPTCNAAMetadata, 1130 &pIE->pbIPTCNAAMetadata, &pIE->cbIPTCNAAMetadataByteCount); 1131 } 1132 1133 1134 1135 ERR PKImageEncode_SetPhotoshopMetadata_WMP(PKImageEncode *pIE, const U8 *pbPhotoshopMetadata, U32 cbPhotoshopMetadata) 1136 { 1137 return SetMetadata(pIE, pbPhotoshopMetadata, cbPhotoshopMetadata, 1138 &pIE->pbPhotoshopMetadata, &pIE->cbPhotoshopMetadataByteCount); 1139 } 1140 1141 1142 1143 ERR PKImageEncode_SetDescriptiveMetadata_WMP(PKImageEncode *pIE, const DESCRIPTIVEMETADATA *pSrcMeta) 1144 { 1145 ERR err = WMP_errSuccess; 1146 DESCRIPTIVEMETADATA *pDstMeta = &pIE->sDescMetadata; 1147 1148 // Fail if the caller called us after we've already written the header out 1149 if (pIE->fHeaderDone) 1150 { 1151 assert(FALSE); // Message to programmer 1152 FailIf(TRUE, WMP_errOutOfSequence); 1153 } 1154 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)); 1170 1171 Cleanup: 1172 return err; 1173 } 1174 1175 1176 1177 ERR PKImageEncode_WritePixels_WMP( 1178 PKImageEncode* pIE, 1179 U32 cLine, 1180 U8* pbPixels, 1181 U32 cbStride) 1182 { 1183 ERR err = WMP_errSuccess; 1184 // U32 i = 0; 1185 PKPixelInfo PI; 1186 1187 // Performing non-banded encode 1188 assert(BANDEDENCSTATE_UNINITIALIZED == pIE->WMP.eBandedEncState); 1189 pIE->WMP.eBandedEncState = BANDEDENCSTATE_NONBANDEDENCODE; 1190 1191 PI.pGUIDPixFmt = &pIE->guidPixFormat; 1192 PixelFormatLookup(&PI, LOOKUP_FORWARD); 1193 pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha); 1194 1195 if (!pIE->fHeaderDone) 1196 { 1197 // write metadata 1198 Call(WriteContainerPre(pIE)); 1199 1200 pIE->fHeaderDone = !FALSE; 1201 } 1202 1203 /* if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2){ 1204 pIE->WMP.wmiSCP_Alpha = pIE->WMP.wmiSCP; 1205 } 1206 */ 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)); 1210 } 1211 1212 Call(WriteContainerPost(pIE)); 1213 1214 Cleanup: 1215 return err; 1216 } 1217 1218 1219 ERR PKImageEncode_WritePixelsBandedBegin_WMP(PKImageEncode* pIE, struct WMPStream *pPATempFile) 1220 { 1221 ERR err = WMP_errSuccess; 1222 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; 1226 1227 // Save the planar alpha tempfile for future use 1228 pIE->WMP.pPATempFile = pPATempFile; 1229 1230 //Cleanup: 1231 return err; 1232 } 1233 1234 ERR PKImageEncode_WritePixelsBanded_WMP(PKImageEncode* pIE, U32 cLine, U8* pbPixels, U32 cbStride, Bool fLastCall) 1235 { 1236 ERR err = WMP_errSuccess; 1237 PKPixelInfo PI = {0}; 1238 Bool fPI = FALSE; 1239 BANDEDENCSTATE eEncStateOrig = pIE->WMP.eBandedEncState; 1240 struct WMPStream *pPATempFile = pIE->WMP.pPATempFile; 1241 1242 // Unless this is the last call, reject inputs which are not multiples of 16 1243 FailIf(!fLastCall && 0 != cLine % 16, WMP_errMustBeMultipleOf16LinesUntilLastCall); 1244 1245 if (!pIE->fHeaderDone || BANDEDENCSTATE_INIT == pIE->WMP.eBandedEncState) 1246 { 1247 PI.pGUIDPixFmt = &pIE->guidPixFormat; 1248 PixelFormatLookup(&PI, LOOKUP_FORWARD); 1249 pIE->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha); 1250 fPI = TRUE; 1251 1252 // Check if this is planar alpha: banded encode requires temp file 1253 if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) 1254 { 1255 FailIf(NULL == pPATempFile, WMP_errPlanarAlphaBandedEncRequiresTempFile); 1256 } 1257 } 1258 1259 if (!pIE->fHeaderDone) 1260 { 1261 // write metadata 1262 assert(fPI); 1263 Call(WriteContainerPre(pIE)); 1264 pIE->fHeaderDone = !FALSE; 1265 } 1266 1267 if (BANDEDENCSTATE_INIT == pIE->WMP.eBandedEncState) 1268 { 1269 // Record start of main content for future call to WriteContainerPost 1270 size_t offPos; 1271 Call(pIE->pStream->GetPos(pIE->pStream, &offPos)); 1272 pIE->WMP.nOffImage = (Long)offPos; 1273 1274 assert(fPI); 1275 Call(PKImageEncode_EncodeContent_Init(pIE, PI, cLine, pbPixels, cbStride)); 1276 pIE->WMP.eBandedEncState = BANDEDENCSTATE_ENCODING; 1277 } 1278 1279 Call(PKImageEncode_EncodeContent_Encode(pIE, cLine, pbPixels, cbStride)); 1280 if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) 1281 { 1282 //planar alpha 1283 if (BANDEDENCSTATE_INIT == eEncStateOrig) 1284 { 1285 size_t offStart; 1286 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); 1291 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)); 1295 } 1296 1297 Call(PKImageEncode_EncodeAlpha_Encode(pIE, cLine, pbPixels, cbStride)); 1298 } 1299 1300 Cleanup: 1301 return err; 1302 } 1303 1304 ERR PKImageEncode_WritePixelsBandedEnd_WMP(PKImageEncode* pIE) 1305 { 1306 ERR err = WMP_errSuccess; 1307 struct WMPStream *pMainStream = pIE->WMP.wmiSCP.pWStream; 1308 size_t offAlpha; 1309 1310 assert(BANDEDENCSTATE_ENCODING == pIE->WMP.eBandedEncState); 1311 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; 1316 1317 if (pIE->WMP.bHasAlpha && pIE->WMP.wmiSCP.uAlphaMode == 2) 1318 { 1319 size_t cbAlpha; 1320 size_t cbBytesCopied; 1321 struct WMPStream *pAlphaStream = pIE->WMP.wmiSCP_Alpha.pWStream; 1322 1323 assert(pAlphaStream != pMainStream); // Otherwise we didn't use a temp file 1324 1325 // Close it up - this causes write to temp file 1326 Call(PKImageEncode_EncodeAlpha_Term(pIE)); 1327 1328 // Calculate size of alpha bitstream and its new offset 1329 Call(pAlphaStream->GetPos(pAlphaStream, &cbAlpha)); 1330 1331 // Copy alpha bitstream to end of main stream 1332 cbBytesCopied = 0; 1333 Call(pAlphaStream->SetPos(pAlphaStream, 0)); 1334 while (cbBytesCopied < cbAlpha) 1335 { 1336 char rgbBuf[TEMPFILE_COPYBUF_SIZE]; 1337 size_t cbCopy; 1338 1339 cbCopy = min(sizeof(rgbBuf), cbAlpha - cbBytesCopied); 1340 Call(pAlphaStream->Read(pAlphaStream, rgbBuf, cbCopy)); 1341 Call(pMainStream->Write(pMainStream, rgbBuf, cbCopy)); 1342 1343 cbBytesCopied += cbCopy; 1344 } 1345 assert(cbBytesCopied == cbAlpha); 1346 1347 // Update alpha offset/length for WriteContainerPost 1348 pIE->WMP.nOffAlpha = (Long)offAlpha; 1349 pIE->WMP.nCbAlpha = (Long)cbAlpha; 1350 } 1351 1352 Call(WriteContainerPost(pIE)); 1353 1354 Cleanup: 1355 return err; 1356 } 1357 1358 1359 ERR PKImageEncode_Transcode_WMP( 1360 PKImageEncode* pIE, 1361 PKImageDecode* pID, 1362 CWMTranscodingParam* pParam) 1363 { 1364 ERR err = WMP_errSuccess; 1365 Float fResX = 0, fResY = 0; 1366 PKPixelFormatGUID pixGUID = {0}; 1367 CWMTranscodingParam tcParamAlpha; 1368 size_t offPos = 0; 1369 Bool fPlanarAlpha; 1370 PKPixelInfo PI; 1371 1372 struct WMPStream* pWSDec = NULL; 1373 struct WMPStream* pWSEnc= pIE->pStream; 1374 1375 // pass through metadata 1376 Call(pID->GetPixelFormat(pID, &pixGUID)); 1377 Call(pIE->SetPixelFormat(pIE, pixGUID)); 1378 1379 Call(pIE->SetSize(pIE, (I32)pParam->cWidth, (I32)pParam->cHeight)); 1380 1381 Call(pID->GetResolution(pID, &fResX, &fResY)); 1382 Call(pIE->SetResolution(pIE, fResX, fResY)); 1383 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! 1388 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 1400 1401 fPlanarAlpha = pIE->WMP.bHasAlpha && (2 == pParam->uAlphaMode); 1402 1403 // write matadata 1404 Call(WriteContainerPre(pIE)); 1405 1406 // Copy transcoding params for alpha (codec changes the struct) 1407 if (fPlanarAlpha) 1408 tcParamAlpha = *pParam; 1409 1410 // write compressed bitstream 1411 Call(pID->GetRawStream(pID, &pWSDec)); 1412 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; 1416 1417 if (fPlanarAlpha) 1418 { 1419 pIE->WMP.nOffAlpha = (Long)offPos; 1420 1421 // Cue the stream to alpha block 1422 assert(pID->WMP.wmiDEMisc.uAlphaOffset > 0); 1423 Call(pWSDec->SetPos(pWSDec, pID->WMP.wmiDEMisc.uAlphaOffset)); 1424 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; 1428 } 1429 1430 // fixup matadata 1431 Call(WriteContainerPost(pIE)); 1432 1433 Cleanup: 1434 return err; 1435 } 1436 1437 ERR PKImageEncode_CreateNewFrame_WMP( 1438 PKImageEncode* pIE, 1439 void* pvParam, 1440 size_t cbParam) 1441 { 1442 ERR err = WMP_errSuccess; 1443 1444 UNREFERENCED_PARAMETER( pIE ); 1445 UNREFERENCED_PARAMETER( pvParam ); 1446 UNREFERENCED_PARAMETER( cbParam ); 1447 1448 Call(WMP_errNotYetImplemented); 1449 1450 Cleanup: 1451 return err; 1452 } 1453 1454 ERR PKImageEncode_Release_WMP( 1455 PKImageEncode** ppIE) 1456 { 1457 ERR err = WMP_errSuccess; 1458 1459 PKImageEncode *pIE = *ppIE; 1460 pIE->pStream->Close(&pIE->pStream); 1461 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; 1474 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); 1490 1491 Call(PKFree((void **) ppIE)); 1492 1493 Cleanup: 1494 return err; 1495 } 1496 1497 //---------------------------------------------------------------- 1498 ERR PKImageEncode_Create_WMP(PKImageEncode** ppIE) 1499 { 1500 ERR err = WMP_errSuccess; 1501 1502 PKImageEncode* pIE = NULL; 1503 1504 Call(PKImageEncode_Create(ppIE)); 1505 1506 pIE = *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; 1512 1513 pIE->WritePixelsBandedBegin = PKImageEncode_WritePixelsBandedBegin_WMP; 1514 pIE->WritePixelsBanded = PKImageEncode_WritePixelsBanded_WMP; 1515 pIE->WritePixelsBandedEnd = PKImageEncode_WritePixelsBandedEnd_WMP; 1516 1517 pIE->Transcode = PKImageEncode_Transcode_WMP; 1518 pIE->CreateNewFrame = PKImageEncode_CreateNewFrame_WMP; 1519 pIE->Release = PKImageEncode_Release_WMP; 1520 pIE->bWMP = TRUE; 1521 1522 Cleanup: 1523 return err; 1524 } 1525 1526 1527 //================================================================ 1528 // PKImageDecode_WMP 1529 //================================================================ 1530 ERR ParsePFDEntry( 1531 PKImageDecode* pID, 1532 U16 uTag, 1533 U16 uType, 1534 U32 uCount, 1535 U32 uValue) 1536 { 1537 ERR err = WMP_errSuccess; 1538 ERR errTmp = WMP_errSuccess; 1539 PKPixelInfo PI; 1540 struct WMPStream* pWS = pID->pStream; 1541 // size_t offPos = 0; 1542 1543 union uf{ 1544 U32 uVal; 1545 Float fVal; 1546 }ufValue = {0}; 1547 1548 //================================ 1549 switch (uTag) 1550 { 1551 case WMP_tagPixelFormat: 1552 { 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)); 1559 1560 PI.pGUIDPixFmt = &pID->guidPixFormat; 1561 PixelFormatLookup(&PI, LOOKUP_FORWARD); 1562 1563 pID->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha); 1564 pID->WMP.wmiI.cBitsPerUnit = PI.cbitUnit; 1565 pID->WMP.wmiI.bRGB = !(PI.grBit & PK_pixfmtBGR); 1566 1567 break; 1568 } 1569 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; 1575 break; 1576 1577 case WMP_tagImageWidth: 1578 FailIf(0 == uValue, WMP_errUnsupportedFormat); 1579 break; 1580 1581 case WMP_tagImageHeight: 1582 FailIf(0 == uValue, WMP_errUnsupportedFormat); 1583 break; 1584 1585 case WMP_tagImageOffset: 1586 FailIf(1 != uCount, WMP_errUnsupportedFormat); 1587 pID->WMP.wmiDEMisc.uImageOffset = uValue; 1588 break; 1589 1590 case WMP_tagImageByteCount: 1591 FailIf(1 != uCount, WMP_errUnsupportedFormat); 1592 pID->WMP.wmiDEMisc.uImageByteCount = uValue; 1593 break; 1594 1595 case WMP_tagAlphaOffset: 1596 FailIf(1 != uCount, WMP_errUnsupportedFormat); 1597 pID->WMP.wmiDEMisc.uAlphaOffset = uValue; 1598 break; 1599 1600 case WMP_tagAlphaByteCount: 1601 FailIf(1 != uCount, WMP_errUnsupportedFormat); 1602 pID->WMP.wmiDEMisc.uAlphaByteCount = uValue; 1603 break; 1604 1605 case WMP_tagWidthResolution: 1606 FailIf(1 != uCount, WMP_errUnsupportedFormat); 1607 ufValue.uVal = uValue; 1608 pID->fResX = ufValue.fVal; 1609 break; 1610 1611 case WMP_tagHeightResolution: 1612 FailIf(1 != uCount, WMP_errUnsupportedFormat); 1613 ufValue.uVal = uValue; 1614 pID->fResY = ufValue.fVal; 1615 break; 1616 1617 case WMP_tagIccProfile: 1618 pID->WMP.wmiDEMisc.uColorProfileByteCount = uCount; 1619 pID->WMP.wmiDEMisc.uColorProfileOffset = uValue; 1620 break; 1621 1622 case WMP_tagXMPMetadata: 1623 pID->WMP.wmiDEMisc.uXMPMetadataByteCount = uCount; 1624 pID->WMP.wmiDEMisc.uXMPMetadataOffset = uValue; 1625 break; 1626 1627 case WMP_tagEXIFMetadata: 1628 pID->WMP.wmiDEMisc.uEXIFMetadataOffset = uValue; 1629 CallIgnoreError(errTmp, StreamCalcIFDSize(pWS, uValue, &pID->WMP.wmiDEMisc.uEXIFMetadataByteCount)); 1630 break; 1631 1632 case WMP_tagGPSInfoMetadata: 1633 pID->WMP.wmiDEMisc.uGPSInfoMetadataOffset = uValue; 1634 CallIgnoreError(errTmp, StreamCalcIFDSize(pWS, uValue, &pID->WMP.wmiDEMisc.uGPSInfoMetadataByteCount)); 1635 break; 1636 1637 case WMP_tagIPTCNAAMetadata: 1638 pID->WMP.wmiDEMisc.uIPTCNAAMetadataByteCount = uCount; 1639 pID->WMP.wmiDEMisc.uIPTCNAAMetadataOffset = uValue; 1640 break; 1641 1642 case WMP_tagPhotoshopMetadata: 1643 pID->WMP.wmiDEMisc.uPhotoshopMetadataByteCount = uCount; 1644 pID->WMP.wmiDEMisc.uPhotoshopMetadataOffset = uValue; 1645 break; 1646 1647 case WMP_tagCompression: 1648 case WMP_tagImageType: 1649 case WMP_tagImageDataDiscard: 1650 case WMP_tagAlphaDataDiscard: 1651 break; 1652 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); 1658 break; 1659 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); 1664 break; 1665 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); 1670 break; 1671 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); 1676 break; 1677 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); 1682 break; 1683 1684 case WMP_tagArtist: 1685 CallIgnoreError(errTmp, ReadPropvar(pWS, uType, uCount, uValue, 1686 &pID->WMP.sDescMetadata.pvarArtist)); 1687 assert(DPKVT_LPSTR == pID->WMP.sDescMetadata.pvarArtist.vt); 1688 break; 1689 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); 1694 break; 1695 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); 1700 break; 1701 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); 1706 break; 1707 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); 1712 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; 1720 break; 1721 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); 1726 break; 1727 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); 1732 break; 1733 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); 1738 break; 1739 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); 1744 break; 1745 1746 default: 1747 fprintf(stderr, "Unrecognized WMPTag: %d(%#x), %d, %d, %#x" CRLF, 1748 (int)uTag, (int)uTag, (int)uType, (int)uCount, (int)uValue); 1749 break; 1750 } 1751 1752 Cleanup: 1753 return err; 1754 } 1755 1756 ERR ParsePFD( 1757 PKImageDecode* pID, 1758 size_t offPos, 1759 U16 cEntry) 1760 { 1761 ERR err = WMP_errSuccess; 1762 struct WMPStream* pWS = pID->pStream; 1763 U16 i = 0; 1764 1765 for (i = 0; i < cEntry; ++i) 1766 { 1767 U16 uTag = 0; 1768 U16 uType = 0; 1769 U32 uCount = 0; 1770 U32 uValue = 0; 1771 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; 1776 1777 Call(ParsePFDEntry(pID, uTag, uType, uCount, uValue)); 1778 } 1779 1780 pID->WMP.bHasAlpha = ((pID->WMP.bHasAlpha) && (pID->WMP.wmiDEMisc.uAlphaOffset != 0) && (pID->WMP.wmiDEMisc.uAlphaByteCount != 0));//has planar alpha 1781 1782 Cleanup: 1783 return err; 1784 } 1785 1786 ERR ReadContainer( 1787 PKImageDecode* pID) 1788 { 1789 ERR err = WMP_errSuccess; 1790 1791 struct WMPStream* pWS = pID->pStream; 1792 size_t offPos = 0; 1793 1794 char szSig[2] = {0}; 1795 U16 uWmpID = 0; 1796 U32 offPFD = 0; 1797 U16 cPFDEntry = 0; 1798 U8 bVersion; 1799 1800 //================================ 1801 Call(pWS->GetPos(pWS, &offPos)); 1802 FailIf(0 != offPos, WMP_errUnsupportedFormat); 1803 1804 //================================ 1805 // Header 1806 Call(pWS->Read(pWS, szSig, sizeof(szSig))); offPos += 2; 1807 FailIf(szSig != strstr(szSig, "II"), WMP_errUnsupportedFormat); 1808 1809 Call(GetUShort(pWS, offPos, &uWmpID)); offPos += 2; 1810 FailIf(WMP_valWMPhotoID != (0x00FF & uWmpID), WMP_errUnsupportedFormat); 1811 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); 1815 1816 Call(GetULong(pWS, offPos, &offPFD)); offPos += 4; 1817 1818 //================================ 1819 // PFD 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)); 1824 1825 //================================ 1826 Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uImageOffset)); 1827 1828 Cleanup: 1829 return err; 1830 } 1831 1832 1833 //================================================ 1834 ERR PKImageDecode_Initialize_WMP( 1835 PKImageDecode* pID, 1836 struct WMPStream* pWS) 1837 { 1838 ERR err = WMP_errSuccess; 1839 1840 CWMImageInfo* pII = NULL; 1841 1842 //================================ 1843 Call(PKImageDecode_Initialize(pID, pWS)); 1844 1845 //================================ 1846 Call(ReadContainer(pID)); 1847 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; 1854 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); 1858 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) 1863 { 1864 pID->WMP.wmiI.oOrientation = pID->WMP.oOrientationFromContainer; 1865 } 1866 else 1867 { 1868 // Force to O_NONE to match Vista decode behaviour 1869 pID->WMP.wmiI.oOrientation = O_NONE; 1870 } 1871 1872 pII = &pID->WMP.wmiI; 1873 pID->uWidth = (U32)pII->cWidth; 1874 pID->uHeight = (U32)pII->cHeight; 1875 1876 Cleanup: 1877 return err; 1878 } 1879 1880 1881 ERR PKImageDecode_GetSize_WMP( 1882 PKImageDecode* pID, 1883 I32* piWidth, 1884 I32* piHeight) 1885 { 1886 if (pID->WMP.wmiI.oOrientation >= O_RCW) 1887 { 1888 *piWidth = (I32)pID->uHeight; 1889 *piHeight = (I32)pID->uWidth; 1890 } 1891 else 1892 { 1893 *piWidth = (I32)pID->uWidth; 1894 *piHeight = (I32)pID->uHeight; 1895 } 1896 return WMP_errSuccess; 1897 } 1898 1899 1900 ERR PKImageDecode_GetRawStream_WMP( 1901 PKImageDecode* pID, 1902 struct WMPStream** ppWS) 1903 { 1904 ERR err = WMP_errSuccess; 1905 struct WMPStream* pWS = pID->pStream; 1906 1907 *ppWS = NULL; 1908 Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uImageOffset)); 1909 *ppWS = pWS; 1910 1911 Cleanup: 1912 return err; 1913 } 1914 1915 ERR PKImageDecode_Copy_WMP( 1916 PKImageDecode* pID, 1917 const PKRect* pRect, 1918 U8* pb, 1919 U32 cbStride) 1920 { 1921 ERR err = WMP_errSuccess; 1922 U32 cThumbnailScale; 1923 U32 linesperMBRow; 1924 CWMImageBufferInfo wmiBI = { 0 }; 1925 #ifdef REENTRANT_MODE 1926 U8 *pbLowMemAdj = NULL; 1927 U32 i, cMBRow; 1928 U32 cMBRowStart; 1929 #endif // REENTRANT_MODE 1930 struct WMPStream* pWS = pID->pStream; 1931 U8 tempAlphaMode = 0; 1932 wmiBI.pv = pb; 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)) 1937 #else 1938 FailIf(0 != pRect->X, WMP_errInvalidParameter); 1939 FailIf(0 != pRect->Y, WMP_errInvalidParameter); 1940 #endif // REENTRANT_MODE 1941 1942 cThumbnailScale = 1; 1943 if (pID->WMP.wmiI.cThumbnailWidth > 0) 1944 { 1945 while(cThumbnailScale * pID->WMP.wmiI.cThumbnailWidth < pID->uWidth) 1946 cThumbnailScale <<= 1; 1947 } 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; 1953 1954 #ifdef REENTRANT_MODE 1955 if (0 == pID->WMP.DecoderCurrMBRow) 1956 { 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 1963 { 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 1967 } 1968 #ifdef REENTRANT_MODE 1969 } 1970 #endif // REENTRANT_MODE 1971 //if(pID->WMP.wmiSCP.uAlphaMode != 1) 1972 if((!pID->WMP.bHasAlpha) || (pID->WMP.wmiSCP.uAlphaMode != 1)) 1973 { 1974 if(pID->WMP.bHasAlpha)//planar alpha 1975 { 1976 tempAlphaMode = pID->WMP.wmiSCP.uAlphaMode; 1977 pID->WMP.wmiSCP.uAlphaMode = 0; 1978 } 1979 pID->WMP.wmiSCP.fMeasurePerf = TRUE; 1980 #ifdef REENTRANT_MODE 1981 if (0 == pID->WMP.DecoderCurrMBRow) 1982 { 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); 1985 } 1986 cMBRow = ((U32) pID->WMP.wmiI.cROITopY + pRect->Y + pRect->Height + linesperMBRow - 1) / linesperMBRow + 1; 1987 cMBRowStart = pRect->Y / linesperMBRow + 1; 1988 // if current request starts before current state, then rewind. 1989 if (cMBRowStart < pID->WMP.DecoderCurrMBRow) 1990 { 1991 pID->WMP.DecoderCurrMBRow = 0; 1992 pID->WMP.cLinesDecoded = 0; 1993 pID->WMP.cLinesCropped = 0; 1994 pID->WMP.fFirstNonZeroDecode = FALSE; 1995 FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail); 1996 Call(pID->WMP.wmiSCP.pWStream->SetPos(pID->WMP.wmiSCP.pWStream, pID->WMP.cMarker)); 1997 FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail); 1998 } 1999 2000 // In "Low Memory mode", we don't have full frame buffer. We therefore cannot rotate the image. 2001 // We can flip H, V and HV, but no rotations. 2002 FailIf(pID->WMP.wmiI.oOrientation >= O_RCW, WMP_errFail); 2003 2004 // In low-memory mode, the full frame buffer is unavailable. This doesn't seem to 2005 // matter in O_NONE and O_FLIPH, but for O_FLIPV and O_FLIPVH, outputMBRow tries to write to 2006 // the bottom of full-frame buffer. Adjust the buffer pointer to compensate. 2007 if (O_FLIPV == pID->WMP.wmiI.oOrientation || O_FLIPVH == pID->WMP.wmiI.oOrientation) 2008 { 2009 I32 iActualY2 = pRect->Y + pRect->Height; 2010 pbLowMemAdj = pb - (pID->WMP.wmiI.cROIHeight - (iActualY2 - pID->WMP.cLinesCropped)) * cbStride; 2011 } 2012 else 2013 { 2014 pbLowMemAdj = pb - (pRect->Y - pID->WMP.cLinesCropped) * cbStride; 2015 } 2016 wmiBI.pv = pbLowMemAdj; 2017 2018 for (i = (U32)pID->WMP.DecoderCurrMBRow; i < cMBRow; i++) 2019 { 2020 size_t cLinesDecoded; 2021 wmiBI.uiFirstMBRow = i; 2022 wmiBI.uiLastMBRow = i; 2023 FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC, &wmiBI, &cLinesDecoded), WMP_errFail); 2024 pID->WMP.cLinesDecoded += cLinesDecoded; 2025 if (FALSE == pID->WMP.fFirstNonZeroDecode && cLinesDecoded > 0) 2026 { 2027 pID->WMP.cLinesCropped += (linesperMBRow - cLinesDecoded); 2028 pID->WMP.fFirstNonZeroDecode = TRUE; 2029 } 2030 2031 if (0 == cLinesDecoded && pRect->Y > 0) 2032 { 2033 pID->WMP.cLinesCropped += linesperMBRow; 2034 } 2035 } 2036 wmiBI.pv = pbLowMemAdj; 2037 2038 // If we're past the top of the image, then we're done, so terminate. 2039 if (linesperMBRow * (cMBRow - 1) >= pID->WMP.wmiI.cROIHeight) { 2040 FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail); 2041 } 2042 pID->WMP.DecoderCurrMBRow = cMBRow; // Set to next possible MBRow that is decodable 2043 2044 #else 2045 FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI, &pID->WMP.wmiSCP, &pID->WMP.ctxSC), WMP_errFail); 2046 FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC, &wmiBI), WMP_errFail); 2047 FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC), WMP_errFail); 2048 #endif //REENTRANT_MODE 2049 2050 if(pID->WMP.bHasAlpha)//planar alpha 2051 { 2052 pID->WMP.wmiSCP.uAlphaMode = tempAlphaMode; 2053 } 2054 } 2055 2056 // if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode == 2) 2057 // if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode != 1) 2058 if(pID->WMP.bHasAlpha && pID->WMP.wmiSCP.uAlphaMode != 0) 2059 { 2060 pID->WMP.wmiI_Alpha = pID->WMP.wmiI; 2061 pID->WMP.wmiSCP_Alpha = pID->WMP.wmiSCP; 2062 2063 // assert(pID->WMP.wmiI_Alpha.cfColorFormat == CF_RGB); // only RGBA is supported for now! 2064 pID->WMP.wmiI_Alpha.cfColorFormat = Y_ONLY; 2065 2066 switch (pID->WMP.wmiI.bdBitDepth) 2067 { 2068 case BD_8: 2069 pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) - 1; 2070 break; 2071 2072 case BD_16: 2073 case BD_16S: 2074 case BD_16F: 2075 pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(U16) - 1; 2076 break; 2077 2078 case BD_32: 2079 case BD_32S: 2080 case BD_32F: 2081 pID->WMP.wmiI_Alpha.cLeadingPadding += (pID->WMP.wmiI.cBitsPerUnit >> 3) / sizeof(float) - 1; 2082 break; 2083 2084 case BD_5: 2085 case BD_10: 2086 case BD_565: 2087 default: 2088 break; 2089 } 2090 2091 pID->WMP.wmiSCP_Alpha.fMeasurePerf = TRUE; 2092 Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uAlphaOffset)); 2093 #ifdef REENTRANT_MODE 2094 if (0 == pID->WMP.DecoderCurrAlphaMBRow) // add this to WMP struct! 2095 { 2096 FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail); 2097 } 2098 2099 cMBRow = ((U32) pID->WMP.wmiI.cROITopY + pRect->Y + pRect->Height + linesperMBRow - 1) / linesperMBRow + 1; 2100 cMBRowStart = pRect->Y / linesperMBRow + 1; 2101 // if current request starts before current state, then rewind. 2102 if (cMBRowStart < pID->WMP.DecoderCurrAlphaMBRow) 2103 { 2104 pID->WMP.DecoderCurrAlphaMBRow = 0; 2105 FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail); 2106 FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail); 2107 } 2108 2109 for (i = (U32)pID->WMP.DecoderCurrAlphaMBRow; i < cMBRow; i++) 2110 { 2111 size_t cLinesDecoded; 2112 wmiBI.uiFirstMBRow = i; 2113 wmiBI.uiLastMBRow = i; 2114 FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC_Alpha, &wmiBI, &cLinesDecoded), WMP_errFail); 2115 } 2116 2117 // If we're past the top of the image, then we're done, so terminate 2118 if (linesperMBRow * (cMBRow - 1) >= pID->WMP.wmiI.cROIHeight) { 2119 FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail); 2120 } 2121 pID->WMP.DecoderCurrAlphaMBRow = cMBRow; // Set to next possible MBRow that is decodable 2122 wmiBI.pv = pb; 2123 #else 2124 FailIf(ICERR_OK != ImageStrDecInit(&pID->WMP.wmiI_Alpha, &pID->WMP.wmiSCP_Alpha, &pID->WMP.ctxSC_Alpha), WMP_errFail); 2125 FailIf(ICERR_OK != ImageStrDecDecode(pID->WMP.ctxSC_Alpha, &wmiBI), WMP_errFail); 2126 FailIf(ICERR_OK != ImageStrDecTerm(pID->WMP.ctxSC_Alpha), WMP_errFail); 2127 #endif //REENTRANT_MODE 2128 } 2129 2130 pID->idxCurrentLine += pRect->Height; 2131 2132 Cleanup: 2133 return err; 2134 } 2135 2136 2137 ERR PKImageDecode_GetMetadata_WMP(PKImageDecode *pID, U32 uOffset, U32 uByteCount, U8 *pbGot, U32 *pcbGot) 2138 { 2139 ERR err = WMP_errSuccess; 2140 2141 if (pbGot && uOffset) 2142 { 2143 struct WMPStream* pWS = pID->pStream; 2144 size_t iCurrPos; 2145 2146 FailIf(*pcbGot < uByteCount, WMP_errBufferOverflow); 2147 Call(pWS->GetPos(pWS, &iCurrPos)); 2148 Call(pWS->SetPos(pWS, uOffset)); 2149 Call(pWS->Read(pWS, pbGot, uByteCount)); 2150 Call(pWS->SetPos(pWS, iCurrPos)); 2151 } 2152 2153 Cleanup: 2154 if (Failed(err)) 2155 *pcbGot = 0; 2156 else 2157 *pcbGot = uByteCount; 2158 2159 return err; 2160 } 2161 2162 2163 2164 ERR PKImageDecode_GetColorContext_WMP(PKImageDecode *pID, U8 *pbColorContext, U32 *pcbColorContext) 2165 { 2166 return PKImageDecode_GetMetadata_WMP(pID, pID->WMP.wmiDEMisc.uColorProfileOffset, 2167 pID->WMP.wmiDEMisc.uColorProfileByteCount, pbColorContext, pcbColorContext); 2168 } 2169 2170 2171 2172 ERR PKImageDecode_GetDescriptiveMetadata_WMP(PKImageDecode *pID, DESCRIPTIVEMETADATA *pDescMetadata) 2173 { 2174 ERR err = WMP_errSuccess; 2175 *pDescMetadata = pID->WMP.sDescMetadata; 2176 return err; 2177 } 2178 2179 2180 ERR PKImageDecode_Release_WMP(PKImageDecode** ppID) 2181 { 2182 ERR err = WMP_errSuccess; 2183 PKImageDecode *pID; 2184 2185 if (NULL == ppID) 2186 goto Cleanup; 2187 2188 pID = *ppID; 2189 2190 // Free descriptive metadata 2191 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarImageDescription); 2192 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCameraMake); 2193 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCameraModel); 2194 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarSoftware); 2195 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarDateTime); 2196 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarArtist); 2197 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCopyright); 2198 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarRatingStars); 2199 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarRatingValue); 2200 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarCaption); 2201 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarDocumentName); 2202 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarPageName); 2203 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarPageNumber); 2204 FreeDescMetadata(&pID->WMP.sDescMetadata.pvarHostComputer); 2205 2206 // Release base class 2207 Call(PKImageDecode_Release(ppID)); 2208 2209 Cleanup: 2210 return err; 2211 } 2212 2213 2214 2215 ERR PKImageDecode_Create_WMP(PKImageDecode** ppID) 2216 { 2217 ERR err = WMP_errSuccess; 2218 PKImageDecode* pID = NULL; 2219 2220 Call(PKImageDecode_Create(ppID)); 2221 2222 pID = *ppID; 2223 pID->Initialize = PKImageDecode_Initialize_WMP; 2224 pID->GetSize = PKImageDecode_GetSize_WMP; 2225 pID->GetRawStream = PKImageDecode_GetRawStream_WMP; 2226 pID->Copy = PKImageDecode_Copy_WMP; 2227 pID->GetColorContext = PKImageDecode_GetColorContext_WMP; 2228 pID->GetDescriptiveMetadata = PKImageDecode_GetDescriptiveMetadata_WMP; 2229 pID->Release = PKImageDecode_Release_WMP; 2230 2231 Cleanup: 2232 return err; 2233 } 2234