github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/jxr/jxrlib/jxrtestlib/JXRTestTif.c (about) 1 //*@@@+++@@@@****************************************************************** 2 // 3 // Copyright Microsoft Corp. 4 // All rights reserved. 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are met: 8 // 9 // Redistributions of source code must retain the above copyright notice, 10 // this list of conditions and the following disclaimer. 11 // Redistributions in binary form must reproduce the above copyright notice, 12 // this list of conditions and the following disclaimer in the documentation 13 // and/or other materials provided with the distribution. 14 // 15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 // POSSIBILITY OF SUCH DAMAGE. 26 // 27 //*@@@---@@@@****************************************************************** 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include <strcodec.h> 32 #include <JXRTest.h> 33 34 //================================================================ 35 #define TIF_tagNull 0 36 #define TIF_tagSubfileType 0xff 37 #define TIF_tagNewSubfileType 0xfe 38 #define TIF_tagImageWidth 0x100 39 #define TIF_tagImageLength 0x101 40 #define TIF_tagBitsPerSample 0x102 41 #define TIF_tagCompression 0x103 42 #define TIF_tagPhotometricInterpretation 0x106 43 #define TIF_tagStripOffsets 0x111 44 #define TIF_tagOrientation 0x112 45 #define TIF_tagSamplesPerPixel 0x115 46 #define TIF_tagRowsPerStrip 0x116 47 #define TIF_tagStripByteCounts 0x117 48 #define TIF_tagXResolution 0x11a 49 #define TIF_tagYResolution 0x11b 50 #define TIF_tagPlanarConfiguration 0x11c 51 #define TIF_tagResolutionUnit 0x128 52 #define TIF_tagSoftware 0x131 53 #define TIF_tagColorMap 0x140 54 #define TIF_tagPredictor 0x13d 55 #define TIF_tagInkSet 0x14c 56 #define TIF_tagExtraSamples 0x152 57 #define TIF_tagSampleFormat 0x153 58 59 #define TIF_typBYTE 1 60 #define TIF_typASCII 2 61 #define TIF_typSHORT 3 62 #define TIF_typLONG 4 63 #define TIF_typRATIOAL 5 64 #define TIF_typSBYTE 6 65 #define TIF_typUNDEFINED 7 66 #define TIF_typSSHORT 8 67 #define TIF_typSLONG 9 68 #define TIF_typSRATIONAL 10 69 #define TIF_typFLOAT 11 70 #define TIF_typDOUBLE 12 71 72 73 //================================================================ 74 typedef float FLOAT; 75 typedef double DOUBLE; 76 77 78 //================================================================ 79 // PKImageEncode_TIF helpers 80 //================================================================ 81 typedef struct tagTifDE 82 { 83 U16 uTag; 84 U16 uType; 85 U32 uCount; 86 U32 uValueOrOffset; 87 } TifDE; 88 89 typedef struct tagTifDEMisc 90 { 91 U32 offBitsPerSample; 92 U32 offSampleFormat; 93 U32 bps, spp, sf; 94 U32 iPhotometricInterpretation; 95 96 U32 offXResolution; 97 U32 resXF, resXD; 98 99 U32 offYResolution; 100 U32 resYF, resYD; 101 } TifDEMisc; 102 103 ERR PutTifUShort( 104 struct WMPStream* pS, 105 size_t offPos, 106 U16 uValue) 107 { 108 ERR err = WMP_errSuccess; 109 110 Call(pS->SetPos(pS, offPos)); 111 Call(pS->Write(pS, &uValue, sizeof(uValue))); 112 113 Cleanup: 114 return err; 115 } 116 117 ERR PutTifULong( 118 struct WMPStream* pS, 119 size_t offPos, 120 U32 uValue) 121 { 122 ERR err = WMP_errSuccess; 123 124 Call(pS->SetPos(pS, offPos)); 125 Call(pS->Write(pS, &uValue, sizeof(uValue))); 126 127 Cleanup: 128 return err; 129 } 130 131 ERR WriteTifDE( 132 struct WMPStream* pS, 133 size_t offPos, 134 TifDE* pDE) 135 { 136 ERR err = WMP_errSuccess; 137 138 assert(-1 != pDE->uCount); 139 assert(-1 != pDE->uValueOrOffset); 140 141 Call(PutTifUShort(pS, offPos, pDE->uTag)); offPos += 2; 142 Call(PutTifUShort(pS, offPos, pDE->uType)); offPos += 2; 143 Call(PutTifULong(pS, offPos, pDE->uCount)); offPos += 4; 144 145 switch (pDE->uType) 146 { 147 case TIF_typSHORT: 148 if (1 == pDE->uCount) 149 { 150 Call(PutTifUShort(pS, offPos, (U16)pDE->uValueOrOffset)); offPos += 2; 151 Call(PutTifUShort(pS, offPos, 0)); offPos += 2; 152 break; 153 } 154 155 case TIF_typLONG: 156 case TIF_typRATIOAL: 157 Call(PutTifULong(pS, offPos, pDE->uValueOrOffset)); offPos += 4; 158 break; 159 160 default: 161 Call(WMP_errInvalidParameter); 162 break; 163 } 164 165 Cleanup: 166 return err; 167 } 168 169 ERR WriteTifHeader( 170 PKImageEncode* pIE) 171 { 172 ERR err = WMP_errSuccess; 173 struct WMPStream* pS = pIE->pStream; 174 size_t offPos = 0; 175 176 #ifdef _BIG__ENDIAN_ 177 U8 IIMM[3] = "MM"; 178 #else // _BIG__ENDIAN_ 179 U8 IIMM[3] = "II"; 180 #endif // _BIG__ENDIAN_ 181 182 TifDEMisc tifDEMisc = { 183 (U32) -1, (U32) -1, (U32) -1, (U32) -1, (U32) -1, 184 2, // photometric interpretation 185 (U32) -1, 10000, 10000, 186 (U32) -1, 10000, 10000, 187 }; 188 // const U32 cbTifDEMisc = sizeof(U16) * 10 + sizeof(U32) * 2 * 2; 189 190 const static TifDE tifDEs[] = 191 { 192 {0x100, 4, 1, (U32) -1}, // TIF_tagImageWidth 193 {0x101, 4, 1, (U32) -1}, // TIF_tagImageLength 194 {0x102, 3, (U32) -1, (U32) -1}, // TIF_tagBitsPerSample 195 {0x103, 3, 1, 1}, // TIF_tagCompression 196 {0x106, 3, 1, (U32) -1}, // TIF_tagPhotometricInterpretation 197 {0x111, 4, 1, (U32) -1}, // TIF_tagStripOffsets 198 {0x112, 3, 1, 1}, // TIF_tagOrientation 199 {0x115, 3, 1, (U32) -1}, // TIF_tagSamplesPerPixel 200 {0x116, 4, 1, (U32) -1}, // TIF_tagRowsPerStrip 201 {0x117, 4, 1, (U32) -1}, // TIF_tagStripByteCounts 202 {0x11a, 5, 1, (U32) -1}, // TIF_tagXResolution 203 {0x11b, 5, 1, (U32) -1}, // TIF_tagYResolution 204 {0x11c, 3, 1, 1}, // TIF_tagPlanarConfiguration 205 {0x128, 3, 1, 2}, // TIF_tagResolutionUnit 206 {0x153, 3, (U32) -1, (U32) -1}, // TIF_tagSampleFormat 207 // {0x131, 2, -1, -1}, // TIF_tagSoftware 208 // {0x140, 3, -1, -1}, // TIF_tagColorMap 209 }; 210 U16 cTifDEs = sizeof2(tifDEs); 211 TifDE tifDE = {0}; 212 PKPixelInfo PI; 213 size_t cbLine = 0; 214 215 size_t i = 0; 216 size_t j; 217 218 tifDEMisc.resXF = (U32)(pIE->fResX * 10000); 219 tifDEMisc.resYF = (U32)(pIE->fResY * 10000); 220 221 Call(pS->GetPos(pS, &offPos)); 222 FailIf(0 != offPos, WMP_errUnsupportedFormat); 223 224 //================ 225 // TifHeader 226 Call(pS->Write(pS, IIMM, 2)); offPos += 2; 227 Call(PutTifUShort(pS, offPos, 42)); offPos += 2; 228 Call(PutTifULong(pS, offPos, (U32)(offPos + 4))); offPos += 4; 229 230 //================ 231 // TifDEMisc 232 PI.pGUIDPixFmt = &pIE->guidPixFormat; 233 PixelFormatLookup(&PI, LOOKUP_FORWARD); 234 235 tifDEMisc.iPhotometricInterpretation = 236 //the N channel TIF by PS has PhotometricInterpretation of PK_PI_RGB 237 PI.uInterpretation == PK_PI_NCH || PI.uInterpretation == PK_PI_RGBE ? PK_PI_RGB : 238 (PI.uInterpretation == PK_PI_B0 && pIE->WMP.wmiSCP.bBlackWhite ? PK_PI_W0 : PI.uInterpretation); 239 tifDEMisc.spp = PI.uSamplePerPixel; 240 tifDEMisc.bps = PI.uBitsPerSample; 241 tifDEMisc.sf = PI.uSampleFormat; 242 243 if (tifDEMisc.iPhotometricInterpretation == PK_PI_CMYK) 244 cTifDEs++; 245 if (PI.grBit & PK_pixfmtHasAlpha) 246 cTifDEs++; 247 tifDEMisc.offBitsPerSample = (U32)offPos + sizeof(U16) + 12 * cTifDEs + sizeof(U32); 248 tifDEMisc.offSampleFormat = tifDEMisc.offBitsPerSample + (tifDEMisc.spp == 1 ? 0 : tifDEMisc.spp * 2); 249 tifDEMisc.offXResolution = tifDEMisc.offSampleFormat + (tifDEMisc.spp == 1 ? 0 : tifDEMisc.spp * 2); 250 tifDEMisc.offYResolution = tifDEMisc.offXResolution + 8; 251 252 //================ 253 // TifIFD 254 pIE->offPixel = tifDEMisc.offYResolution + 8; 255 Call(PutTifUShort(pS, offPos, cTifDEs)); offPos += 2; 256 257 //================ 258 tifDE = tifDEs[i++]; 259 assert(TIF_tagImageWidth == tifDE.uTag); 260 tifDE.uValueOrOffset = pIE->uWidth; 261 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 262 263 tifDE = tifDEs[i++]; 264 assert(TIF_tagImageLength == tifDE.uTag); 265 tifDE.uValueOrOffset = pIE->uHeight; 266 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 267 268 tifDE = tifDEs[i++]; 269 assert(TIF_tagBitsPerSample == tifDE.uTag); 270 tifDE.uCount = tifDEMisc.spp; 271 tifDE.uValueOrOffset = 1 == tifDE.uCount ? tifDEMisc.bps : tifDEMisc.offBitsPerSample; 272 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 273 274 tifDE = tifDEs[i++]; 275 assert(TIF_tagCompression == tifDE.uTag); 276 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 277 278 tifDE = tifDEs[i++]; 279 assert(TIF_tagPhotometricInterpretation == tifDE.uTag); 280 tifDE.uValueOrOffset = tifDEMisc.iPhotometricInterpretation; 281 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 282 283 tifDE = tifDEs[i++]; 284 assert(TIF_tagStripOffsets == tifDE.uTag); 285 tifDE.uValueOrOffset = (U32)pIE->offPixel; 286 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 287 288 tifDE = tifDEs[i++]; 289 assert(TIF_tagOrientation == tifDE.uTag); 290 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 291 292 tifDE = tifDEs[i++]; 293 assert(TIF_tagSamplesPerPixel == tifDE.uTag); 294 tifDE.uValueOrOffset = tifDEMisc.spp; 295 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 296 297 tifDE = tifDEs[i++]; 298 assert(TIF_tagRowsPerStrip == tifDE.uTag); 299 tifDE.uValueOrOffset = pIE->uHeight; 300 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 301 302 tifDE = tifDEs[i++]; 303 assert(TIF_tagStripByteCounts == tifDE.uTag); 304 cbLine = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pIE->uWidth + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pIE->uWidth)); 305 tifDE.uValueOrOffset = (U32)(cbLine * pIE->uHeight); 306 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 307 308 tifDE = tifDEs[i++]; 309 assert(TIF_tagXResolution == tifDE.uTag); 310 tifDE.uValueOrOffset = tifDEMisc.offXResolution; 311 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 312 313 tifDE = tifDEs[i++]; 314 assert(TIF_tagYResolution == tifDE.uTag); 315 tifDE.uValueOrOffset = tifDEMisc.offYResolution; 316 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 317 318 tifDE = tifDEs[i++]; 319 assert(TIF_tagPlanarConfiguration == tifDE.uTag); 320 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 321 322 tifDE = tifDEs[i++]; 323 assert(TIF_tagResolutionUnit == tifDE.uTag); 324 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 325 326 if (tifDEMisc.iPhotometricInterpretation == PK_PI_CMYK) 327 { 328 TifDE tifDE = {TIF_tagInkSet, 3, 1, 1}; 329 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 330 } 331 332 if (PI.grBit & PK_pixfmtHasAlpha) 333 { 334 TifDE tifDE = {TIF_tagExtraSamples, 3, 1, 1}; 335 if (!(PI.grBit & PK_pixfmtPreMul)) 336 tifDE.uValueOrOffset++; 337 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 338 } 339 340 tifDE = tifDEs[i++]; 341 assert(TIF_tagSampleFormat == tifDE.uTag); 342 tifDE.uCount = tifDEMisc.spp; 343 tifDE.uValueOrOffset = 1 == tifDE.uCount ? tifDEMisc.sf : tifDEMisc.offSampleFormat; 344 Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12; 345 346 //================ 347 Call(PutTifULong(pS, offPos, 0)); offPos += 4; 348 349 //================ 350 // TifDEMisc 351 if (tifDE.uCount > 1) 352 { 353 assert(tifDEMisc.offBitsPerSample == offPos); 354 if (PI.bdBitDepth == BD_565) 355 { 356 Call(PutTifUShort(pS, offPos, 5)); offPos += 2; 357 Call(PutTifUShort(pS, offPos, 6)); offPos += 2; 358 Call(PutTifUShort(pS, offPos, 5)); offPos += 2; 359 } 360 else 361 { 362 for (j = 0; j < tifDE.uCount; j++) 363 { 364 Call(PutTifUShort(pS, offPos, (U16)tifDEMisc.bps)); offPos += 2; 365 } 366 } 367 368 assert(tifDEMisc.offSampleFormat == offPos); 369 for (j = 0; j < tifDE.uCount; j++) 370 { 371 Call(PutTifUShort(pS, offPos, (U16)tifDEMisc.sf)); offPos += 2; 372 } 373 } 374 375 assert(tifDEMisc.offXResolution == offPos); 376 Call(PutTifULong(pS, offPos, tifDEMisc.resXF)); offPos += 4; 377 Call(PutTifULong(pS, offPos, tifDEMisc.resXD)); offPos += 4; 378 379 assert(tifDEMisc.offYResolution == offPos); 380 Call(PutTifULong(pS, offPos, tifDEMisc.resYF)); offPos += 4; 381 Call(PutTifULong(pS, offPos, tifDEMisc.resYD)); offPos += 4; 382 383 assert(pIE->offPixel == offPos); 384 385 pIE->fHeaderDone = !FALSE; 386 387 Cleanup: 388 return err; 389 } 390 391 //================================================================ 392 // PKImageEncode_TIF 393 //================================================================ 394 ERR PKImageEncode_WritePixels_TIF( 395 PKImageEncode* pIE, 396 U32 cLine, 397 U8* pbPixel, 398 U32 cbStride) 399 { 400 ERR err = WMP_errSuccess; 401 402 struct WMPStream* pS = pIE->pStream; 403 PKPixelInfo PI; 404 size_t cbLine = 0; 405 size_t offPos = 0; 406 size_t i = 0; 407 408 // header 409 if (!pIE->fHeaderDone) 410 { 411 Call(WriteTifHeader(pIE)); 412 } 413 414 // body 415 PI.pGUIDPixFmt = &pIE->guidPixFormat; 416 PixelFormatLookup(&PI, LOOKUP_FORWARD); 417 418 cbLine = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pIE->uWidth + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pIE->uWidth)); 419 420 FailIf(cbStride < cbLine, WMP_errInvalidParameter); 421 422 offPos = pIE->offPixel + cbLine * pIE->idxCurrentLine; 423 Call(pS->SetPos(pS, offPos)); 424 425 for (i = 0; i < cLine; ++i) 426 { 427 Call(pS->Write(pS, pbPixel + cbStride * i, cbLine)); 428 } 429 pIE->idxCurrentLine += cLine; 430 431 Cleanup: 432 return err; 433 } 434 435 ERR PKImageEncode_Create_TIF(PKImageEncode** ppIE) 436 { 437 ERR err = WMP_errSuccess; 438 439 PKImageEncode* pIE = NULL; 440 441 Call(PKImageEncode_Create(ppIE)); 442 443 pIE = *ppIE; 444 pIE->WritePixels = PKImageEncode_WritePixels_TIF; 445 446 Cleanup: 447 return err; 448 } 449 450 451 //================================================================ 452 // PKImageDecode_TIF helpers 453 //================================================================ 454 ERR GetTifUShort( 455 struct WMPStream* pWS, 456 size_t offPos, 457 Bool fLittleEndian, 458 U16* puValue) 459 { 460 ERR err = WMP_errSuccess; 461 U8 buf[2]; 462 463 Call(pWS->SetPos(pWS, offPos)); 464 Call(pWS->Read(pWS, buf, sizeof2(buf))); 465 466 if (fLittleEndian) 467 { 468 *puValue = buf[0] + ((U16)buf[1] << 8); 469 } 470 else 471 { 472 *puValue = ((U16)buf[0] << 8) + buf[1]; 473 } 474 475 Cleanup: 476 return err; 477 } 478 479 ERR GetTifULong( 480 struct WMPStream* pWS, 481 size_t offPos, 482 Bool fLittleEndian, 483 U32* puValue) 484 { 485 ERR err = WMP_errSuccess; 486 U8 buf[4]; 487 488 Call(pWS->SetPos(pWS, offPos)); 489 Call(pWS->Read(pWS, buf, sizeof2(buf))); 490 491 if (fLittleEndian) 492 { 493 *puValue = buf[0] + ((U32)buf[1] << 8) + ((U32)buf[2] << 16) + ((U32)buf[3] << 24); 494 } 495 else 496 { 497 *puValue = ((U32)buf[0] << 24) + ((U32)buf[1] << 16) + ((U32)buf[2] << 8) + buf[3]; 498 } 499 500 Cleanup: 501 return err; 502 } 503 504 ERR GetTifULongArray( 505 struct WMPStream* pWS, 506 size_t offPos, 507 size_t cElements, 508 Bool fLittleEndian, 509 U32* puValue) 510 { 511 ERR err = WMP_errSuccess; 512 513 if (1 == cElements) 514 { 515 puValue[0] = (U32)offPos; 516 } 517 else 518 { 519 size_t i = 0; 520 for (i = 0; i < cElements; ++i) 521 { 522 Call(GetTifULong(pWS, offPos, fLittleEndian, &puValue[i])); 523 offPos += sizeof(*puValue); 524 } 525 } 526 527 Cleanup: 528 return err; 529 } 530 531 ERR ParseTifDEValue( 532 PKTestDecode* pID, 533 U16 uTag, 534 U16 uType, 535 U32 uCount) 536 { 537 ERR err = WMP_errSuccess; 538 539 struct WMPStream* pWS = pID->pStream; 540 U16 bpc[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 541 U16 sf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; 542 U32 uPos = 0; 543 U16 usValue = 0; 544 U32 uValue0 = 0; 545 U32 uValue1 = 0; 546 size_t i, offPos = 0; 547 548 //================================ 549 Call(pWS->GetPos(pWS, &offPos)); 550 551 //================================ 552 switch (uType) 553 { 554 case TIF_typSHORT: 555 Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &usValue)); 556 uValue0 = usValue; 557 break; 558 559 case TIF_typLONG: 560 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0)); 561 break; 562 } 563 564 //================================ 565 switch (uTag) 566 { 567 case TIF_tagNewSubfileType: 568 FailIf(0 != uValue0, WMP_errUnsupportedFormat); 569 break; 570 571 case TIF_tagSubfileType: 572 case TIF_tagPredictor: 573 FailIf(1 != uValue0, WMP_errUnsupportedFormat); 574 break; 575 576 case TIF_tagImageWidth: 577 pID->uWidth = uValue0; 578 break; 579 580 case TIF_tagImageLength: 581 pID->uHeight = uValue0; 582 break; 583 584 case TIF_tagBitsPerSample: 585 if (1 == uCount) 586 { 587 pID->EXT.TIF.uBitsPerSample = uValue0; 588 } 589 else 590 { 591 Bool bpcAnd = 1; 592 593 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos)); 594 offPos = uPos; 595 596 Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &bpc[0])); 597 598 for (i = 1; i < uCount; i++) 599 { 600 Call(GetTifUShort(pWS, offPos + (i << 1) , pID->EXT.TIF.fLittleEndian, &bpc[i])); 601 bpcAnd = (bpcAnd && (bpc[0] == bpc[i])); 602 } 603 604 if (bpcAnd) 605 pID->EXT.TIF.uBitsPerSample = bpc[0]; 606 else 607 Call(WMP_errUnsupportedFormat); 608 } 609 break; 610 611 case TIF_tagExtraSamples: 612 FailIf(0 != uValue0 && 1 != uValue0 && 2 != uValue0, WMP_errUnsupportedFormat); 613 pID->EXT.TIF.uExtraSamples = uValue0; 614 break; 615 616 case TIF_tagSampleFormat: 617 if (1 == uCount) 618 { 619 pID->EXT.TIF.uSampleFormat = uValue0; 620 } 621 else 622 { 623 Bool sfAnd = 1; 624 625 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos)); 626 offPos = uPos; 627 628 Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &sf[0])); 629 630 for (i = 1; i < uCount; i++) 631 { 632 Call(GetTifUShort(pWS, offPos + (i << 1) , pID->EXT.TIF.fLittleEndian, &sf[i])); 633 sfAnd = (sfAnd && (sf[0] == sf[i])); 634 } 635 636 if (sfAnd) 637 pID->EXT.TIF.uSampleFormat = sf[0]; 638 else 639 Call(WMP_errUnsupportedFormat); 640 } 641 break; 642 643 case TIF_tagCompression: 644 FailIf(1 != uValue0, WMP_errUnsupportedFormat); 645 break; 646 647 case TIF_tagPhotometricInterpretation: 648 Test(PK_PI_W0 == uValue0 || PK_PI_B0 == uValue0 || PK_PI_RGB == uValue0 649 || PK_PI_RGBPalette == uValue0 || PK_PI_TransparencyMask == uValue0 650 || PK_PI_CMYK == uValue0 || PK_PI_YCbCr == uValue0 651 || PK_PI_CIELab == uValue0, WMP_errUnsupportedFormat); 652 653 pID->EXT.TIF.uInterpretation = uValue0; 654 break; 655 656 case TIF_tagStripOffsets: 657 Call(WMPAlloc((void **) &pID->EXT.TIF.uStripOffsets, sizeof(*pID->EXT.TIF.uStripOffsets) * uCount)); 658 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0)); 659 Call(GetTifULongArray(pWS, uValue0, uCount, pID->EXT.TIF.fLittleEndian, pID->EXT.TIF.uStripOffsets)); 660 break; 661 662 case TIF_tagOrientation: 663 case TIF_tagSamplesPerPixel: 664 pID->EXT.TIF.uSamplePerPixel = uValue0; 665 break; 666 667 case TIF_tagRowsPerStrip: 668 pID->EXT.TIF.uRowsPerStrip = uValue0; 669 break; 670 671 case TIF_tagStripByteCounts: 672 Call(WMPAlloc((void **) &pID->EXT.TIF.uStripByteCounts, sizeof(*pID->EXT.TIF.uStripByteCounts) * uCount)); 673 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0)); 674 Call(GetTifULongArray(pWS, uValue0, uCount, pID->EXT.TIF.fLittleEndian, pID->EXT.TIF.uStripByteCounts)); 675 break; 676 677 case TIF_tagXResolution: 678 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos)); 679 offPos = uPos; 680 681 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0));//numerator 682 Call(GetTifULong(pWS, offPos + 4, pID->EXT.TIF.fLittleEndian, &uValue1));//denominator 683 684 pID->EXT.TIF.fResX = (Float)uValue0/(Float)uValue1; 685 break; 686 687 case TIF_tagYResolution: 688 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos)); 689 offPos = uPos; 690 691 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0));//numerator 692 Call(GetTifULong(pWS, offPos + 4, pID->EXT.TIF.fLittleEndian, &uValue1));//denominator 693 pID->EXT.TIF.fResY = (Float)uValue0/(Float)uValue1; 694 break; 695 696 case TIF_tagResolutionUnit: 697 pID->EXT.TIF.uResolutionUnit = usValue; 698 break; 699 700 case TIF_tagPlanarConfiguration: 701 case TIF_tagSoftware: 702 case TIF_tagColorMap: 703 break; 704 705 default: 706 printf("Unrecognized TIFTag: %d(%#x), %d, %d" CRLF, (int)uTag, (int)uTag, (int)uType, (int)uCount); 707 break; 708 } 709 710 Cleanup: 711 return err; 712 } 713 714 ERR ParseTifDEArray( 715 PKTestDecode* pID, 716 size_t offPos) 717 { 718 ERR err = WMP_errSuccess; 719 720 struct WMPStream* pWS = pID->pStream; 721 U16 uTag = 0; 722 U16 uType = 0; 723 U32 uCount = 0; 724 725 Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uTag)); 726 offPos += 2; 727 728 Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uType)); 729 offPos += 2; 730 731 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uCount)); 732 offPos += 4; 733 734 Call(ParseTifDEValue(pID, uTag, uType, uCount)); 735 736 Cleanup: 737 return err; 738 } 739 740 ERR ParseTifHeader( 741 PKTestDecode* pID, 742 struct WMPStream* pWS) 743 { 744 ERR err = WMP_errSuccess; 745 PKPixelInfo PI; 746 747 size_t offPosBase = 0; 748 size_t offPos = 0; 749 750 U8 szSig[3] = {0, 0, '\0'}; 751 U16 uTiffId = 0; 752 U32 uOffNextIFD = 0; 753 U16 uCountDE = 0, i = 0; 754 755 //default 756 pID->EXT.TIF.uRowsPerStrip = (U32) -1; 757 pID->EXT.TIF.uInterpretation = (U32) -1; 758 pID->EXT.TIF.uSamplePerPixel = (U32) -1; 759 pID->EXT.TIF.uBitsPerSample = (U32) -1; 760 pID->EXT.TIF.uSampleFormat = 1; 761 pID->EXT.TIF.uResolutionUnit = 2; 762 pID->EXT.TIF.fResX = 96; 763 pID->EXT.TIF.fResY = 96; 764 765 //================================ 766 Call(pWS->GetPos(pWS, &offPosBase)); 767 FailIf(0 != offPosBase, WMP_errUnsupportedFormat); 768 769 //================================ 770 // Header 771 Call(pWS->Read(pWS, szSig, 2)); 772 offPos += 2; 773 if (szSig == (U8 *) strstr((char *) szSig, "II")) 774 { 775 pID->EXT.TIF.fLittleEndian = !FALSE; 776 } 777 else if (szSig == (U8 *) strstr((char *) szSig, "MM")) 778 { 779 pID->EXT.TIF.fLittleEndian = FALSE; 780 } 781 else 782 { 783 Call(WMP_errUnsupportedFormat); 784 } 785 786 Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uTiffId)); 787 offPos += 2; 788 FailIf(42 != uTiffId, WMP_errUnsupportedFormat); 789 790 Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uOffNextIFD)); 791 offPos += 4; 792 793 //================================ 794 // IFD 795 offPos = (size_t)uOffNextIFD; 796 Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uCountDE)); 797 offPos += 2; 798 799 for (i = 0; i < uCountDE; ++i) 800 { 801 Call(ParseTifDEArray(pID, offPos)); 802 offPos += 12; 803 } 804 805 if(pID->EXT.TIF.uRowsPerStrip == -1) 806 pID->EXT.TIF.uRowsPerStrip = pID->uHeight;//default 807 808 FailIf((-1 == pID->EXT.TIF.uInterpretation 809 || -1 == pID->EXT.TIF.uSamplePerPixel 810 || -1 == pID->EXT.TIF.uBitsPerSample), WMP_errUnsupportedFormat); 811 812 PI.uInterpretation = pID->EXT.TIF.uInterpretation; 813 PI.uSamplePerPixel = pID->EXT.TIF.uSamplePerPixel; 814 PI.uBitsPerSample = pID->EXT.TIF.uBitsPerSample; 815 PI.uSampleFormat = pID->EXT.TIF.uSampleFormat; 816 817 PI.grBit = pID->EXT.TIF.uExtraSamples == 1 || pID->EXT.TIF.uExtraSamples == 2 || 818 /* Workaround for some images without correct info about alpha channel */ 819 (pID->EXT.TIF.uExtraSamples == 0 && pID->EXT.TIF.uSamplePerPixel > 3) ? PK_pixfmtHasAlpha : 0x0; 820 PI.grBit |= pID->EXT.TIF.uExtraSamples == 1 ? PK_pixfmtPreMul : 0x0; 821 822 pID->fResX = (3 == pID->EXT.TIF.uResolutionUnit ? (Float)(pID->EXT.TIF.fResX * 2.54) : pID->EXT.TIF.fResX);//cm -> inch 823 pID->fResY = (3 == pID->EXT.TIF.uResolutionUnit ? (Float)(pID->EXT.TIF.fResY * 2.54) : pID->EXT.TIF.fResY);//cm -> inch 824 825 Call(PixelFormatLookup(&PI, LOOKUP_BACKWARD_TIF)); 826 827 pID->guidPixFormat = *(PI.pGUIDPixFmt); 828 829 Cleanup: 830 return err; 831 } 832 833 //================================================================ 834 // PKImageDecode_TIF 835 //================================================================ 836 ERR PKImageDecode_Initialize_TIF( 837 PKTestDecode* pID, 838 struct WMPStream* pWS) 839 { 840 ERR err = WMP_errSuccess; 841 842 Call(PKTestDecode_Initialize(pID, pWS)); 843 Call(ParseTifHeader(pID, pWS)); 844 845 Cleanup: 846 return err; 847 } 848 849 ERR GetScanLineOffset( 850 PKTestDecode* pID, 851 I32 iLine, 852 U32 cbLine, 853 U32 *offLine) 854 { 855 *offLine = pID->EXT.TIF.uRowsPerStrip ? 856 (pID->EXT.TIF.uStripOffsets[iLine / pID->EXT.TIF.uRowsPerStrip] + 857 cbLine * (iLine % pID->EXT.TIF.uRowsPerStrip)) : 858 0; 859 860 return WMP_errSuccess; 861 } 862 863 ERR PKImageDecode_Copy_TIF( 864 PKTestDecode* pID, 865 const PKRect* pRect, 866 U8* pb, 867 U32 cbStride) 868 { 869 ERR err = WMP_errSuccess; 870 871 struct WMPStream* pS = pID->pStream; 872 PKPixelInfo PI; 873 U32 cbLine = 0; 874 I32 i = 0; 875 876 PI.pGUIDPixFmt = &pID->guidPixFormat; 877 PixelFormatLookup(&PI, LOOKUP_FORWARD); 878 879 cbLine = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pRect->Width + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pRect->Width)); 880 881 assert(0 == pRect->X && pID->uWidth == (U32)pRect->Width); 882 assert(cbLine <= cbStride); 883 884 for (i = 0; i < pRect->Height; ++i) 885 { 886 U32 offPixels = 0; 887 Call(GetScanLineOffset(pID, pRect->Y + i, cbLine, &offPixels)); 888 889 Call(pS->SetPos(pS, offPixels)); 890 Call(pS->Read(pS, pb + cbStride * i, cbLine)); 891 892 if (PK_PI_W0 == pID->EXT.TIF.uInterpretation) 893 { 894 U32 j, begin = cbStride * (U32)i, end = begin + cbLine; 895 for (j = begin; j < end; ++j) 896 { 897 pb[j] = ~pb[j]; 898 } 899 } 900 } 901 902 Cleanup: 903 return err; 904 } 905 906 ERR PKImageDecode_Release_TIF(PKTestDecode** ppID) 907 { 908 ERR err = WMP_errSuccess; 909 910 PKTestDecode *pID = *ppID; 911 912 Call(WMPFree(&pID->EXT.TIF.uStripOffsets)); 913 Call(WMPFree(&pID->EXT.TIF.uStripByteCounts)); 914 915 Call(PKTestDecode_Release(ppID)); 916 917 Cleanup: 918 return err; 919 } 920 921 ERR PKImageDecode_Create_TIF(PKTestDecode** ppID) 922 { 923 ERR err = WMP_errSuccess; 924 PKTestDecode* pID = NULL; 925 926 Call(PKTestDecode_Create(ppID)); 927 928 pID = *ppID; 929 pID->Initialize = PKImageDecode_Initialize_TIF; 930 pID->Copy = PKImageDecode_Copy_TIF; 931 pID->Release = PKImageDecode_Release_TIF; 932 933 Cleanup: 934 return err; 935 } 936