Commit a4ddbf0a authored by Mathieu Malaterre's avatar Mathieu Malaterre

Import Upstream version 1.1

parent 054ac943
......@@ -119,7 +119,7 @@ libjxrglue.a: $(OBJ_GLUE) $(OBJ_TEST)
##
LIBRARIES=libjxrglue.a libjpegxr.a
LIBS=-L. $(LIBRARIES)
LIBS=-L. $(LIBRARIES) -lm
ENCAPP=JxrEncApp
$(ENCAPP): $(LIBRARIES)
......
JPEG XR Device Porting Kit v1.0 - April 2013
---------------------------------------------------------------------------------
JPEG XR
-------
This device porting kit (DPK) supports the JPEG XR still image format, based on
technology originally developed by Mirosoft under the name HD Photo (formerly
Windows Media™ Photo). The JPEG XR format is similar, but not identical, to the
HD Photo/Windows Media™ Photo format.
The JPEG XR format replaces the HD Photo/Windows Media™ Photo format in both
Windows 8 and the Windows Image Component (WIC). WIC accompanies the Internet
Explorer 10 redistributable packages for down-level versions of Windows.
Some “Windows Media™ Photo” (WMP) naming conventions are still used internally
with this release of the DPK.
JPEG XR files use the .jxr extension. Applications that support the JPEG XR
file format should recognize and decode HD Photo/Windows Media™ Photo
.hdp/.wdp files, but only offer to create files with the .jxr extension.
Device Porting Kit Contents
---------------------------
This device porting kit contains documentation, reference source code, sample
applications and utilities for the evaluation and implementation of the JPEG XR
file format and compression technology.
Assuming the installation dir is C:\jxrlib, all the paths mentioned below are
relative to this base path.
The Visual Studio 2010 main solution is:
jxrencoderdecoder\JXR.sln
The Visual Studio 2012 main solution is:
jxrencoderdecoder\JXR_vc11.sln
Build JXR.sln Debug Configuration, you will get:
jxrencoderdecoder\Debug\JXRDecApp\JXRDecApp.exe
jxrencoderdecoder\Debug\JXREncApp\JXREncApp.exe
The main directory contains a Unix/Linux compatible make file for building the
encoder and decoder, including support for big endian or little endian processor
architecture. It is the developer's responsibility to properly organize all the
source files according to the paths defined in this make file for its correct
operation. This is provided as a convenience for cross-platform developers and
to demonstrate the correct operation of the encoder and decoder on big endian
systems.
The JPEG XR Image Coding Spectification provides a detailed specification of the
compression encoder and decoder algorithms plus the detailed structure of the
compressed data (elementary) bit stream. This document is designed to be used in
conjunction with the included source code. If you find instances where the code
differs from the documentation, the code implementation should be used as the
reference.
The JPEG XR Image Coding Spectification is an international standard and is
available at: http://www.itu.int/rec/T-REC-T.832 while the reference software is
available at: http://www.itu.int/rec/T-REC-T.835.
"JPEGXR_DPK_1.0.doc" documents the contents of this porting kit, the usage of
the command line file conversion utilities (JXREncApp.exe and JXRDecApp.exe), and
technical details of the API's and data structures between these sample command
line applications and the core codec.
The code and documentation in this release represent the final design and
specification of the 1.0 bit stream, and can be used as the reference for final
implementations of encoders and decoders for JPEG XR.
This release of the DPK has received extensive testing of all the various pixel
formats, encoder options and modes of operation. We are confident that most errors
and other bugs have been resolved. Any code bugs, documentation errors or other
discrepancies found in this release candidate should be reported to Microsoft as
promptly as possible. These can be submitted to hdview@microsoft.com.
This DPK provides basic support for big endian architectures. We have
successfully tested the encoder and decoder using a big endian processor. This
support is provided as a starting reference to be adapted to the specific
platform and hardware architecture of the target system.
Contact Information
-------------------
For any and all technical questions or feedback about any part of this Device
Porting Kit, including the documentation, please send email to:
hdview@microsoft.com
We will respond as promptly as possible with answers to your questions.
Additional information, best practices, tools, utilities, sample code, sample
image content, links to additional resources and community discussion can
currently be found at http://hdview.wordpress.com/.
- The Microsoft JPEG XR Development Team
---------------------------------------------------------------------------------
......@@ -195,10 +195,14 @@ void WmpDecAppUsage(const char* szExe)
void WmpDecAppShowArgs(WMPDECAPPARGS* args)
{
GUID guidPF = args->guidPixFormat;
printf("================================" CRLF);
printf("Input file: %s" CRLF, args->szInputFile);
printf("Output file: %s" CRLF, args->szOutputFile);
printf("Color format: %x" CRLF, args->guidPixFormat);
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("Post processing strength: %d" CRLF, args->cPostProcStrength);
printf("Thumbnail: %d" CRLF, (int) args->tThumbnailFactor);
printf("================================" CRLF);
......@@ -638,81 +642,3 @@ Cleanup:
return (int)err;
}
//================================================================
#ifdef _WIN32_WCE
#define DEFDIR "\\Temp\\"
int GetArguments(int* pc, char** ppv[])
{
size_t i = 0;
static char line[132];
static char* args[20] =
{
"WMPDecApp.exe",
"-i",
DEFDIR "test.jxr",
"-o",
DEFDIR "test.bmp",
"-c",
"0",
"-v",
"-t",
NULL,
};
FILE* pfIn = fopen(DEFDIR "WMPIni.txt", "r");
// default arguments to return
*pc = 9;
*ppv = args;
while (fgets(line, sizeof2(line), pfIn))
{
// search for the matching line
if (0 == strcmp(strtok(line, " \t"), args[0]))
{
// extract each argument from the matching line
for (i = 1; i < sizeof2(args) - 1 && (args[i] = strtok(NULL, " \t\n\r")); ++i);
*pc = i;
printf("Args from WMPIni.txt" CRLF);
break;
}
}
fclose(pfIn);
for (i = 0; i < (size_t)*pc; printf("%s ", args[i++]));
puts("");
return 0;
}
//================================================================
// Windows CE App entry
//================================================================
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
int argc = 0;
char** argv = NULL;
//================================
// redirect stdou and stderr
fclose(stdout);
fopen(DEFDIR "stdout.txt", "wb");
fclose(stderr);
fopen(DEFDIR "stderr.txt", "wb");
//================================
GetArguments(&argc, &argv);
//================================
return main(argc, argv);
}
#endif
......@@ -42,8 +42,8 @@ typedef struct tagWMPENCAPPARGS
CWMIStrCodecParam wmiSCP;
float fltImageQuality;
float fltAlphaQuality;
Bool bOverlapSet;
Bool bColorFormatSet;
} WMPENCAPPARGS;
//----------------------------------------------------------------
......@@ -64,9 +64,8 @@ void WmpEncAppUsage(const char* szExe)
printf(" -o output.jxr Output JPEG XR file name" CRLF);
printf(CRLF);
printf(" -q quality [0.0 - 1.0) : quality" CRLF);
printf(" or quantization [1 - 255] : quantization" CRLF);
printf(" Default is lossless (1.0 quality or 1 quantization)" 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);
......@@ -125,11 +124,13 @@ void WmpEncAppUsage(const char* szExe)
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);
......@@ -140,11 +141,11 @@ void WmpEncAppUsage(const char* szExe)
printf(CRLF);
printf(" -v Display verbose encoder information" CRLF);
printf(CRLF);
printf(" -V tile_wd0 [tile_wd1 ... ] Macro block rows per tile " CRLF);
printf(" -V tile_wd0 [tile_wd1 ... ] Macro block columns per tile " CRLF);
printf(CRLF);
printf(" -H tile_ht0 [tile_ht1 ... ] Macro block columns per tile" CRLF);
printf(" -H tile_ht0 [tile_ht1 ... ] Macro block rows per tile" CRLF);
printf(CRLF);
printf(" -U num_h_tiles num_v_tiles Horiz & vert tile count for uniform tiling" 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);
......@@ -158,9 +159,7 @@ void WmpEncAppUsage(const char* szExe)
printf(" Other: Reserved, do not use" CRLF);
printf(CRLF);
printf(" -Q quality [0.0 - 1.0) : quality" CRLF);
printf(" or quantization [1 - 255] : quantization" CRLF);
printf(" for alpha Default is lossless (1.0 quality or 1 quantization)" 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);
......@@ -177,11 +176,15 @@ void WmpEncAppUsage(const char* 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: %x" CRLF, args->guidPixFormat);
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");
......@@ -202,7 +205,7 @@ void WmpEncAppInitDefaultArgs(WMPENCAPPARGS* args)
args->wmiSCP.bdBitDepth = BD_LONG;
args->wmiSCP.bfBitstreamFormat = FREQUENCY;
args->wmiSCP.bProgressiveMode = TRUE;
args->wmiSCP.olOverlap = OL_NONE;
args->wmiSCP.olOverlap = OL_ONE;
args->wmiSCP.cNumOfSliceMinus1H = args->wmiSCP.cNumOfSliceMinus1V = 0;
args->wmiSCP.sbSubband = SB_ALL;
args->wmiSCP.uAlphaMode = 0;
......@@ -210,8 +213,8 @@ void WmpEncAppInitDefaultArgs(WMPENCAPPARGS* args)
args->wmiSCP.uiDefaultQPIndexAlpha = 1;
args->fltImageQuality = 1.f;
args->fltAlphaQuality = 1.f;
args->bOverlapSet = 0;
args->bColorFormatSet = 0;
}
ERR WmpEncAppValidateArgs(WMPENCAPPARGS* args)
......@@ -338,11 +341,7 @@ ERR WmpEncAppParseArgs(int argc, char* argv[], WMPENCAPPARGS* args)
break;
case 'Q':
{
args->fltAlphaQuality = (float) atof(argv[i]);
if (args->fltAlphaQuality < 0.f || args->fltAlphaQuality > 255.f)
Call(WMP_errInvalidArgument);
}
args->wmiSCP.uiDefaultQPIndexAlpha = (U8)(atoi(argv[i]));
break;
case 's':
......@@ -376,12 +375,13 @@ ERR WmpEncAppParseArgs(int argc, char* argv[], WMPENCAPPARGS* args)
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 >= 255)
if(i + 1 == argc || argv[i + 1][0] == '-' || j >= MAX_TILES-1)
break;
}
args->wmiSCP.cNumOfSliceMinus1H = (U8)j;
......@@ -390,7 +390,7 @@ ERR WmpEncAppParseArgs(int argc, char* argv[], WMPENCAPPARGS* args)
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 >= 255)
if(i + 1 == argc || argv[i + 1][0] == '-' || j >= MAX_TILES-1)
break;
}
args->wmiSCP.cNumOfSliceMinus1V = (U8)j;
......@@ -462,6 +462,20 @@ Cleanup:
// 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 },
......@@ -591,6 +605,9 @@ main(int argc, char* argv[])
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));
......@@ -616,9 +633,9 @@ main(int argc, char* argv[])
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) 180-IQ*100 30-IQ*25 4:4:4 2
//(0.4, 0.8) 8-IQ*5 (see table) 180-IQ*100 30-IQ*25 4:4:4 1
//[0.8, 1.0) 8-IQ*5 (see table) 260-IQ*200 30-IQ*25 4:4:4 1
//[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)
......@@ -631,6 +648,14 @@ main(int argc, char* argv[])
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 *
......@@ -643,16 +668,21 @@ main(int argc, char* argv[])
int qi;
float qf;
int* pQPs;
if (args.fltImageQuality > 0.8f && PI.bdBitDepth == BD_8)
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 =
PI.bdBitDepth == BD_8 ? DPK_QPS_8[qi] :
(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] :
(PI.bdBitDepth == BD_16F ? DPK_QPS_16f[qi] :
DPK_QPS_32f[qi])));
pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8) (0.5f +
......@@ -674,59 +704,8 @@ main(int argc, char* argv[])
pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8) args.fltImageQuality;
}
if(pEncoder->WMP.wmiSCP.uAlphaMode != 0)
{
if (args.fltAlphaQuality < 1.0F)
{
if (!args.bOverlapSet)
{
if (args.fltAlphaQuality > 0.4F)
pEncoder->WMP.wmiSCP_Alpha.olOverlap = OL_ONE;
else
pEncoder->WMP.wmiSCP_Alpha.olOverlap = OL_TWO;
}
if (PI.bdBitDepth == BD_8)
{
// remap [0.8, 0.866, 0.933, 1.0] to [0.8, 0.9, 1.0, 1.1]
// to use DPK QP table
int qi;
float qf;
if (args.fltAlphaQuality > 0.8f)
args.fltAlphaQuality = 0.8f + (args.fltAlphaQuality - 0.8f) * 1.5f;
qi = (int) (10.f * args.fltAlphaQuality);
qf = 10.f * args.fltAlphaQuality - (float) qi;
pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex = (U8) (0.5f +
(float) DPK_QPS_8[qi][0] * (1.f - qf) + (float) DPK_QPS_8[qi + 1][0] * qf);
}
else if (PI.bdBitDepth == BD_16)
{
if (args.fltAlphaQuality >= 0.8F)
pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8)(260 - 200.0F *
args.fltAlphaQuality + 0.5F);
else
pEncoder->WMP.wmiSCP.uiDefaultQPIndex = (U8)(180 - 100.0F *
args.fltAlphaQuality + 0.5F);
}
else if (PI.bdBitDepth == BD_32F)
{
pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex = (U8)(30 - 25.0F *
args.fltAlphaQuality + 0.5F);
pEncoder->WMP.wmiSCP_Alpha.cfColorFormat = YUV_444; // spec says float must be YUV 444
}
else
{
pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex = 1; // Default to lossless
}
}
else
{
pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex = (U8) args.fltAlphaQuality;
}
args.wmiSCP.uiDefaultQPIndexAlpha = pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex;
}
if(pEncoder->WMP.wmiSCP.uAlphaMode == 2)
pEncoder->WMP.wmiSCP_Alpha.uiDefaultQPIndex = args.wmiSCP.uiDefaultQPIndexAlpha;
Call(pEncoder->SetPixelFormat(pEncoder, args.guidPixFormat));
......@@ -764,89 +743,3 @@ Cleanup:
return (int)err;
}
//================================================================
#ifdef _WIN32_WCE
/*
#==============
# comments
#==============
WMPEncApp.exe -i \Temp\test.bmp -o \Temp\test.jxr -q 1
WMPDecApp.exe -i \Temp\test.jxr -o \Temp\test.bmp -c 6
*/
#define DEFDIR "\\Temp\\"
int GetArguments(int* pc, char** ppv[])
{
size_t i = 0;
static char line[132];
static char* args[20] =
{
"WMPEncApp.exe",
"-i",
DEFDIR "test.bmp",
"-o",
DEFDIR "test.jxr",
"-q",
"1",
"-v",
"-t",
NULL,
};
FILE* pfIn = fopen(DEFDIR "WMPIni.txt", "r");
// default arguments to return
*pc = 9;
*ppv = args;
while (fgets(line, sizeof2(line), pfIn))
{
// search for the matching line
if (0 == strcmp(strtok(line, " \t"), args[0]))
{
// extract each argument from the matching line
for (i = 1; i < sizeof2(args) - 1 && (args[i] = strtok(NULL, " \t\n\r")); ++i);
*pc = i;
printf("Args from WMPIni.txt" CRLF);
break;
}
}
fclose(pfIn);
for (i = 0; i < (size_t)*pc; printf("%s ", args[i++]));
puts("");
return 0;
}
//================================================================
// Windows CE App entry
//================================================================
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
int argc = 0;
char** argv = NULL;
//================================
// redirect stdou and stderr
fclose(stdout);
fopen(DEFDIR "stdout.txt", "wb");
fclose(stderr);
fopen(DEFDIR "stderr.txt", "wb");
//================================
GetArguments(&argc, &argv);
//================================
return main(argc, argv);
}
#endif
......@@ -46,8 +46,7 @@ extern "C" {
#define min(b,a) ((a) < (b) ? (a) : (b))
#endif
#ifdef __ANSI__
//#define STRCPY_SAFE(pszDest, cbDest, pszSrc) (strcpy((pszDest), (pszSrc)) == (pszDest) ? 0 : 1)
#define STRCPY_SAFE(pszDest, cbDest, pszSrc) (strlcpy((pszDest), (pszSrc), (cbDest)) < (cbDest) ? 0 : 1) // Macintosh impl, not ANSI
#define STRCPY_SAFE(pszDest, cbDest, pszSrc) (strncpy((pszDest), (pszSrc), (cbDest)) == (pszDest) ? 0 : 1)
#else
#define STRCPY_SAFE(pszDest, cbDest, pszSrc) (strcpy_s((pszDest), (cbDest), (pszSrc)))
#endif // __ANSI__
......
......@@ -33,6 +33,110 @@
//================================================================
// PKFormatConverter
//================================================================
#define HLF_MIN 0.00006103515625f
#define HLF_MAX 65504.0f
#define HLF_MIN_BITS 0x0400
#define HLF_MAX_BITS 0x7bff
#define HLF_MIN_BITS_NEG (HLF_MIN_BITS | 0x8000)
#define HLF_MAX_BITS_NEG (HLF_MAX_BITS | 0x8000)
#define HLF_QNaN_BITZS 0x7fff
// simple and slow implementation of half <-> float conversion
static U32 Convert_Half_To_Float(U16 u16)
{
// 1s5e10m -> 1s8e23m
const U32 s = (u16 >> 15) & 0x0001;
const U32 e = (u16 >> 10) & 0x001f;
const U32 m = (u16 >> 0) & 0x03ff;
if (0 == e) // 0, denorm
{
return s << 31;
}
else if (~(~0 << 5) == e) // inf, snan, qnan
{
return (s << 31) | ~(~0 << 8) << 23| (m << 13);
}
return (s << 31) | ((e - 15 + 127) << 23) | (m << 13); // norm
}
static U16 Convert_Float_To_Half(float f)
{
// 1s5e10m -> 1s8e23m
const U32 iFloat = *(U32*)&f; // Convert float to U32
if (f != f)
{
return (U16)(iFloat | HLF_QNaN_BITZS); // +QNaN, -QNaN
}
else if (f < -HLF_MAX)
{
return HLF_MAX_BITS_NEG;
}
else if (HLF_MAX < f)
{
return HLF_MAX_BITS;
}
else if (-HLF_MIN < f && f < HLF_MIN)
{
return (U16)((iFloat >> 16) & 0x8000); // +0, -0
}
// Cut-and-paste from C++, introduce scope so we can decl more vars
{
const U32 s = (iFloat >> 31) & 0x00000001;
const U32 e = (iFloat >> 23) & 0x000000ff;
const U32 m = (iFloat >> 0) & 0x007fffff;
return (U16) ((s << 15) | ((e - 127 + 15) << 10) | (m >> 13));
}
}
static U8 Convert_Float_To_U8(float f)
{
// convert from linear scRGB to non-linear sRGB
if (f <= 0)
{
return 0;
}
else if (f <= 0.0031308f)
{
return (U8)((255.0f * f * 12.92f) + 0.5f);
}
else if (f < 1.0f)
{
return (U8)((255.0f * ((1.055f * (float)pow(f, 1.0 / 2.4)) - 0.055f)) + 0.5f);
}
else
{
return 255;
}
}
static U8 Convert_AlphaFloat_To_U8(float f)
{
// alpha is converted differently than RGB in scRGB
if (f <= 0)
{
return 0;
}
else if (f < 1.0f)
{
return (U8)((255.0f * f) + 0.5f);
}
else
{
return 255;
}
}
ERR RGB24_BGR24(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbStride)
{
I32 i = 0, j = 0;
......@@ -905,70 +1009,6 @@ ERR RGB96Float_RGBE(PKFormatConverter* pFC, const PKRect* pRect, U8* pb, U32 cbS
return WMP_errSuccess;
}
#define HLF_MIN 0.00006103515625f
#define HLF_MAX 65504.0f
#define HLF_MIN_BITS 0x0400
#define HLF_MAX_BITS 0x7bff
#define HLF_MIN_BITS_NEG (HLF_MIN_BITS | 0x8000)
#define HLF_MAX_BITS_NEG (HLF_MAX_BITS | 0x8000)
#define HLF_QNaN_BITZS 0x7fff
// simple and slow implementation of half <-> float conversion
static U32 Convert_Half_To_Float(U16 u16)
{
// 1s5e10m -> 1s8e23m
const U32 s = (u16 >> 15) & 0x0001;
const U32 e = (u16 >> 10) & 0x001f;
const U32 m = (u16 >> 0) & 0x03ff;
if (0 == e) // 0, denorm
{
return s << 31;
}
else if (~(~0 << 5) == e) // inf, snan, qnan
{
return (s << 31) | ~(~0 << 8) << 23| (m << 13);
}
return (s << 31) | ((e - 15 + 127) << 23) | (m << 13); // norm
}
static U16 Convert_Float_To_Half(float f)
{
// 1s5e10m -> 1s8e23m
const U32 iFloat = *(U32*)&f; // Convert float to U32
if (f != f)
{
return (U16)(iFloat | HLF_QNaN_BITZS); // +QNaN, -QNaN