mirror of
https://github.com/ValveSoftware/Proton.git
synced 2024-12-29 16:15:52 +03:00
746 lines
28 KiB
C
746 lines
28 KiB
C
//*@@@+++@@@@******************************************************************
|
|
//
|
|
// Copyright © Microsoft Corp.
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// • Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
// • Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
//*@@@---@@@@******************************************************************
|
|
#include <JXRTest.h>
|
|
#include <time.h>
|
|
|
|
|
|
//================================================================
|
|
// Command line argument support
|
|
//================================================================
|
|
typedef struct tagWMPENCAPPARGS
|
|
{
|
|
char* szInputFile;
|
|
char* szOutputFile;
|
|
|
|
PKPixelFormatGUID guidPixFormat;
|
|
// Bool bFlagRGB_BGR;
|
|
|
|
CWMIStrCodecParam wmiSCP;
|
|
float fltImageQuality;
|
|
Bool bOverlapSet;
|
|
Bool bColorFormatSet;
|
|
} WMPENCAPPARGS;
|
|
|
|
//----------------------------------------------------------------
|
|
void WmpEncAppUsage(const char* szExe)
|
|
{
|
|
printf(CRLF);
|
|
printf("JPEG XR Encoder Utility" CRLF);
|
|
printf("Copyright 2013 Microsoft Corporation - All Rights Reserved" CRLF);
|
|
printf(CRLF);
|
|
printf("%s [options]..." CRLF, szExe);
|
|
printf(CRLF);
|
|
printf(" -i input.bmp/tif/hdr Input image file name" CRLF);
|
|
printf(" bmp: <=8bpc, BGR" CRLF);
|
|
printf(" tif: >=8bpc, RGB" CRLF);
|
|
printf(" hdr: 24bppRGBE only" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -o output.jxr Output JPEG XR file name" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -q quality [0.0 - 1.0) Default = 1.0, lossless" CRLF);
|
|
printf(" or quantization [1 - 255] Default = 1, lossless" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -c format Required to define uncompressed source pixel format" CRLF);
|
|
printf(" 0: 24bppBGR" CRLF);
|
|
printf(" 1: 1bppBlackWhite" CRLF);
|
|
printf(" 2: 8bppGray" CRLF);
|
|
printf(" 3: 16bppGray" CRLF);
|
|
printf(" 4: 16bppGrayFixedPoint" CRLF);
|
|
printf(" 5: 16bppGrayHalf" CRLF);
|
|
// printf(" 6: 32bppGray" CRLF);
|
|
printf(" 7: 32bppGrayFixedPoint" CRLF);
|
|
printf(" 8: 32bppGrayFloat" CRLF);
|
|
|
|
printf(" 9: 24bppRGB" CRLF);
|
|
printf(" 10: 48bppRGB" CRLF);
|
|
printf(" 11: 48bppRGBFixedPoint" CRLF);
|
|
printf(" 12: 48bppRGBHalf" CRLF);
|
|
// printf(" 13: 96bppRGB" CRLF);
|
|
printf(" 14: 96bppRGBFixedPoint" CRLF);
|
|
printf(" 15: 128bppRGBFloat" CRLF);
|
|
|
|
printf(" 16: 32bppRGBE" CRLF);
|
|
|
|
printf(" 17: 32bppCMYK" CRLF);
|
|
printf(" 18: 64bppCMYK" CRLF);
|
|
|
|
/*
|
|
printf(" 19 - YUV 420" CRLF);
|
|
printf(" 20 - YUV 422" CRLF);
|
|
printf(" 21 - YUV 444" CRLF);
|
|
*/
|
|
printf(" 22: 32bppBGRA" CRLF);
|
|
printf(" 23: 64bppRGBA" CRLF);
|
|
printf(" 24: 64bppRGBAFixedPoint" CRLF);
|
|
printf(" 25: 64bppRGBAHalf" CRLF);
|
|
// printf(" 26 - 128bpp RGBA" CRLF);
|
|
printf(" 27: 128bppRGBAFixedPoint" CRLF);
|
|
printf(" 28: 128bppRGBAFloat" CRLF);
|
|
|
|
printf(" 29: 16bppBGR555" CRLF);
|
|
printf(" 30: 16bppBGR565" CRLF);
|
|
printf(" 31: 32bppBGR101010" CRLF);
|
|
//printf(" 101..116 - 1..16 channel 8bpp" CRLF);
|
|
printf(" 32: 40bppCMYKA" CRLF);
|
|
printf(" 33: 80bppCMYKA" CRLF);
|
|
|
|
printf(" 34: 32bppBGR" CRLF);
|
|
/*
|
|
printf(" 35: 32bppPBGRA" CRLF);
|
|
printf(" 36: 64bppPRGBA" CRLF);
|
|
printf(" 37: 128bppPRGBA Float" CRLF);
|
|
*/
|
|
printf(CRLF);
|
|
|
|
printf(" -d chroma sub-sampling 0: Y-only" CRLF);
|
|
printf(" 1: YCoCg 4:2:0" CRLF);
|
|
printf(" 2: YCoCg 4:2:2" CRLF);
|
|
printf(" 3: YCoCg 4:4:4 (default)" CRLF);
|
|
printf(" (if not set is 4:4:4 for quality >= 0.5 or 4:2:0 for quality < 0.5)" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -l overlapping 0: No overlapping" CRLF);
|
|
printf(" 1: One level overlapping (default)" CRLF);
|
|
printf(" 2: Two level overlapping" CRLF);
|
|
printf(" (if not set is One for quality > 0.4 or Two for quality <= 0.4)" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -f Turn off frequency order bit stream (to spatial)" CRLF);
|
|
printf(CRLF);
|
|
printf(" -p Turn off progressive mode (to sequential)" CRLF);
|
|
printf(CRLF);
|
|
printf(" -t Display timing information" CRLF);
|
|
printf(CRLF);
|
|
printf(" -v Display verbose encoder information" CRLF);
|
|
printf(CRLF);
|
|
printf(" -V tile_wd0 [tile_wd1 ... ] Macro block columns per tile " CRLF);
|
|
printf(CRLF);
|
|
printf(" -H tile_ht0 [tile_ht1 ... ] Macro block rows per tile" CRLF);
|
|
printf(CRLF);
|
|
printf(" -U num_v_tiles num_h_tiles Vertical & horizontal tile count for uniform tiling" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -b Black/White Applies to 1bpp black/white images" CRLF);
|
|
printf(" 0: 0 = black (default)" CRLF);
|
|
printf(" 1: 0 = white" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -a alpha channel format Required for any pixel format with an alpha channel" CRLF);
|
|
printf(" 2: Planar alpha (default)" CRLF);
|
|
printf(" 3: Interleaved alpha" CRLF);
|
|
printf(" Other: Reserved, do not use" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -Q quantization for alpha [1 - 255] Default = 1, lossless" CRLF);
|
|
printf(CRLF);
|
|
|
|
printf(" -F trimmed flexbits [0 - 15] 0: no trimming (default)" CRLF);
|
|
printf(" 15: trim all" CRLF);
|
|
printf(CRLF);
|
|
printf(" -s skip subbands 0: All subbands included (default)" CRLF);
|
|
printf(" 1: Skip flexbits" CRLF);
|
|
printf(" 2: Skip highpass" CRLF);
|
|
printf(" 3: Skip highpass & lowpass (DC only)" CRLF);
|
|
printf(CRLF);
|
|
printf("Eg: %s -i input.bmp -o output.jxr -q 10" CRLF, szExe);
|
|
}
|
|
|
|
void WmpEncAppShowArgs(WMPENCAPPARGS* args)
|
|
{
|
|
const char *szCF[] = {"Y_ONLY", "YUV_420", "YUV_422", "YUV_444", "CMYK"};
|
|
|
|
GUID guidPF = args->guidPixFormat;
|
|
|
|
printf("================================" CRLF);
|
|
printf("Input file: %s" CRLF, args->szInputFile);
|
|
printf("Output file: %s" CRLF, args->szOutputFile);
|
|
printf("Color format: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X" CRLF,
|
|
guidPF.Data1, guidPF.Data2, guidPF.Data3, guidPF.Data4[0], guidPF.Data4[1], guidPF.Data4[2],
|
|
guidPF.Data4[3], guidPF.Data4[4], guidPF.Data4[5], guidPF.Data4[6], guidPF.Data4[7]);
|
|
printf("Internal cf: %s" CRLF, szCF[args->wmiSCP.cfColorFormat]);
|
|
printf("Overlap: %s" CRLF, 0 < args->wmiSCP.olOverlap ? "yes" : "no");
|
|
printf("DCOverlap: %s" CRLF, 1 < args->wmiSCP.olOverlap ? "yes" : "no");
|
|
printf("Alpha: %s" CRLF, 1 < args->wmiSCP.uAlphaMode ? "yes" : "no");
|
|
printf("================================" CRLF);
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
void WmpEncAppInitDefaultArgs(WMPENCAPPARGS* args)
|
|
{
|
|
memset(args, 0, sizeof(*args));
|
|
|
|
args->guidPixFormat = GUID_PKPixelFormatDontCare;
|
|
|
|
args->wmiSCP.bVerbose = FALSE;
|
|
args->wmiSCP.cfColorFormat = YUV_444;
|
|
// args->bFlagRGB_BGR = FALSE; //default BGR
|
|
args->wmiSCP.bdBitDepth = BD_LONG;
|
|
args->wmiSCP.bfBitstreamFormat = FREQUENCY;
|
|
args->wmiSCP.bProgressiveMode = TRUE;
|
|
args->wmiSCP.olOverlap = OL_ONE;
|
|
args->wmiSCP.cNumOfSliceMinus1H = args->wmiSCP.cNumOfSliceMinus1V = 0;
|
|
args->wmiSCP.sbSubband = SB_ALL;
|
|
args->wmiSCP.uAlphaMode = 0;
|
|
args->wmiSCP.uiDefaultQPIndex = 1;
|
|
args->wmiSCP.uiDefaultQPIndexAlpha = 1;
|
|
|
|
args->fltImageQuality = 1.f;
|
|
args->bOverlapSet = 0;
|
|
args->bColorFormatSet = 0;
|
|
}
|
|
|
|
ERR WmpEncAppValidateArgs(WMPENCAPPARGS* args)
|
|
{
|
|
ERR err = WMP_errSuccess;
|
|
|
|
Test(NULL != args->szInputFile, WMP_errInvalidParameter);
|
|
Test(NULL != args->szOutputFile, WMP_errInvalidParameter);
|
|
|
|
Cleanup:
|
|
return err;
|
|
}
|
|
|
|
ERR WmpEncAppParseArgs(int argc, char* argv[], WMPENCAPPARGS* args)
|
|
{
|
|
ERR err = WMP_errSuccess;
|
|
|
|
static const PKPixelFormatGUID* pixelFormat[] =
|
|
{
|
|
&GUID_PKPixelFormat24bppBGR,
|
|
|
|
&GUID_PKPixelFormatBlackWhite,
|
|
|
|
&GUID_PKPixelFormat8bppGray,
|
|
&GUID_PKPixelFormat16bppGray,
|
|
&GUID_PKPixelFormat16bppGrayFixedPoint,
|
|
&GUID_PKPixelFormat16bppGrayHalf,
|
|
&GUID_PKPixelFormatDontCare, // &GUID_PKPixelFormat32bppGray,
|
|
&GUID_PKPixelFormat32bppGrayFixedPoint,
|
|
&GUID_PKPixelFormat32bppGrayFloat,
|
|
|
|
&GUID_PKPixelFormat24bppRGB,
|
|
&GUID_PKPixelFormat48bppRGB,
|
|
&GUID_PKPixelFormat48bppRGBFixedPoint,
|
|
&GUID_PKPixelFormat48bppRGBHalf,
|
|
&GUID_PKPixelFormatDontCare, // &GUID_PKPixelFormat96bppRGB,
|
|
&GUID_PKPixelFormat96bppRGBFixedPoint,
|
|
&GUID_PKPixelFormat128bppRGBFloat,
|
|
|
|
&GUID_PKPixelFormat32bppRGBE,
|
|
&GUID_PKPixelFormat32bppCMYK,
|
|
&GUID_PKPixelFormat64bppCMYK,
|
|
|
|
&GUID_PKPixelFormat12bppYUV420,
|
|
&GUID_PKPixelFormat16bppYUV422,
|
|
&GUID_PKPixelFormat24bppYUV444,
|
|
|
|
//&GUID_PKPixelFormat32bppRGBA,
|
|
&GUID_PKPixelFormat32bppBGRA,
|
|
&GUID_PKPixelFormat64bppRGBA,
|
|
&GUID_PKPixelFormat64bppRGBAFixedPoint,
|
|
&GUID_PKPixelFormat64bppRGBAHalf,
|
|
&GUID_PKPixelFormatDontCare, // &GUID_PKPixelFormat128bppRGBA,
|
|
&GUID_PKPixelFormat128bppRGBAFixedPoint,
|
|
&GUID_PKPixelFormat128bppRGBAFloat,
|
|
|
|
//&GUID_PKPixelFormat32bppPBGRA
|
|
&GUID_PKPixelFormat16bppRGB555,
|
|
&GUID_PKPixelFormat16bppRGB565,
|
|
&GUID_PKPixelFormat32bppRGB101010,
|
|
&GUID_PKPixelFormat40bppCMYKAlpha,
|
|
&GUID_PKPixelFormat80bppCMYKAlpha,
|
|
&GUID_PKPixelFormat32bppBGR,
|
|
&GUID_PKPixelFormat32bppPBGRA,
|
|
&GUID_PKPixelFormat64bppPRGBA,
|
|
&GUID_PKPixelFormat128bppPRGBAFloat,
|
|
};
|
|
|
|
size_t InvalidPF[9] = {6, 13, 19, 20, 21, 26, 35, 36, 37};
|
|
size_t AlphaPF[8] = {22, 23, 24, 25, 27, 28, 32, 33};
|
|
|
|
int i = 1, j = 0, k;
|
|
char c;
|
|
int idxPF = -1;
|
|
|
|
WmpEncAppInitDefaultArgs(args);
|
|
|
|
while (i < argc && argv[i][0] == '-')
|
|
{
|
|
switch ((c = argv[i][1])) {
|
|
/* the no-argument switches */
|
|
case 't':
|
|
// NOOP - now we always print timing info
|
|
break;
|
|
|
|
case 'v':
|
|
args->wmiSCP.bVerbose = !FALSE;
|
|
break;
|
|
|
|
/* simple flag argument */
|
|
case 'f':
|
|
args->wmiSCP.bfBitstreamFormat = SPATIAL;
|
|
break;
|
|
|
|
case 'p':
|
|
args->wmiSCP.bProgressiveMode = FALSE;
|
|
break;
|
|
|
|
case 'u':
|
|
args->wmiSCP.bUnscaledArith = TRUE;
|
|
break;
|
|
|
|
default:
|
|
i ++;
|
|
if (i == argc || argv[i][0] == '-') // need more info
|
|
Call(WMP_errInvalidArgument);
|
|
|
|
switch (c)
|
|
{
|
|
case 'i':
|
|
args->szInputFile = argv[i];
|
|
break;
|
|
|
|
case 'o':
|
|
args->szOutputFile = argv[i];
|
|
break;
|
|
|
|
case 'q':
|
|
{
|
|
args->fltImageQuality = (float) atof(argv[i]);
|
|
if (args->fltImageQuality < 0.f || args->fltImageQuality > 255.f)
|
|
Call(WMP_errInvalidArgument);
|
|
}
|
|
break;
|
|
|
|
case 'Q':
|
|
args->wmiSCP.uiDefaultQPIndexAlpha = (U8)(atoi(argv[i]));
|
|
break;
|
|
|
|
case 's':
|
|
args->wmiSCP.sbSubband = (SUBBAND)(atoi(argv[i]));
|
|
break;
|
|
|
|
case 'c':
|
|
idxPF = (size_t)atol(argv[i]);
|
|
for (k = 0; k < 9; k++)
|
|
{
|
|
if (InvalidPF[k] == (size_t) idxPF)
|
|
{
|
|
printf("*** Unsupported format in JPEG XR ***\n");
|
|
Call(WMP_errInvalidArgument);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'a':
|
|
args->wmiSCP.uAlphaMode = (U8)atoi(argv[i]);
|
|
break;
|
|
|
|
/* case 'R':
|
|
args->bFlagRGB_BGR = (Bool)atoi(argv[i]);
|
|
break;
|
|
*/
|
|
case 'l':
|
|
args->wmiSCP.olOverlap = (OVERLAP)atoi(argv[i]);
|
|
args->bOverlapSet = 1;
|
|
break;
|
|
|
|
case 'd':
|
|
args->wmiSCP.cfColorFormat = (COLORFORMAT)atoi(argv[i]);
|
|
args->bColorFormatSet = 1;
|
|
break;
|
|
|
|
case 'H': // horizontal tiling
|
|
for(j = 0;;i ++, j ++){
|
|
args->wmiSCP.uiTileY[j] = atoi(argv[i]);
|
|
if(i + 1 == argc || argv[i + 1][0] == '-' || j >= MAX_TILES-1)
|
|
break;
|
|
}
|
|
args->wmiSCP.cNumOfSliceMinus1H = (U8)j;
|
|
break;
|
|
|
|
case 'V': // vertical tiling
|
|
for(j = 0;;i ++, j ++){
|
|
args->wmiSCP.uiTileX[j] = atoi(argv[i]);
|
|
if(i + 1 == argc || argv[i + 1][0] == '-' || j >= MAX_TILES-1)
|
|
break;
|
|
}
|
|
args->wmiSCP.cNumOfSliceMinus1V = (U8)j;
|
|
break;
|
|
|
|
case 'U': // uniform tiling
|
|
if(i + 1 < argc && argv[i + 1][0] != '-'){
|
|
if(atoi(argv[i]) > 0 && atoi(argv[i + 1]) > 0){
|
|
args->wmiSCP.cNumOfSliceMinus1H = atoi(argv[i]) - 1;
|
|
args->wmiSCP.cNumOfSliceMinus1V = atoi(argv[i + 1]) - 1;
|
|
}
|
|
i ++;
|
|
}
|
|
break;
|
|
|
|
case 'm':
|
|
args->wmiSCP.nLenMantissaOrShift = (U8)atoi(argv[i]);
|
|
break;
|
|
|
|
case 'C':
|
|
args->wmiSCP.nExpBias = (I8) atoi(argv[i]) + 128; // rollover arithmetic
|
|
break;
|
|
|
|
case 'b':
|
|
args->wmiSCP.bBlackWhite = (Bool)atoi(argv[i]);
|
|
break;
|
|
|
|
case 'F':
|
|
args->wmiSCP.uiTrimFlexBits = (U8)atoi(argv[i]);
|
|
if (args->wmiSCP.uiTrimFlexBits > 15)
|
|
args->wmiSCP.uiTrimFlexBits = 15;
|
|
break;
|
|
|
|
default:
|
|
Call(WMP_errInvalidArgument);
|
|
}
|
|
}
|
|
|
|
i ++;
|
|
}
|
|
|
|
FailIf((int) sizeof2(pixelFormat) <= idxPF, WMP_errUnsupportedFormat);
|
|
if (idxPF >= 0)
|
|
args->guidPixFormat = *pixelFormat[idxPF];
|
|
|
|
if ((idxPF >= 1) && (idxPF <= 8))
|
|
args->wmiSCP.cfColorFormat = Y_ONLY;
|
|
else if ((idxPF == 17) || (idxPF == 18) || (idxPF == 32) || (idxPF == 33))
|
|
args->wmiSCP.cfColorFormat = CMYK;
|
|
|
|
for (k = 0; k < 8; k++)
|
|
{
|
|
if (AlphaPF[k] == (size_t) idxPF)
|
|
{
|
|
if(0 == args->wmiSCP.uAlphaMode)//with Alpha and no default, set default as Planar
|
|
{
|
|
args->wmiSCP.uAlphaMode = 2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//================================
|
|
Call(WmpEncAppValidateArgs(args));
|
|
|
|
Cleanup:
|
|
return err;
|
|
}
|
|
|
|
|
|
// Y, U, V, YHP, UHP, VHP
|
|
int DPK_QPS_420[12][6] = { // for 8 bit only
|
|
{ 66, 65, 70, 72, 72, 77 },
|
|
{ 59, 58, 63, 64, 63, 68 },
|
|
{ 52, 51, 57, 56, 56, 61 },
|
|
{ 48, 48, 54, 51, 50, 55 },
|
|
{ 43, 44, 48, 46, 46, 49 },
|
|
{ 37, 37, 42, 38, 38, 43 },
|
|
{ 26, 28, 31, 27, 28, 31 },
|
|
{ 16, 17, 22, 16, 17, 21 },
|
|
{ 10, 11, 13, 10, 10, 13 },
|
|
{ 5, 5, 6, 5, 5, 6 },
|
|
{ 2, 2, 3, 2, 2, 2 }
|
|
};
|
|
|
|
int DPK_QPS_8[12][6] = {
|
|
{ 67, 79, 86, 72, 90, 98 },
|
|
{ 59, 74, 80, 64, 83, 89 },
|
|
{ 53, 68, 75, 57, 76, 83 },
|
|
{ 49, 64, 71, 53, 70, 77 },
|
|
{ 45, 60, 67, 48, 67, 74 },
|
|
{ 40, 56, 62, 42, 59, 66 },
|
|
{ 33, 49, 55, 35, 51, 58 },
|
|
{ 27, 44, 49, 28, 45, 50 },
|
|
{ 20, 36, 42, 20, 38, 44 },
|
|
{ 13, 27, 34, 13, 28, 34 },
|
|
{ 7, 17, 21, 8, 17, 21 }, // Photoshop 100%
|
|
{ 2, 5, 6, 2, 5, 6 }
|
|
};
|
|
|
|
int DPK_QPS_16[11][6] = {
|
|
{ 197, 203, 210, 202, 207, 213 },
|
|
{ 174, 188, 193, 180, 189, 196 },
|
|
{ 152, 167, 173, 156, 169, 174 },
|
|
{ 135, 152, 157, 137, 153, 158 },
|
|
{ 119, 137, 141, 119, 138, 142 },
|
|
{ 102, 120, 125, 100, 120, 124 },
|
|
{ 82, 98, 104, 79, 98, 103 },
|
|
{ 60, 76, 81, 58, 76, 81 },
|
|
{ 39, 52, 58, 36, 52, 58 },
|
|
{ 16, 27, 33, 14, 27, 33 },
|
|
{ 5, 8, 9, 4, 7, 8 }
|
|
};
|
|
|
|
int DPK_QPS_16f[11][6] = {
|
|
{ 148, 177, 171, 165, 187, 191 },
|
|
{ 133, 155, 153, 147, 172, 181 },
|
|
{ 114, 133, 138, 130, 157, 167 },
|
|
{ 97, 118, 120, 109, 137, 144 },
|
|
{ 76, 98, 103, 85, 115, 121 },
|
|
{ 63, 86, 91, 62, 96, 99 },
|
|
{ 46, 68, 71, 43, 73, 75 },
|
|
{ 29, 48, 52, 27, 48, 51 },
|
|
{ 16, 30, 35, 14, 29, 34 },
|
|
{ 8, 14, 17, 7, 13, 17 },
|
|
{ 3, 5, 7, 3, 5, 6 }
|
|
};
|
|
|
|
int DPK_QPS_32f[11][6] = {
|
|
{ 194, 206, 209, 204, 211, 217 },
|
|
{ 175, 187, 196, 186, 193, 205 },
|
|
{ 157, 170, 177, 167, 180, 190 },
|
|
{ 133, 152, 156, 144, 163, 168 },
|
|
{ 116, 138, 142, 117, 143, 148 },
|
|
{ 98, 120, 123, 96, 123, 126 },
|
|
{ 80, 99, 102, 78, 99, 102 },
|
|
{ 65, 79, 84, 63, 79, 84 },
|
|
{ 48, 61, 67, 45, 60, 66 },
|
|
{ 27, 41, 46, 24, 40, 45 },
|
|
{ 3, 22, 24, 2, 21, 22 }
|
|
};
|
|
|
|
//================================================================
|
|
// main function
|
|
//================================================================
|
|
int
|
|
#ifndef __ANSI__
|
|
__cdecl
|
|
#endif // __ANSI__
|
|
main(int argc, char* argv[])
|
|
{
|
|
ERR err = WMP_errSuccess;
|
|
|
|
PKFactory* pFactory = NULL;
|
|
struct WMPStream* pEncodeStream = NULL;
|
|
PKCodecFactory* pCodecFactory = NULL;
|
|
PKCodecFactory* pTestFactory = NULL;
|
|
PKImageEncode* pEncoder = NULL;
|
|
|
|
// clock_t start = 0, finish = 0;
|
|
WMPENCAPPARGS args;
|
|
char* pExt = NULL;
|
|
|
|
//================================
|
|
// parse command line parameters
|
|
if (1 == argc)
|
|
{
|
|
WmpEncAppUsage(argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
Call(WmpEncAppParseArgs(argc, argv, &args));
|
|
if (args.wmiSCP.bVerbose)
|
|
{
|
|
WmpEncAppShowArgs(&args);
|
|
}
|
|
|
|
//================================
|
|
pExt = strrchr(args.szInputFile, '.');
|
|
FailIf(NULL == pExt, WMP_errUnsupportedFormat);
|
|
|
|
//================================
|
|
Call(PKCreateFactory(&pFactory, PK_SDK_VERSION));
|
|
Call(pFactory->CreateStreamFromFilename(&pEncodeStream, args.szOutputFile, "wb"));
|
|
|
|
//================================
|
|
Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION));
|
|
Call(pCodecFactory->CreateCodec(&IID_PKImageWmpEncode, (void**)&pEncoder));
|
|
|
|
//----------------------------------------------------------------
|
|
Call(PKCreateTestFactory(&pTestFactory, WMP_SDK_VERSION));
|
|
|
|
//
|
|
// go through each image
|
|
//
|
|
//for (i = 0; ; ++i)
|
|
{
|
|
PKImageDecode* pDecoder = NULL;
|
|
PKFormatConverter* pConverter = NULL;
|
|
PKPixelInfo PI;
|
|
|
|
Float rX = 0.0, rY = 0.0;
|
|
PKRect rect = {0, 0, 0, 0};
|
|
|
|
//================================
|
|
Call(pTestFactory->CreateDecoderFromFile(args.szInputFile, &pDecoder));
|
|
if (IsEqualGUID(&args.guidPixFormat, &GUID_PKPixelFormatDontCare))
|
|
Call(pDecoder->GetPixelFormat(pDecoder, &args.guidPixFormat));
|
|
|
|
PI.pGUIDPixFmt = &args.guidPixFormat;
|
|
Call(PixelFormatLookup(&PI, LOOKUP_FORWARD));
|
|
if ((PI.grBit & PK_pixfmtHasAlpha) && args.wmiSCP.uAlphaMode == 0)
|
|
args.wmiSCP.uAlphaMode = 2; // with Alpha and no default, set default as Planar
|
|
|
|
FailIf(PI.uSamplePerPixel > 1 && PI.uBitsPerSample > 8 && args.wmiSCP.cfColorFormat != YUV_444,
|
|
WMP_errInvalidArgument);
|
|
|
|
//================================
|
|
Call(pCodecFactory->CreateFormatConverter(&pConverter));
|
|
Call(pConverter->Initialize(pConverter, pDecoder, pExt, args.guidPixFormat));
|
|
|
|
//================================
|
|
Call(pDecoder->GetSize(pDecoder, &rect.Width, &rect.Height));
|
|
|
|
if (args.wmiSCP.cNumOfSliceMinus1H == 0 && args.wmiSCP.uiTileY[0] > 0)
|
|
{
|
|
// # of horizontal slices, rounded down by half tile size.
|
|
U32 uTileY = args.wmiSCP.uiTileY[0] * MB_HEIGHT_PIXEL;
|
|
args.wmiSCP.cNumOfSliceMinus1H = (U32) rect.Height < (uTileY >> 1) ? 0 :
|
|
(rect.Height + (uTileY >> 1)) / uTileY - 1;
|
|
}
|
|
if (args.wmiSCP.cNumOfSliceMinus1V == 0 && args.wmiSCP.uiTileX[0] > 0)
|
|
{
|
|
// # of vertical slices, rounded down by half tile size.
|
|
U32 uTileX = args.wmiSCP.uiTileX[0] * MB_HEIGHT_PIXEL;
|
|
args.wmiSCP.cNumOfSliceMinus1V = (U32) rect.Width < (uTileX >> 1) ? 0 :
|
|
(rect.Width + (uTileX >> 1)) / uTileX - 1;
|
|
}
|
|
|
|
Call(pEncoder->Initialize(pEncoder, pEncodeStream, &args.wmiSCP, sizeof(args.wmiSCP)));
|
|
|
|
//ImageQuality Q (BD==1) Q (BD==8) Q (BD==16) Q (BD==32F) Subsample Overlap
|
|
//[0.0, 0.4] 8-IQ*5 (see table) (see table) (see table) 4:4:4 2
|
|
//(0.4, 0.8) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1
|
|
//[0.8, 1.0) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1
|
|
//[1.0, 1.0] 1 1 1 1 4:4:4 0
|
|
|
|
if (args.fltImageQuality < 1.0F)
|
|
{
|
|
if (!args.bOverlapSet)
|
|
{
|
|
if (args.fltImageQuality > 0.4F)
|
|
pEncoder->WMP.wmiSCP.olOverlap = OL_ONE;
|
|
else
|
|
pEncoder->WMP.wmiSCP.olOverlap = OL_TWO;
|
|
}
|
|
|
|
if (!args.bColorFormatSet)
|
|
{
|
|
if (args.fltImageQuality >= 0.5F || PI.uBitsPerSample > 8)
|
|
pEncoder->WMP.wmiSCP.cfColorFormat = YUV_444;
|
|
else
|
|
pEncoder->WMP.wmiSCP.cfColorFormat = YUV_420;
|
|
}
|
|
|
|
if (PI.bdBitDepth == BD_1)
|
|
{
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8)(8 - 5.0F *
|
|
args.fltImageQuality + 0.5F);
|
|
}
|
|
else
|
|
{
|
|
// remap [0.8, 0.866, 0.933, 1.0] to [0.8, 0.9, 1.0, 1.1]
|
|
// to use 8-bit DPK QP table (0.933 == Photoshop JPEG 100)
|
|
int qi;
|
|
float qf;
|
|
int* pQPs;
|
|
if (args.fltImageQuality > 0.8f && PI.bdBitDepth == BD_8 &&
|
|
pEncoder->WMP.wmiSCP.cfColorFormat != YUV_420 &&
|
|
pEncoder->WMP.wmiSCP.cfColorFormat != YUV_422)
|
|
args.fltImageQuality = 0.8f + (args.fltImageQuality - 0.8f) * 1.5f;
|
|
|
|
qi = (int) (10.f * args.fltImageQuality);
|
|
qf = 10.f * args.fltImageQuality - (float) qi;
|
|
|
|
pQPs =
|
|
(pEncoder->WMP.wmiSCP.cfColorFormat == YUV_420 ||
|
|
pEncoder->WMP.wmiSCP.cfColorFormat == YUV_422) ?
|
|
DPK_QPS_420[qi] :
|
|
(PI.bdBitDepth == BD_8 ? DPK_QPS_8[qi] :
|
|
(PI.bdBitDepth == BD_16 ? DPK_QPS_16[qi] :
|
|
(PI.bdBitDepth == BD_16F ? DPK_QPS_16f[qi] :
|
|
DPK_QPS_32f[qi])));
|
|
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8) (0.5f +
|
|
(float) pQPs[0] * (1.f - qf) + (float) (pQPs + 6)[0] * qf);
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndexU = (U8) (0.5f +
|
|
(float) pQPs[1] * (1.f - qf) + (float) (pQPs + 6)[1] * qf);
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndexV = (U8) (0.5f +
|
|
(float) pQPs[2] * (1.f - qf) + (float) (pQPs + 6)[2] * qf);
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndexYHP = (U8) (0.5f +
|
|
(float) pQPs[3] * (1.f - qf) + (float) (pQPs + 6)[3] * qf);
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndexUHP = (U8) (0.5f +
|
|
(float) pQPs[4] * (1.f - qf) + (float) (pQPs + 6)[4] * qf);
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndexVHP = (U8) (0.5f +
|
|
(float) pQPs[5] * (1.f - qf) + (float) (pQPs + 6)[5] * qf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8) args.fltImageQuality;
|
|
}
|
|
|
|
if(pEncoder->WMP.wmiSCP.uAlphaMode == 2)
|
|
pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex = args.wmiSCP.uiDefaultQPIndexAlpha;
|
|
|
|
Call(pEncoder->SetPixelFormat(pEncoder, args.guidPixFormat));
|
|
|
|
Call(pEncoder->SetSize(pEncoder, rect.Width, rect.Height));
|
|
|
|
Call(pDecoder->GetResolution(pDecoder, &rX, &rY));
|
|
Call(pEncoder->SetResolution(pEncoder, rX, rY));
|
|
|
|
//================================
|
|
// re-encode the input source to the output
|
|
//
|
|
pEncoder->WriteSource = PKImageEncode_WriteSource;
|
|
Call(pEncoder->WriteSource(pEncoder, pConverter, &rect));
|
|
|
|
pConverter->Release(&pConverter);
|
|
pDecoder->Release(&pDecoder);
|
|
|
|
//if (i + 1 == 5)
|
|
//{
|
|
// break;
|
|
//}
|
|
|
|
// multi-frame support NYI
|
|
//Call(pEncoder->CreateNewFrame(pEncoder, &wmiSCP, sizeof(wmiSCP)));
|
|
}
|
|
|
|
// Call(pEncoder->Terminate(pEncoder));
|
|
pEncoder->Release(&pEncoder);
|
|
|
|
Cleanup:
|
|
if (WMP_errSuccess != err)
|
|
{
|
|
WmpEncAppUsage(argv[0]);
|
|
}
|
|
|
|
return (int)err;
|
|
}
|