github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/jxr/jxrlib/jxrencoderdecoder/JxrEncApp.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 <JXRTest.h> 29 #include <time.h> 30 31 32 //================================================================ 33 // Command line argument support 34 //================================================================ 35 typedef struct tagWMPENCAPPARGS 36 { 37 char* szInputFile; 38 char* szOutputFile; 39 40 PKPixelFormatGUID guidPixFormat; 41 // Bool bFlagRGB_BGR; 42 43 CWMIStrCodecParam wmiSCP; 44 float fltImageQuality; 45 Bool bOverlapSet; 46 Bool bColorFormatSet; 47 } WMPENCAPPARGS; 48 49 //---------------------------------------------------------------- 50 void WmpEncAppUsage(const char* szExe) 51 { 52 printf(CRLF); 53 printf("JPEG XR Encoder Utility" CRLF); 54 printf("Copyright 2013 Microsoft Corporation - All Rights Reserved" CRLF); 55 printf(CRLF); 56 printf("%s [options]..." CRLF, szExe); 57 printf(CRLF); 58 printf(" -i input.bmp/tif/hdr Input image file name" CRLF); 59 printf(" bmp: <=8bpc, BGR" CRLF); 60 printf(" tif: >=8bpc, RGB" CRLF); 61 printf(" hdr: 24bppRGBE only" CRLF); 62 printf(CRLF); 63 64 printf(" -o output.jxr Output JPEG XR file name" CRLF); 65 printf(CRLF); 66 67 printf(" -q quality [0.0 - 1.0) Default = 1.0, lossless" CRLF); 68 printf(" or quantization [1 - 255] Default = 1, lossless" CRLF); 69 printf(CRLF); 70 71 printf(" -c format Required to define uncompressed source pixel format" CRLF); 72 printf(" 0: 24bppBGR" CRLF); 73 printf(" 1: 1bppBlackWhite" CRLF); 74 printf(" 2: 8bppGray" CRLF); 75 printf(" 3: 16bppGray" CRLF); 76 printf(" 4: 16bppGrayFixedPoint" CRLF); 77 printf(" 5: 16bppGrayHalf" CRLF); 78 // printf(" 6: 32bppGray" CRLF); 79 printf(" 7: 32bppGrayFixedPoint" CRLF); 80 printf(" 8: 32bppGrayFloat" CRLF); 81 82 printf(" 9: 24bppRGB" CRLF); 83 printf(" 10: 48bppRGB" CRLF); 84 printf(" 11: 48bppRGBFixedPoint" CRLF); 85 printf(" 12: 48bppRGBHalf" CRLF); 86 // printf(" 13: 96bppRGB" CRLF); 87 printf(" 14: 96bppRGBFixedPoint" CRLF); 88 printf(" 15: 128bppRGBFloat" CRLF); 89 90 printf(" 16: 32bppRGBE" CRLF); 91 92 printf(" 17: 32bppCMYK" CRLF); 93 printf(" 18: 64bppCMYK" CRLF); 94 95 /* 96 printf(" 19 - YUV 420" CRLF); 97 printf(" 20 - YUV 422" CRLF); 98 printf(" 21 - YUV 444" CRLF); 99 */ 100 printf(" 22: 32bppBGRA" CRLF); 101 printf(" 23: 64bppRGBA" CRLF); 102 printf(" 24: 64bppRGBAFixedPoint" CRLF); 103 printf(" 25: 64bppRGBAHalf" CRLF); 104 // printf(" 26 - 128bpp RGBA" CRLF); 105 printf(" 27: 128bppRGBAFixedPoint" CRLF); 106 printf(" 28: 128bppRGBAFloat" CRLF); 107 108 printf(" 29: 16bppBGR555" CRLF); 109 printf(" 30: 16bppBGR565" CRLF); 110 printf(" 31: 32bppBGR101010" CRLF); 111 //printf(" 101..116 - 1..16 channel 8bpp" CRLF); 112 printf(" 32: 40bppCMYKA" CRLF); 113 printf(" 33: 80bppCMYKA" CRLF); 114 115 printf(" 34: 32bppBGR" CRLF); 116 /* 117 printf(" 35: 32bppPBGRA" CRLF); 118 printf(" 36: 64bppPRGBA" CRLF); 119 printf(" 37: 128bppPRGBA Float" CRLF); 120 */ 121 printf(CRLF); 122 123 printf(" -d chroma sub-sampling 0: Y-only" CRLF); 124 printf(" 1: YCoCg 4:2:0" CRLF); 125 printf(" 2: YCoCg 4:2:2" CRLF); 126 printf(" 3: YCoCg 4:4:4 (default)" CRLF); 127 printf(" (if not set is 4:4:4 for quality >= 0.5 or 4:2:0 for quality < 0.5)" CRLF); 128 printf(CRLF); 129 130 printf(" -l overlapping 0: No overlapping" CRLF); 131 printf(" 1: One level overlapping (default)" CRLF); 132 printf(" 2: Two level overlapping" CRLF); 133 printf(" (if not set is One for quality > 0.4 or Two for quality <= 0.4)" CRLF); 134 printf(CRLF); 135 136 printf(" -f Turn off frequency order bit stream (to spatial)" CRLF); 137 printf(CRLF); 138 printf(" -p Turn off progressive mode (to sequential)" CRLF); 139 printf(CRLF); 140 printf(" -t Display timing information" CRLF); 141 printf(CRLF); 142 printf(" -v Display verbose encoder information" CRLF); 143 printf(CRLF); 144 printf(" -V tile_wd0 [tile_wd1 ... ] Macro block columns per tile " CRLF); 145 printf(CRLF); 146 printf(" -H tile_ht0 [tile_ht1 ... ] Macro block rows per tile" CRLF); 147 printf(CRLF); 148 printf(" -U num_v_tiles num_h_tiles Vertical & horizontal tile count for uniform tiling" CRLF); 149 printf(CRLF); 150 151 printf(" -b Black/White Applies to 1bpp black/white images" CRLF); 152 printf(" 0: 0 = black (default)" CRLF); 153 printf(" 1: 0 = white" CRLF); 154 printf(CRLF); 155 156 printf(" -a alpha channel format Required for any pixel format with an alpha channel" CRLF); 157 printf(" 2: Planar alpha (default)" CRLF); 158 printf(" 3: Interleaved alpha" CRLF); 159 printf(" Other: Reserved, do not use" CRLF); 160 printf(CRLF); 161 162 printf(" -Q quantization for alpha [1 - 255] Default = 1, lossless" CRLF); 163 printf(CRLF); 164 165 printf(" -F trimmed flexbits [0 - 15] 0: no trimming (default)" CRLF); 166 printf(" 15: trim all" CRLF); 167 printf(CRLF); 168 printf(" -s skip subbands 0: All subbands included (default)" CRLF); 169 printf(" 1: Skip flexbits" CRLF); 170 printf(" 2: Skip highpass" CRLF); 171 printf(" 3: Skip highpass & lowpass (DC only)" CRLF); 172 printf(CRLF); 173 printf("Eg: %s -i input.bmp -o output.jxr -q 10" CRLF, szExe); 174 } 175 176 void WmpEncAppShowArgs(WMPENCAPPARGS* args) 177 { 178 const char *szCF[] = {"Y_ONLY", "YUV_420", "YUV_422", "YUV_444", "CMYK"}; 179 180 GUID guidPF = args->guidPixFormat; 181 182 printf("================================" CRLF); 183 printf("Input file: %s" CRLF, args->szInputFile); 184 printf("Output file: %s" CRLF, args->szOutputFile); 185 printf("Color format: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X" CRLF, 186 guidPF.Data1, guidPF.Data2, guidPF.Data3, guidPF.Data4[0], guidPF.Data4[1], guidPF.Data4[2], 187 guidPF.Data4[3], guidPF.Data4[4], guidPF.Data4[5], guidPF.Data4[6], guidPF.Data4[7]); 188 printf("Internal cf: %s" CRLF, szCF[args->wmiSCP.cfColorFormat]); 189 printf("Overlap: %s" CRLF, 0 < args->wmiSCP.olOverlap ? "yes" : "no"); 190 printf("DCOverlap: %s" CRLF, 1 < args->wmiSCP.olOverlap ? "yes" : "no"); 191 printf("Alpha: %s" CRLF, 1 < args->wmiSCP.uAlphaMode ? "yes" : "no"); 192 printf("================================" CRLF); 193 } 194 195 //---------------------------------------------------------------- 196 void WmpEncAppInitDefaultArgs(WMPENCAPPARGS* args) 197 { 198 memset(args, 0, sizeof(*args)); 199 200 args->guidPixFormat = GUID_PKPixelFormatDontCare; 201 202 args->wmiSCP.bVerbose = FALSE; 203 args->wmiSCP.cfColorFormat = YUV_444; 204 // args->bFlagRGB_BGR = FALSE; //default BGR 205 args->wmiSCP.bdBitDepth = BD_LONG; 206 args->wmiSCP.bfBitstreamFormat = FREQUENCY; 207 args->wmiSCP.bProgressiveMode = TRUE; 208 args->wmiSCP.olOverlap = OL_ONE; 209 args->wmiSCP.cNumOfSliceMinus1H = args->wmiSCP.cNumOfSliceMinus1V = 0; 210 args->wmiSCP.sbSubband = SB_ALL; 211 args->wmiSCP.uAlphaMode = 0; 212 args->wmiSCP.uiDefaultQPIndex = 1; 213 args->wmiSCP.uiDefaultQPIndexAlpha = 1; 214 215 args->fltImageQuality = 1.f; 216 args->bOverlapSet = 0; 217 args->bColorFormatSet = 0; 218 } 219 220 ERR WmpEncAppValidateArgs(WMPENCAPPARGS* args) 221 { 222 ERR err = WMP_errSuccess; 223 224 Test(NULL != args->szInputFile, WMP_errInvalidParameter); 225 Test(NULL != args->szOutputFile, WMP_errInvalidParameter); 226 227 Cleanup: 228 return err; 229 } 230 231 ERR WmpEncAppParseArgs(int argc, char* argv[], WMPENCAPPARGS* args) 232 { 233 ERR err = WMP_errSuccess; 234 235 static const PKPixelFormatGUID* pixelFormat[] = 236 { 237 &GUID_PKPixelFormat24bppBGR, 238 239 &GUID_PKPixelFormatBlackWhite, 240 241 &GUID_PKPixelFormat8bppGray, 242 &GUID_PKPixelFormat16bppGray, 243 &GUID_PKPixelFormat16bppGrayFixedPoint, 244 &GUID_PKPixelFormat16bppGrayHalf, 245 &GUID_PKPixelFormatDontCare, // &GUID_PKPixelFormat32bppGray, 246 &GUID_PKPixelFormat32bppGrayFixedPoint, 247 &GUID_PKPixelFormat32bppGrayFloat, 248 249 &GUID_PKPixelFormat24bppRGB, 250 &GUID_PKPixelFormat48bppRGB, 251 &GUID_PKPixelFormat48bppRGBFixedPoint, 252 &GUID_PKPixelFormat48bppRGBHalf, 253 &GUID_PKPixelFormatDontCare, // &GUID_PKPixelFormat96bppRGB, 254 &GUID_PKPixelFormat96bppRGBFixedPoint, 255 &GUID_PKPixelFormat128bppRGBFloat, 256 257 &GUID_PKPixelFormat32bppRGBE, 258 &GUID_PKPixelFormat32bppCMYK, 259 &GUID_PKPixelFormat64bppCMYK, 260 261 &GUID_PKPixelFormat12bppYUV420, 262 &GUID_PKPixelFormat16bppYUV422, 263 &GUID_PKPixelFormat24bppYUV444, 264 265 //&GUID_PKPixelFormat32bppRGBA, 266 &GUID_PKPixelFormat32bppBGRA, 267 &GUID_PKPixelFormat64bppRGBA, 268 &GUID_PKPixelFormat64bppRGBAFixedPoint, 269 &GUID_PKPixelFormat64bppRGBAHalf, 270 &GUID_PKPixelFormatDontCare, // &GUID_PKPixelFormat128bppRGBA, 271 &GUID_PKPixelFormat128bppRGBAFixedPoint, 272 &GUID_PKPixelFormat128bppRGBAFloat, 273 274 //&GUID_PKPixelFormat32bppPBGRA 275 &GUID_PKPixelFormat16bppRGB555, 276 &GUID_PKPixelFormat16bppRGB565, 277 &GUID_PKPixelFormat32bppRGB101010, 278 &GUID_PKPixelFormat40bppCMYKAlpha, 279 &GUID_PKPixelFormat80bppCMYKAlpha, 280 &GUID_PKPixelFormat32bppBGR, 281 &GUID_PKPixelFormat32bppPBGRA, 282 &GUID_PKPixelFormat64bppPRGBA, 283 &GUID_PKPixelFormat128bppPRGBAFloat, 284 }; 285 286 size_t InvalidPF[9] = {6, 13, 19, 20, 21, 26, 35, 36, 37}; 287 size_t AlphaPF[8] = {22, 23, 24, 25, 27, 28, 32, 33}; 288 289 int i = 1, j = 0, k; 290 char c; 291 int idxPF = -1; 292 293 WmpEncAppInitDefaultArgs(args); 294 295 while (i < argc && argv[i][0] == '-') 296 { 297 switch ((c = argv[i][1])) { 298 /* the no-argument switches */ 299 case 't': 300 // NOOP - now we always print timing info 301 break; 302 303 case 'v': 304 args->wmiSCP.bVerbose = !FALSE; 305 break; 306 307 /* simple flag argument */ 308 case 'f': 309 args->wmiSCP.bfBitstreamFormat = SPATIAL; 310 break; 311 312 case 'p': 313 args->wmiSCP.bProgressiveMode = FALSE; 314 break; 315 316 case 'u': 317 args->wmiSCP.bUnscaledArith = TRUE; 318 break; 319 320 default: 321 i ++; 322 if (i == argc || argv[i][0] == '-') // need more info 323 Call(WMP_errInvalidArgument); 324 325 switch (c) 326 { 327 case 'i': 328 args->szInputFile = argv[i]; 329 break; 330 331 case 'o': 332 args->szOutputFile = argv[i]; 333 break; 334 335 case 'q': 336 { 337 args->fltImageQuality = (float) atof(argv[i]); 338 if (args->fltImageQuality < 0.f || args->fltImageQuality > 255.f) 339 Call(WMP_errInvalidArgument); 340 } 341 break; 342 343 case 'Q': 344 args->wmiSCP.uiDefaultQPIndexAlpha = (U8)(atoi(argv[i])); 345 break; 346 347 case 's': 348 args->wmiSCP.sbSubband = (SUBBAND)(atoi(argv[i])); 349 break; 350 351 case 'c': 352 idxPF = (size_t)atol(argv[i]); 353 for (k = 0; k < 9; k++) 354 { 355 if (InvalidPF[k] == (size_t) idxPF) 356 { 357 printf("*** Unsupported format in JPEG XR ***\n"); 358 Call(WMP_errInvalidArgument); 359 } 360 } 361 break; 362 363 case 'a': 364 args->wmiSCP.uAlphaMode = (U8)atoi(argv[i]); 365 break; 366 367 /* case 'R': 368 args->bFlagRGB_BGR = (Bool)atoi(argv[i]); 369 break; 370 */ 371 case 'l': 372 args->wmiSCP.olOverlap = (OVERLAP)atoi(argv[i]); 373 args->bOverlapSet = 1; 374 break; 375 376 case 'd': 377 args->wmiSCP.cfColorFormat = (COLORFORMAT)atoi(argv[i]); 378 args->bColorFormatSet = 1; 379 break; 380 381 case 'H': // horizontal tiling 382 for(j = 0;;i ++, j ++){ 383 args->wmiSCP.uiTileY[j] = atoi(argv[i]); 384 if(i + 1 == argc || argv[i + 1][0] == '-' || j >= MAX_TILES-1) 385 break; 386 } 387 args->wmiSCP.cNumOfSliceMinus1H = (U8)j; 388 break; 389 390 case 'V': // vertical tiling 391 for(j = 0;;i ++, j ++){ 392 args->wmiSCP.uiTileX[j] = atoi(argv[i]); 393 if(i + 1 == argc || argv[i + 1][0] == '-' || j >= MAX_TILES-1) 394 break; 395 } 396 args->wmiSCP.cNumOfSliceMinus1V = (U8)j; 397 break; 398 399 case 'U': // uniform tiling 400 if(i + 1 < argc && argv[i + 1][0] != '-'){ 401 if(atoi(argv[i]) > 0 && atoi(argv[i + 1]) > 0){ 402 args->wmiSCP.cNumOfSliceMinus1H = atoi(argv[i]) - 1; 403 args->wmiSCP.cNumOfSliceMinus1V = atoi(argv[i + 1]) - 1; 404 } 405 i ++; 406 } 407 break; 408 409 case 'm': 410 args->wmiSCP.nLenMantissaOrShift = (U8)atoi(argv[i]); 411 break; 412 413 case 'C': 414 args->wmiSCP.nExpBias = (I8) atoi(argv[i]) + 128; // rollover arithmetic 415 break; 416 417 case 'b': 418 args->wmiSCP.bBlackWhite = (Bool)atoi(argv[i]); 419 break; 420 421 case 'F': 422 args->wmiSCP.uiTrimFlexBits = (U8)atoi(argv[i]); 423 if (args->wmiSCP.uiTrimFlexBits > 15) 424 args->wmiSCP.uiTrimFlexBits = 15; 425 break; 426 427 default: 428 Call(WMP_errInvalidArgument); 429 } 430 } 431 432 i ++; 433 } 434 435 FailIf((int) sizeof2(pixelFormat) <= idxPF, WMP_errUnsupportedFormat); 436 if (idxPF >= 0) 437 args->guidPixFormat = *pixelFormat[idxPF]; 438 439 if ((idxPF >= 1) && (idxPF <= 8)) 440 args->wmiSCP.cfColorFormat = Y_ONLY; 441 else if ((idxPF == 17) || (idxPF == 18) || (idxPF == 32) || (idxPF == 33)) 442 args->wmiSCP.cfColorFormat = CMYK; 443 444 for (k = 0; k < 8; k++) 445 { 446 if (AlphaPF[k] == (size_t) idxPF) 447 { 448 if(0 == args->wmiSCP.uAlphaMode)//with Alpha and no default, set default as Planar 449 { 450 args->wmiSCP.uAlphaMode = 2; 451 } 452 break; 453 } 454 } 455 456 //================================ 457 Call(WmpEncAppValidateArgs(args)); 458 459 Cleanup: 460 return err; 461 } 462 463 464 // Y, U, V, YHP, UHP, VHP 465 int DPK_QPS_420[12][6] = { // for 8 bit only 466 { 66, 65, 70, 72, 72, 77 }, 467 { 59, 58, 63, 64, 63, 68 }, 468 { 52, 51, 57, 56, 56, 61 }, 469 { 48, 48, 54, 51, 50, 55 }, 470 { 43, 44, 48, 46, 46, 49 }, 471 { 37, 37, 42, 38, 38, 43 }, 472 { 26, 28, 31, 27, 28, 31 }, 473 { 16, 17, 22, 16, 17, 21 }, 474 { 10, 11, 13, 10, 10, 13 }, 475 { 5, 5, 6, 5, 5, 6 }, 476 { 2, 2, 3, 2, 2, 2 } 477 }; 478 479 int DPK_QPS_8[12][6] = { 480 { 67, 79, 86, 72, 90, 98 }, 481 { 59, 74, 80, 64, 83, 89 }, 482 { 53, 68, 75, 57, 76, 83 }, 483 { 49, 64, 71, 53, 70, 77 }, 484 { 45, 60, 67, 48, 67, 74 }, 485 { 40, 56, 62, 42, 59, 66 }, 486 { 33, 49, 55, 35, 51, 58 }, 487 { 27, 44, 49, 28, 45, 50 }, 488 { 20, 36, 42, 20, 38, 44 }, 489 { 13, 27, 34, 13, 28, 34 }, 490 { 7, 17, 21, 8, 17, 21 }, // Photoshop 100% 491 { 2, 5, 6, 2, 5, 6 } 492 }; 493 494 int DPK_QPS_16[11][6] = { 495 { 197, 203, 210, 202, 207, 213 }, 496 { 174, 188, 193, 180, 189, 196 }, 497 { 152, 167, 173, 156, 169, 174 }, 498 { 135, 152, 157, 137, 153, 158 }, 499 { 119, 137, 141, 119, 138, 142 }, 500 { 102, 120, 125, 100, 120, 124 }, 501 { 82, 98, 104, 79, 98, 103 }, 502 { 60, 76, 81, 58, 76, 81 }, 503 { 39, 52, 58, 36, 52, 58 }, 504 { 16, 27, 33, 14, 27, 33 }, 505 { 5, 8, 9, 4, 7, 8 } 506 }; 507 508 int DPK_QPS_16f[11][6] = { 509 { 148, 177, 171, 165, 187, 191 }, 510 { 133, 155, 153, 147, 172, 181 }, 511 { 114, 133, 138, 130, 157, 167 }, 512 { 97, 118, 120, 109, 137, 144 }, 513 { 76, 98, 103, 85, 115, 121 }, 514 { 63, 86, 91, 62, 96, 99 }, 515 { 46, 68, 71, 43, 73, 75 }, 516 { 29, 48, 52, 27, 48, 51 }, 517 { 16, 30, 35, 14, 29, 34 }, 518 { 8, 14, 17, 7, 13, 17 }, 519 { 3, 5, 7, 3, 5, 6 } 520 }; 521 522 int DPK_QPS_32f[11][6] = { 523 { 194, 206, 209, 204, 211, 217 }, 524 { 175, 187, 196, 186, 193, 205 }, 525 { 157, 170, 177, 167, 180, 190 }, 526 { 133, 152, 156, 144, 163, 168 }, 527 { 116, 138, 142, 117, 143, 148 }, 528 { 98, 120, 123, 96, 123, 126 }, 529 { 80, 99, 102, 78, 99, 102 }, 530 { 65, 79, 84, 63, 79, 84 }, 531 { 48, 61, 67, 45, 60, 66 }, 532 { 27, 41, 46, 24, 40, 45 }, 533 { 3, 22, 24, 2, 21, 22 } 534 }; 535 536 //================================================================ 537 // main function 538 //================================================================ 539 int 540 #ifndef __ANSI__ 541 __cdecl 542 #endif // __ANSI__ 543 main(int argc, char* argv[]) 544 { 545 ERR err = WMP_errSuccess; 546 547 PKFactory* pFactory = NULL; 548 struct WMPStream* pEncodeStream = NULL; 549 PKCodecFactory* pCodecFactory = NULL; 550 PKCodecFactory* pTestFactory = NULL; 551 PKImageEncode* pEncoder = NULL; 552 553 // clock_t start = 0, finish = 0; 554 WMPENCAPPARGS args; 555 char* pExt = NULL; 556 557 //================================ 558 // parse command line parameters 559 if (1 == argc) 560 { 561 WmpEncAppUsage(argv[0]); 562 return 0; 563 } 564 565 Call(WmpEncAppParseArgs(argc, argv, &args)); 566 if (args.wmiSCP.bVerbose) 567 { 568 WmpEncAppShowArgs(&args); 569 } 570 571 //================================ 572 pExt = strrchr(args.szInputFile, '.'); 573 FailIf(NULL == pExt, WMP_errUnsupportedFormat); 574 575 //================================ 576 Call(PKCreateFactory(&pFactory, PK_SDK_VERSION)); 577 Call(pFactory->CreateStreamFromFilename(&pEncodeStream, args.szOutputFile, "wb")); 578 579 //================================ 580 Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION)); 581 Call(pCodecFactory->CreateCodec(&IID_PKImageWmpEncode, &pEncoder)); 582 583 //---------------------------------------------------------------- 584 Call(PKCreateTestFactory(&pTestFactory, WMP_SDK_VERSION)); 585 586 // 587 // go through each image 588 // 589 //for (i = 0; ; ++i) 590 { 591 PKImageDecode* pDecoder = NULL; 592 PKFormatConverter* pConverter = NULL; 593 PKPixelInfo PI; 594 595 Float rX = 0.0, rY = 0.0; 596 PKRect rect = {0, 0, 0, 0}; 597 598 //================================ 599 Call(pTestFactory->CreateDecoderFromFile(args.szInputFile, &pDecoder)); 600 if (IsEqualGUID(&args.guidPixFormat, &GUID_PKPixelFormatDontCare)) 601 Call(pDecoder->GetPixelFormat(pDecoder, &args.guidPixFormat)); 602 603 PI.pGUIDPixFmt = &args.guidPixFormat; 604 Call(PixelFormatLookup(&PI, LOOKUP_FORWARD)); 605 if ((PI.grBit & PK_pixfmtHasAlpha) && args.wmiSCP.uAlphaMode == 0) 606 args.wmiSCP.uAlphaMode = 2; // with Alpha and no default, set default as Planar 607 608 FailIf(PI.uSamplePerPixel > 1 && PI.uBitsPerSample > 8 && args.wmiSCP.cfColorFormat != YUV_444, 609 WMP_errInvalidArgument); 610 611 //================================ 612 Call(pCodecFactory->CreateFormatConverter(&pConverter)); 613 Call(pConverter->Initialize(pConverter, pDecoder, pExt, args.guidPixFormat)); 614 615 //================================ 616 Call(pDecoder->GetSize(pDecoder, &rect.Width, &rect.Height)); 617 618 if (args.wmiSCP.cNumOfSliceMinus1H == 0 && args.wmiSCP.uiTileY[0] > 0) 619 { 620 // # of horizontal slices, rounded down by half tile size. 621 U32 uTileY = args.wmiSCP.uiTileY[0] * MB_HEIGHT_PIXEL; 622 args.wmiSCP.cNumOfSliceMinus1H = (U32) rect.Height < (uTileY >> 1) ? 0 : 623 (rect.Height + (uTileY >> 1)) / uTileY - 1; 624 } 625 if (args.wmiSCP.cNumOfSliceMinus1V == 0 && args.wmiSCP.uiTileX[0] > 0) 626 { 627 // # of vertical slices, rounded down by half tile size. 628 U32 uTileX = args.wmiSCP.uiTileX[0] * MB_HEIGHT_PIXEL; 629 args.wmiSCP.cNumOfSliceMinus1V = (U32) rect.Width < (uTileX >> 1) ? 0 : 630 (rect.Width + (uTileX >> 1)) / uTileX - 1; 631 } 632 633 Call(pEncoder->Initialize(pEncoder, pEncodeStream, &args.wmiSCP, sizeof(args.wmiSCP))); 634 635 //ImageQuality Q (BD==1) Q (BD==8) Q (BD==16) Q (BD==32F) Subsample Overlap 636 //[0.0, 0.4] 8-IQ*5 (see table) (see table) (see table) 4:4:4 2 637 //(0.4, 0.8) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1 638 //[0.8, 1.0) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1 639 //[1.0, 1.0] 1 1 1 1 4:4:4 0 640 641 if (args.fltImageQuality < 1.0F) 642 { 643 if (!args.bOverlapSet) 644 { 645 if (args.fltImageQuality > 0.4F) 646 pEncoder->WMP.wmiSCP.olOverlap = OL_ONE; 647 else 648 pEncoder->WMP.wmiSCP.olOverlap = OL_TWO; 649 } 650 651 if (!args.bColorFormatSet) 652 { 653 if (args.fltImageQuality >= 0.5F || PI.uBitsPerSample > 8) 654 pEncoder->WMP.wmiSCP.cfColorFormat = YUV_444; 655 else 656 pEncoder->WMP.wmiSCP.cfColorFormat = YUV_420; 657 } 658 659 if (PI.bdBitDepth == BD_1) 660 { 661 pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8)(8 - 5.0F * 662 args.fltImageQuality + 0.5F); 663 } 664 else 665 { 666 // remap [0.8, 0.866, 0.933, 1.0] to [0.8, 0.9, 1.0, 1.1] 667 // to use 8-bit DPK QP table (0.933 == Photoshop JPEG 100) 668 int qi; 669 float qf; 670 int* pQPs; 671 if (args.fltImageQuality > 0.8f && PI.bdBitDepth == BD_8 && 672 pEncoder->WMP.wmiSCP.cfColorFormat != YUV_420 && 673 pEncoder->WMP.wmiSCP.cfColorFormat != YUV_422) 674 args.fltImageQuality = 0.8f + (args.fltImageQuality - 0.8f) * 1.5f; 675 676 qi = (int) (10.f * args.fltImageQuality); 677 qf = 10.f * args.fltImageQuality - (float) qi; 678 679 pQPs = 680 (pEncoder->WMP.wmiSCP.cfColorFormat == YUV_420 || 681 pEncoder->WMP.wmiSCP.cfColorFormat == YUV_422) ? 682 DPK_QPS_420[qi] : 683 (PI.bdBitDepth == BD_8 ? DPK_QPS_8[qi] : 684 (PI.bdBitDepth == BD_16 ? DPK_QPS_16[qi] : 685 (PI.bdBitDepth == BD_16F ? DPK_QPS_16f[qi] : 686 DPK_QPS_32f[qi]))); 687 688 pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8) (0.5f + 689 (float) pQPs[0] * (1.f - qf) + (float) (pQPs + 6)[0] * qf); 690 pEncoder->WMP.wmiSCP.uiDefaultQPIndexU = (U8) (0.5f + 691 (float) pQPs[1] * (1.f - qf) + (float) (pQPs + 6)[1] * qf); 692 pEncoder->WMP.wmiSCP.uiDefaultQPIndexV = (U8) (0.5f + 693 (float) pQPs[2] * (1.f - qf) + (float) (pQPs + 6)[2] * qf); 694 pEncoder->WMP.wmiSCP.uiDefaultQPIndexYHP = (U8) (0.5f + 695 (float) pQPs[3] * (1.f - qf) + (float) (pQPs + 6)[3] * qf); 696 pEncoder->WMP.wmiSCP.uiDefaultQPIndexUHP = (U8) (0.5f + 697 (float) pQPs[4] * (1.f - qf) + (float) (pQPs + 6)[4] * qf); 698 pEncoder->WMP.wmiSCP.uiDefaultQPIndexVHP = (U8) (0.5f + 699 (float) pQPs[5] * (1.f - qf) + (float) (pQPs + 6)[5] * qf); 700 } 701 } 702 else 703 { 704 pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8) args.fltImageQuality; 705 } 706 707 if(pEncoder->WMP.wmiSCP.uAlphaMode == 2) 708 pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex = args.wmiSCP.uiDefaultQPIndexAlpha; 709 710 Call(pEncoder->SetPixelFormat(pEncoder, args.guidPixFormat)); 711 712 Call(pEncoder->SetSize(pEncoder, rect.Width, rect.Height)); 713 714 Call(pDecoder->GetResolution(pDecoder, &rX, &rY)); 715 Call(pEncoder->SetResolution(pEncoder, rX, rY)); 716 717 //================================ 718 // re-encode the input source to the output 719 // 720 pEncoder->WriteSource = PKImageEncode_WriteSource; 721 Call(pEncoder->WriteSource(pEncoder, pConverter, &rect)); 722 723 pConverter->Release(&pConverter); 724 pDecoder->Release(&pDecoder); 725 726 //if (i + 1 == 5) 727 //{ 728 // break; 729 //} 730 731 // multi-frame support NYI 732 //Call(pEncoder->CreateNewFrame(pEncoder, &wmiSCP, sizeof(wmiSCP))); 733 } 734 735 // Call(pEncoder->Terminate(pEncoder)); 736 pEncoder->Release(&pEncoder); 737 738 Cleanup: 739 if (WMP_errSuccess != err) 740 { 741 WmpEncAppUsage(argv[0]); 742 } 743 744 return (int)err; 745 }