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  }