Add some external dependencies.

This commit is contained in:
Ignacio
2017-02-08 11:42:25 -08:00
parent 1004d5d5b5
commit d7612a3b67
64 changed files with 38084 additions and 1 deletions

58
extern/EtcLib/Etc/Etc.cpp vendored Normal file
View File

@ -0,0 +1,58 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "EtcConfig.h"
#include "Etc.h"
#include <string.h>
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
// C-style inteface to the encoder
//
void Encode(float *a_pafSourceRGBA,
unsigned int a_uiSourceWidth,
unsigned int a_uiSourceHeight,
Image::Format a_format,
ErrorMetric a_eErrMetric,
float a_fEffort,
unsigned int a_uiJobs,
unsigned int a_uiMaxJobs,
unsigned char **a_ppaucEncodingBits,
unsigned int *a_puiEncodingBitsBytes,
unsigned int *a_puiExtendedWidth,
unsigned int *a_puiExtendedHeight,
int *a_piEncodingTime_ms, bool a_bVerboseOutput)
{
Image image(a_pafSourceRGBA, a_uiSourceWidth,
a_uiSourceHeight,
a_eErrMetric);
image.m_bVerboseOutput = a_bVerboseOutput;
image.Encode(a_format, a_eErrMetric, a_fEffort, a_uiJobs, a_uiMaxJobs);
*a_ppaucEncodingBits = image.GetEncodingBits();
*a_puiEncodingBitsBytes = image.GetEncodingBitsBytes();
*a_puiExtendedWidth = image.GetExtendedWidth();
*a_puiExtendedHeight = image.GetExtendedHeight();
*a_piEncodingTime_ms = image.GetEncodingTimeMs();
}
// ----------------------------------------------------------------------------------------------------
//
}

47
extern/EtcLib/Etc/Etc.h vendored Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "EtcConfig.h"
#include "EtcImage.h"
#include "EtcColor.h"
#include "EtcErrorMetric.h"
#define ETCCOMP_MIN_EFFORT_LEVEL (0.0f)
#define ETCCOMP_DEFAULT_EFFORT_LEVEL (40.0f)
#define ETCCOMP_MAX_EFFORT_LEVEL (100.0f)
namespace Etc
{
class Block4x4EncodingBits;
// C-style inteface to the encoder
void Encode(float *a_pafSourceRGBA,
unsigned int a_uiSourceWidth,
unsigned int a_uiSourceHeight,
Image::Format a_format,
ErrorMetric a_eErrMetric,
float a_fEffort,
unsigned int a_uiJobs,
unsigned int a_uimaxJobs,
unsigned char **a_ppaucEncodingBits,
unsigned int *a_puiEncodingBitsBytes,
unsigned int *a_puiExtendedWidth,
unsigned int *a_puiExtendedHeight,
int *a_piEncodingTime_ms, bool a_bVerboseOutput = false);
}

64
extern/EtcLib/Etc/EtcColor.h vendored Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <math.h>
namespace Etc
{
inline float LogToLinear(float a_fLog)
{
static const float ALPHA = 0.055f;
static const float ONE_PLUS_ALPHA = 1.0f + ALPHA;
if (a_fLog <= 0.04045f)
{
return a_fLog / 12.92f;
}
else
{
return powf((a_fLog + ALPHA) / ONE_PLUS_ALPHA, 2.4f);
}
}
inline float LinearToLog(float &a_fLinear)
{
static const float ALPHA = 0.055f;
static const float ONE_PLUS_ALPHA = 1.0f + ALPHA;
if (a_fLinear <= 0.0031308f)
{
return 12.92f * a_fLinear;
}
else
{
return ONE_PLUS_ALPHA * powf(a_fLinear, (1.0f/2.4f)) - ALPHA;
}
}
class ColorR8G8B8A8
{
public:
unsigned char ucR;
unsigned char ucG;
unsigned char ucB;
unsigned char ucA;
};
}

321
extern/EtcLib/Etc/EtcColorFloatRGBA.h vendored Normal file
View File

@ -0,0 +1,321 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "EtcConfig.h"
#include "EtcColor.h"
#include <math.h>
namespace Etc
{
class ColorFloatRGBA
{
public:
ColorFloatRGBA(void)
{
fR = fG = fB = fA = 0.0f;
}
ColorFloatRGBA(float a_fR, float a_fG, float a_fB, float a_fA)
{
fR = a_fR;
fG = a_fG;
fB = a_fB;
fA = a_fA;
}
inline ColorFloatRGBA operator+(ColorFloatRGBA& a_rfrgba)
{
ColorFloatRGBA frgba;
frgba.fR = fR + a_rfrgba.fR;
frgba.fG = fG + a_rfrgba.fG;
frgba.fB = fB + a_rfrgba.fB;
frgba.fA = fA + a_rfrgba.fA;
return frgba;
}
inline ColorFloatRGBA operator+(float a_f)
{
ColorFloatRGBA frgba;
frgba.fR = fR + a_f;
frgba.fG = fG + a_f;
frgba.fB = fB + a_f;
frgba.fA = fA;
return frgba;
}
inline ColorFloatRGBA operator-(float a_f)
{
ColorFloatRGBA frgba;
frgba.fR = fR - a_f;
frgba.fG = fG - a_f;
frgba.fB = fB - a_f;
frgba.fA = fA;
return frgba;
}
inline ColorFloatRGBA operator-(ColorFloatRGBA& a_rfrgba)
{
ColorFloatRGBA frgba;
frgba.fR = fR - a_rfrgba.fR;
frgba.fG = fG - a_rfrgba.fG;
frgba.fB = fB - a_rfrgba.fB;
frgba.fA = fA - a_rfrgba.fA;
return frgba;
}
inline ColorFloatRGBA operator*(float a_f)
{
ColorFloatRGBA frgba;
frgba.fR = fR * a_f;
frgba.fG = fG * a_f;
frgba.fB = fB * a_f;
frgba.fA = fA;
return frgba;
}
inline ColorFloatRGBA ScaleRGB(float a_f)
{
ColorFloatRGBA frgba;
frgba.fR = a_f * fR;
frgba.fG = a_f * fG;
frgba.fB = a_f * fB;
frgba.fA = fA;
return frgba;
}
inline ColorFloatRGBA RoundRGB(void)
{
ColorFloatRGBA frgba;
frgba.fR = roundf(fR);
frgba.fG = roundf(fG);
frgba.fB = roundf(fB);
return frgba;
}
inline ColorFloatRGBA ToLinear()
{
ColorFloatRGBA frgbaLinear;
frgbaLinear.fR = LogToLinear(fR);
frgbaLinear.fG = LogToLinear(fG);
frgbaLinear.fB = LogToLinear(fB);
frgbaLinear.fA = fA;
return frgbaLinear;
}
inline ColorFloatRGBA ToLog(void)
{
ColorFloatRGBA frgbaLog;
frgbaLog.fR = LinearToLog(fR);
frgbaLog.fG = LinearToLog(fG);
frgbaLog.fB = LinearToLog(fB);
frgbaLog.fA = fA;
return frgbaLog;
}
inline static ColorFloatRGBA ConvertFromRGBA8(unsigned char a_ucR,
unsigned char a_ucG, unsigned char a_ucB, unsigned char a_ucA)
{
ColorFloatRGBA frgba;
frgba.fR = (float)a_ucR / 255.0f;
frgba.fG = (float)a_ucG / 255.0f;
frgba.fB = (float)a_ucB / 255.0f;
frgba.fA = (float)a_ucA / 255.0f;
return frgba;
}
inline static ColorFloatRGBA ConvertFromRGB4(unsigned char a_ucR4,
unsigned char a_ucG4,
unsigned char a_ucB4)
{
ColorFloatRGBA frgba;
unsigned char ucR8 = (unsigned char)((a_ucR4 << 4) + a_ucR4);
unsigned char ucG8 = (unsigned char)((a_ucG4 << 4) + a_ucG4);
unsigned char ucB8 = (unsigned char)((a_ucB4 << 4) + a_ucB4);
frgba.fR = (float)ucR8 / 255.0f;
frgba.fG = (float)ucG8 / 255.0f;
frgba.fB = (float)ucB8 / 255.0f;
frgba.fA = 1.0f;
return frgba;
}
inline static ColorFloatRGBA ConvertFromRGB5(unsigned char a_ucR5,
unsigned char a_ucG5,
unsigned char a_ucB5)
{
ColorFloatRGBA frgba;
unsigned char ucR8 = (unsigned char)((a_ucR5 << 3) + (a_ucR5 >> 2));
unsigned char ucG8 = (unsigned char)((a_ucG5 << 3) + (a_ucG5 >> 2));
unsigned char ucB8 = (unsigned char)((a_ucB5 << 3) + (a_ucB5 >> 2));
frgba.fR = (float)ucR8 / 255.0f;
frgba.fG = (float)ucG8 / 255.0f;
frgba.fB = (float)ucB8 / 255.0f;
frgba.fA = 1.0f;
return frgba;
}
inline static ColorFloatRGBA ConvertFromR6G7B6(unsigned char a_ucR6,
unsigned char a_ucG7,
unsigned char a_ucB6)
{
ColorFloatRGBA frgba;
unsigned char ucR8 = (unsigned char)((a_ucR6 << 2) + (a_ucR6 >> 4));
unsigned char ucG8 = (unsigned char)((a_ucG7 << 1) + (a_ucG7 >> 6));
unsigned char ucB8 = (unsigned char)((a_ucB6 << 2) + (a_ucB6 >> 4));
frgba.fR = (float)ucR8 / 255.0f;
frgba.fG = (float)ucG8 / 255.0f;
frgba.fB = (float)ucB8 / 255.0f;
frgba.fA = 1.0f;
return frgba;
}
// quantize to 4 bits, expand to 8 bits
inline ColorFloatRGBA QuantizeR4G4B4(void) const
{
ColorFloatRGBA frgba = *this;
// quantize to 4 bits
frgba = frgba.ClampRGB().ScaleRGB(15.0f).RoundRGB();
unsigned int uiR4 = (unsigned int)frgba.fR;
unsigned int uiG4 = (unsigned int)frgba.fG;
unsigned int uiB4 = (unsigned int)frgba.fB;
// expand to 8 bits
frgba.fR = (float) ((uiR4 << 4) + uiR4);
frgba.fG = (float) ((uiG4 << 4) + uiG4);
frgba.fB = (float) ((uiB4 << 4) + uiB4);
frgba = frgba.ScaleRGB(1.0f/255.0f);
return frgba;
}
// quantize to 5 bits, expand to 8 bits
inline ColorFloatRGBA QuantizeR5G5B5(void) const
{
ColorFloatRGBA frgba = *this;
// quantize to 5 bits
frgba = frgba.ClampRGB().ScaleRGB(31.0f).RoundRGB();
unsigned int uiR5 = (unsigned int)frgba.fR;
unsigned int uiG5 = (unsigned int)frgba.fG;
unsigned int uiB5 = (unsigned int)frgba.fB;
// expand to 8 bits
frgba.fR = (float)((uiR5 << 3) + (uiR5 >> 2));
frgba.fG = (float)((uiG5 << 3) + (uiG5 >> 2));
frgba.fB = (float)((uiB5 << 3) + (uiB5 >> 2));
frgba = frgba.ScaleRGB(1.0f / 255.0f);
return frgba;
}
// quantize to 6/7/6 bits, expand to 8 bits
inline ColorFloatRGBA QuantizeR6G7B6(void) const
{
ColorFloatRGBA frgba = *this;
// quantize to 6/7/6 bits
ColorFloatRGBA frgba6 = frgba.ClampRGB().ScaleRGB(63.0f).RoundRGB();
ColorFloatRGBA frgba7 = frgba.ClampRGB().ScaleRGB(127.0f).RoundRGB();
unsigned int uiR6 = (unsigned int)frgba6.fR;
unsigned int uiG7 = (unsigned int)frgba7.fG;
unsigned int uiB6 = (unsigned int)frgba6.fB;
// expand to 8 bits
frgba.fR = (float)((uiR6 << 2) + (uiR6 >> 4));
frgba.fG = (float)((uiG7 << 1) + (uiG7 >> 6));
frgba.fB = (float)((uiB6 << 2) + (uiB6 >> 4));
frgba = frgba.ScaleRGB(1.0f / 255.0f);
return frgba;
}
inline ColorFloatRGBA ClampRGB(void)
{
ColorFloatRGBA frgba = *this;
if (frgba.fR < 0.0f) { frgba.fR = 0.0f; }
if (frgba.fR > 1.0f) { frgba.fR = 1.0f; }
if (frgba.fG < 0.0f) { frgba.fG = 0.0f; }
if (frgba.fG > 1.0f) { frgba.fG = 1.0f; }
if (frgba.fB < 0.0f) { frgba.fB = 0.0f; }
if (frgba.fB > 1.0f) { frgba.fB = 1.0f; }
return frgba;
}
inline ColorFloatRGBA ClampRGBA(void)
{
ColorFloatRGBA frgba = *this;
if (frgba.fR < 0.0f) { frgba.fR = 0.0f; }
if (frgba.fR > 1.0f) { frgba.fR = 1.0f; }
if (frgba.fG < 0.0f) { frgba.fG = 0.0f; }
if (frgba.fG > 1.0f) { frgba.fG = 1.0f; }
if (frgba.fB < 0.0f) { frgba.fB = 0.0f; }
if (frgba.fB > 1.0f) { frgba.fB = 1.0f; }
if (frgba.fA < 0.0f) { frgba.fA = 0.0f; }
if (frgba.fA > 1.0f) { frgba.fA = 1.0f; }
return frgba;
}
inline int IntRed(float a_fScale)
{
return (int)roundf(fR * a_fScale);
}
inline int IntGreen(float a_fScale)
{
return (int)roundf(fG * a_fScale);
}
inline int IntBlue(float a_fScale)
{
return (int)roundf(fB * a_fScale);
}
inline int IntAlpha(float a_fScale)
{
return (int)roundf(fA * a_fScale);
}
float fR, fG, fB, fA;
};
}

67
extern/EtcLib/Etc/EtcConfig.h vendored Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifdef _WIN32
#define ETC_WINDOWS (1)
#else
#define ETC_WINDOWS (0)
#endif
#if __APPLE__
#define ETC_OSX (1)
#else
#define ETC_OSX (0)
#endif
#if __unix__
#define ETC_UNIX (1)
#else
#define ETC_UNIX (0)
#endif
// short names for common types
#include <stdint.h>
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef float f32;
typedef double f64;
// Keep asserts enabled in release builds during development
#undef NDEBUG
// 0=disable. stb_image can be used if you need to compress
//other image formats like jpg
#define USE_STB_IMAGE_LOAD 0
#if ETC_WINDOWS
#include <SDKDDKVer.h>
#define _CRT_SECURE_NO_WARNINGS (1)
#include <tchar.h>
#endif
#include <stdio.h>

685
extern/EtcLib/Etc/EtcImage.cpp vendored Normal file
View File

@ -0,0 +1,685 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
EtcImage.cpp
Image is an array of 4x4 blocks that represent the encoding of the source image
*/
#include "EtcConfig.h"
#include <stdlib.h>
#include "EtcImage.h"
#include "Etc.h"
#include "EtcBlock4x4.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcSortedBlockList.h"
#if ETC_WINDOWS
#include <windows.h>
#endif
#include <ctime>
#include <chrono>
#include <future>
#include <stdio.h>
#include <string.h>
#include <assert.h>
// fix conflict with Block4x4::AlphaMix
#ifdef OPAQUE
#undef OPAQUE
#endif
#ifdef TRANSPARENT
#undef TRANSPARENT
#endif
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
//
Image::Image(void)
{
m_encodingStatus = EncodingStatus::SUCCESS;
m_warningsToCapture = EncodingStatus::SUCCESS;
m_pafrgbaSource = nullptr;
m_pablock = nullptr;
m_encodingbitsformat = Block4x4EncodingBits::Format::UNKNOWN;
m_uiEncodingBitsBytes = 0;
m_paucEncodingBits = nullptr;
m_format = Format::UNKNOWN;
m_iNumOpaquePixels = 0;
m_iNumTranslucentPixels = 0;
m_iNumTransparentPixels = 0;
}
// ----------------------------------------------------------------------------------------------------
// constructor using source image
// used to set state before Encode() is called
//
Image::Image(float *a_pafSourceRGBA, unsigned int a_uiSourceWidth,
unsigned int a_uiSourceHeight,
ErrorMetric a_errormetric)
{
m_encodingStatus = EncodingStatus::SUCCESS;
m_warningsToCapture = EncodingStatus::SUCCESS;
m_pafrgbaSource = (ColorFloatRGBA *) a_pafSourceRGBA;
m_uiSourceWidth = a_uiSourceWidth;
m_uiSourceHeight = a_uiSourceHeight;
m_uiExtendedWidth = CalcExtendedDimension((unsigned short)m_uiSourceWidth);
m_uiExtendedHeight = CalcExtendedDimension((unsigned short)m_uiSourceHeight);
m_uiBlockColumns = m_uiExtendedWidth >> 2;
m_uiBlockRows = m_uiExtendedHeight >> 2;
m_pablock = new Block4x4[GetNumberOfBlocks()];
assert(m_pablock);
m_format = Format::UNKNOWN;
m_encodingbitsformat = Block4x4EncodingBits::Format::UNKNOWN;
m_uiEncodingBitsBytes = 0;
m_paucEncodingBits = nullptr;
m_errormetric = a_errormetric;
m_fEffort = 0.0f;
m_iEncodeTime_ms = -1;
m_iNumOpaquePixels = 0;
m_iNumTranslucentPixels = 0;
m_iNumTransparentPixels = 0;
m_bVerboseOutput = false;
}
// ----------------------------------------------------------------------------------------------------
// constructor using encoding bits
// recreates encoding state using a previously encoded image
//
Image::Image(Format a_format,
unsigned int a_uiSourceWidth, unsigned int a_uiSourceHeight,
unsigned char *a_paucEncidingBits, unsigned int a_uiEncodingBitsBytes,
Image *a_pimageSource, ErrorMetric a_errormetric)
{
m_encodingStatus = EncodingStatus::SUCCESS;
m_pafrgbaSource = nullptr;
m_uiSourceWidth = a_uiSourceWidth;
m_uiSourceHeight = a_uiSourceHeight;
m_uiExtendedWidth = CalcExtendedDimension((unsigned short)m_uiSourceWidth);
m_uiExtendedHeight = CalcExtendedDimension((unsigned short)m_uiSourceHeight);
m_uiBlockColumns = m_uiExtendedWidth >> 2;
m_uiBlockRows = m_uiExtendedHeight >> 2;
unsigned int uiBlocks = GetNumberOfBlocks();
m_pablock = new Block4x4[uiBlocks];
assert(m_pablock);
m_format = a_format;
m_iNumOpaquePixels = 0;
m_iNumTranslucentPixels = 0;
m_iNumTransparentPixels = 0;
m_encodingbitsformat = DetermineEncodingBitsFormat(m_format);
if (m_encodingbitsformat == Block4x4EncodingBits::Format::UNKNOWN)
{
AddToEncodingStatus(ERROR_UNKNOWN_FORMAT);
return;
}
m_uiEncodingBitsBytes = a_uiEncodingBitsBytes;
m_paucEncodingBits = a_paucEncidingBits;
m_errormetric = a_errormetric;
m_fEffort = 0.0f;
m_bVerboseOutput = false;
m_iEncodeTime_ms = -1;
unsigned char *paucEncodingBits = m_paucEncodingBits;
unsigned int uiEncodingBitsBytesPerBlock = Block4x4EncodingBits::GetBytesPerBlock(m_encodingbitsformat);
unsigned int uiH = 0;
unsigned int uiV = 0;
for (unsigned int uiBlock = 0; uiBlock < uiBlocks; uiBlock++)
{
m_pablock[uiBlock].InitFromEtcEncodingBits(a_format, uiH, uiV, paucEncodingBits,
a_pimageSource, a_errormetric);
paucEncodingBits += uiEncodingBitsBytesPerBlock;
uiH += 4;
if (uiH >= m_uiSourceWidth)
{
uiH = 0;
uiV += 4;
}
}
}
// ----------------------------------------------------------------------------------------------------
//
Image::~Image(void)
{
if (m_pablock != nullptr)
{
delete[] m_pablock;
m_pablock = nullptr;
}
/*if (m_paucEncodingBits != nullptr)
{
delete[] m_paucEncodingBits;
m_paucEncodingBits = nullptr;
}*/
}
// ----------------------------------------------------------------------------------------------------
// encode an image
// create a set of encoding bits that conforms to a_format
// find best fit using a_errormetric
// explore a range of possible encodings based on a_fEffort (range = [0:100])
// speed up process using a_uiJobs as the number of process threads (a_uiJobs must not excede a_uiMaxJobs)
//
Image::EncodingStatus Image::Encode(Format a_format, ErrorMetric a_errormetric, float a_fEffort, unsigned int a_uiJobs, unsigned int a_uiMaxJobs)
{
auto start = std::chrono::steady_clock::now();
m_encodingStatus = EncodingStatus::SUCCESS;
m_format = a_format;
m_errormetric = a_errormetric;
m_fEffort = a_fEffort;
if (m_errormetric < 0 || m_errormetric > ERROR_METRICS)
{
AddToEncodingStatus(ERROR_UNKNOWN_ERROR_METRIC);
return m_encodingStatus;
}
if (m_fEffort < ETCCOMP_MIN_EFFORT_LEVEL)
{
AddToEncodingStatus(WARNING_EFFORT_OUT_OF_RANGE);
m_fEffort = ETCCOMP_MIN_EFFORT_LEVEL;
}
else if (m_fEffort > ETCCOMP_MAX_EFFORT_LEVEL)
{
AddToEncodingStatus(WARNING_EFFORT_OUT_OF_RANGE);
m_fEffort = ETCCOMP_MAX_EFFORT_LEVEL;
}
if (a_uiJobs < 1)
{
a_uiJobs = 1;
AddToEncodingStatus(WARNING_JOBS_OUT_OF_RANGE);
}
else if (a_uiJobs > a_uiMaxJobs)
{
a_uiJobs = a_uiMaxJobs;
AddToEncodingStatus(WARNING_JOBS_OUT_OF_RANGE);
}
m_encodingbitsformat = DetermineEncodingBitsFormat(m_format);
if (m_encodingbitsformat == Block4x4EncodingBits::Format::UNKNOWN)
{
AddToEncodingStatus(ERROR_UNKNOWN_FORMAT);
return m_encodingStatus;
}
assert(m_paucEncodingBits == nullptr);
m_uiEncodingBitsBytes = GetNumberOfBlocks() * Block4x4EncodingBits::GetBytesPerBlock(m_encodingbitsformat);
m_paucEncodingBits = new unsigned char[m_uiEncodingBitsBytes];
InitBlocksAndBlockSorter();
std::future<void> *handle = new std::future<void>[a_uiMaxJobs];
unsigned int uiNumThreadsNeeded = 0;
unsigned int uiUnfinishedBlocks = GetNumberOfBlocks();
uiNumThreadsNeeded = (uiUnfinishedBlocks < a_uiJobs) ? uiUnfinishedBlocks : a_uiJobs;
for (int i = 0; i < (int)uiNumThreadsNeeded - 1; i++)
{
handle[i] = async(std::launch::async, &Image::RunFirstPass, this, i, uiNumThreadsNeeded);
}
RunFirstPass(uiNumThreadsNeeded - 1, uiNumThreadsNeeded);
for (int i = 0; i < (int)uiNumThreadsNeeded - 1; i++)
{
handle[i].get();
}
// perform effort-based encoding
if (m_fEffort > ETCCOMP_MIN_EFFORT_LEVEL)
{
unsigned int uiFinishedBlocks = 0;
unsigned int uiTotalEffortBlocks = static_cast<unsigned int>(roundf(0.01f * m_fEffort * GetNumberOfBlocks()));
if (m_bVerboseOutput)
{
printf("effortblocks = %d\n", uiTotalEffortBlocks);
}
unsigned int uiPass = 0;
while (1)
{
if (m_bVerboseOutput)
{
uiPass++;
printf("pass %u\n", uiPass);
}
m_psortedblocklist->Sort();
uiUnfinishedBlocks = m_psortedblocklist->GetNumberOfSortedBlocks();
uiFinishedBlocks = GetNumberOfBlocks() - uiUnfinishedBlocks;
if (m_bVerboseOutput)
{
printf(" %u unfinished blocks\n", uiUnfinishedBlocks);
// m_psortedblocklist->Print();
}
//stop enocding when we did enough to satify the effort percentage
if (uiFinishedBlocks >= uiTotalEffortBlocks)
{
if (m_bVerboseOutput)
{
printf("Finished %d Blocks out of %d\n", uiFinishedBlocks, uiTotalEffortBlocks);
}
break;
}
unsigned int uiIteratedBlocks = 0;
unsigned int blocksToIterateThisPass = (uiTotalEffortBlocks - uiFinishedBlocks);
uiNumThreadsNeeded = (uiUnfinishedBlocks < a_uiJobs) ? uiUnfinishedBlocks : a_uiJobs;
if (uiNumThreadsNeeded <= 1)
{
//since we already how many blocks each thread will process
//cap the thread limit to do the proper amount of work, and not more
uiIteratedBlocks = IterateThroughWorstBlocks(blocksToIterateThisPass, 0, 1);
}
else
{
//we have a lot of work to do, so lets multi thread it
std::future<unsigned int> *handleToBlockEncoders = new std::future<unsigned int>[uiNumThreadsNeeded-1];
for (int i = 0; i < (int)uiNumThreadsNeeded - 1; i++)
{
handleToBlockEncoders[i] = async(std::launch::async, &Image::IterateThroughWorstBlocks, this, blocksToIterateThisPass, i, uiNumThreadsNeeded);
}
uiIteratedBlocks = IterateThroughWorstBlocks(blocksToIterateThisPass, uiNumThreadsNeeded - 1, uiNumThreadsNeeded);
for (int i = 0; i < (int)uiNumThreadsNeeded - 1; i++)
{
uiIteratedBlocks += handleToBlockEncoders[i].get();
}
delete[] handleToBlockEncoders;
}
if (m_bVerboseOutput)
{
printf(" %u iterated blocks\n", uiIteratedBlocks);
}
}
}
// generate Etc2-compatible bit-format 4x4 blocks
for (int i = 0; i < (int)a_uiJobs - 1; i++)
{
handle[i] = async(std::launch::async, &Image::SetEncodingBits, this, i, a_uiJobs);
}
SetEncodingBits(a_uiJobs - 1, a_uiJobs);
for (int i = 0; i < (int)a_uiJobs - 1; i++)
{
handle[i].get();
}
auto end = std::chrono::steady_clock::now();
std::chrono::milliseconds elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
m_iEncodeTime_ms = (int)elapsed.count();
delete[] handle;
delete m_psortedblocklist;
return m_encodingStatus;
}
// ----------------------------------------------------------------------------------------------------
// iterate the encoding thru the blocks with the worst error
// stop when a_uiMaxBlocks blocks have been iterated
// split the blocks between the process threads using a_uiMultithreadingOffset and a_uiMultithreadingStride
//
unsigned int Image::IterateThroughWorstBlocks(unsigned int a_uiMaxBlocks,
unsigned int a_uiMultithreadingOffset,
unsigned int a_uiMultithreadingStride)
{
assert(a_uiMultithreadingStride > 0);
unsigned int uiIteratedBlocks = a_uiMultithreadingOffset;
SortedBlockList::Link *plink = m_psortedblocklist->GetLinkToFirstBlock();
for (plink = plink->Advance(a_uiMultithreadingOffset);
plink != nullptr;
plink = plink->Advance(a_uiMultithreadingStride) )
{
if (uiIteratedBlocks >= a_uiMaxBlocks)
{
break;
}
plink->GetBlock()->PerformEncodingIteration(m_fEffort);
uiIteratedBlocks += a_uiMultithreadingStride;
}
return uiIteratedBlocks;
}
// ----------------------------------------------------------------------------------------------------
// determine which warnings to check for during Encode() based on encoding format
//
void Image::FindEncodingWarningTypesForCurFormat()
{
TrackEncodingWarning(WARNING_ALL_TRANSPARENT_PIXELS);
TrackEncodingWarning(WARNING_SOME_RGBA_NOT_0_TO_1);
switch (m_format)
{
case Image::Format::ETC1:
case Image::Format::RGB8:
case Image::Format::SRGB8:
TrackEncodingWarning(WARNING_SOME_NON_OPAQUE_PIXELS);
TrackEncodingWarning(WARNING_SOME_TRANSLUCENT_PIXELS);
break;
case Image::Format::RGB8A1:
case Image::Format::SRGB8A1:
TrackEncodingWarning(WARNING_SOME_TRANSLUCENT_PIXELS);
TrackEncodingWarning(WARNING_ALL_OPAQUE_PIXELS);
break;
case Image::Format::RGBA8:
case Image::Format::SRGBA8:
TrackEncodingWarning(WARNING_ALL_OPAQUE_PIXELS);
break;
case Image::Format::R11:
case Image::Format::SIGNED_R11:
TrackEncodingWarning(WARNING_SOME_NON_OPAQUE_PIXELS);
TrackEncodingWarning(WARNING_SOME_TRANSLUCENT_PIXELS);
TrackEncodingWarning(WARNING_SOME_GREEN_VALUES_ARE_NOT_ZERO);
TrackEncodingWarning(WARNING_SOME_BLUE_VALUES_ARE_NOT_ZERO);
break;
case Image::Format::RG11:
case Image::Format::SIGNED_RG11:
TrackEncodingWarning(WARNING_SOME_NON_OPAQUE_PIXELS);
TrackEncodingWarning(WARNING_SOME_TRANSLUCENT_PIXELS);
TrackEncodingWarning(WARNING_SOME_BLUE_VALUES_ARE_NOT_ZERO);
break;
case Image::Format::FORMATS:
case Image::Format::UNKNOWN:
default:
assert(0);
break;
}
}
// ----------------------------------------------------------------------------------------------------
// examine source pixels to check for warnings
//
void Image::FindAndSetEncodingWarnings()
{
int numPixels = (m_uiBlockRows * 4) * (m_uiBlockColumns * 4);
if (m_iNumOpaquePixels == numPixels)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_ALL_OPAQUE_PIXELS);
}
if (m_iNumOpaquePixels < numPixels)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_SOME_NON_OPAQUE_PIXELS);
}
if (m_iNumTranslucentPixels > 0)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_SOME_TRANSLUCENT_PIXELS);
}
if (m_iNumTransparentPixels == numPixels)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_ALL_TRANSPARENT_PIXELS);
}
if (m_numColorValues.fB > 0.0f)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_SOME_BLUE_VALUES_ARE_NOT_ZERO);
}
if (m_numColorValues.fG > 0.0f)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_SOME_GREEN_VALUES_ARE_NOT_ZERO);
}
if (m_numOutOfRangeValues.fR > 0.0f || m_numOutOfRangeValues.fG > 0.0f)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_SOME_RGBA_NOT_0_TO_1);
}
if (m_numOutOfRangeValues.fB > 0.0f || m_numOutOfRangeValues.fA > 0.0f)
{
AddToEncodingStatusIfSignfigant(Image::EncodingStatus::WARNING_SOME_RGBA_NOT_0_TO_1);
}
}
// ----------------------------------------------------------------------------------------------------
// return a string name for a given image format
//
const char * Image::EncodingFormatToString(Image::Format a_format)
{
switch (a_format)
{
case Image::Format::ETC1:
return "ETC1";
case Image::Format::RGB8:
return "RGB8";
case Image::Format::SRGB8:
return "SRGB8";
case Image::Format::RGB8A1:
return "RGB8A1";
case Image::Format::SRGB8A1:
return "SRGB8A1";
case Image::Format::RGBA8:
return "RGBA8";
case Image::Format::SRGBA8:
return "SRGBA8";
case Image::Format::R11:
return "R11";
case Image::Format::SIGNED_R11:
return "SIGNED_R11";
case Image::Format::RG11:
return "RG11";
case Image::Format::SIGNED_RG11:
return "SIGNED_RG11";
case Image::Format::FORMATS:
case Image::Format::UNKNOWN:
default:
return "UNKNOWN";
}
}
// ----------------------------------------------------------------------------------------------------
// return a string name for the image's format
//
const char * Image::EncodingFormatToString(void)
{
return EncodingFormatToString(m_format);
}
// ----------------------------------------------------------------------------------------------------
// init image blocks prior to encoding
// init block sorter for subsequent sortings
// check for encoding warnings
//
void Image::InitBlocksAndBlockSorter(void)
{
FindEncodingWarningTypesForCurFormat();
// init each block
Block4x4 *pblock = m_pablock;
unsigned char *paucEncodingBits = m_paucEncodingBits;
for (unsigned int uiBlockRow = 0; uiBlockRow < m_uiBlockRows; uiBlockRow++)
{
unsigned int uiBlockV = uiBlockRow * 4;
for (unsigned int uiBlockColumn = 0; uiBlockColumn < m_uiBlockColumns; uiBlockColumn++)
{
unsigned int uiBlockH = uiBlockColumn * 4;
pblock->InitFromSource(this, uiBlockH, uiBlockV, paucEncodingBits, m_errormetric);
paucEncodingBits += Block4x4EncodingBits::GetBytesPerBlock(m_encodingbitsformat);
pblock++;
}
}
FindAndSetEncodingWarnings();
// init block sorter
{
m_psortedblocklist = new SortedBlockList(GetNumberOfBlocks(), 100);
for (unsigned int uiBlock = 0; uiBlock < GetNumberOfBlocks(); uiBlock++)
{
pblock = &m_pablock[uiBlock];
m_psortedblocklist->AddBlock(pblock);
}
}
}
// ----------------------------------------------------------------------------------------------------
// run the first pass of the encoder
// the encoder generally finds a reasonable, fast encoding
// this is run on all blocks regardless of effort to ensure that all blocks have a valid encoding
//
void Image::RunFirstPass(unsigned int a_uiMultithreadingOffset, unsigned int a_uiMultithreadingStride)
{
assert(a_uiMultithreadingStride > 0);
for (unsigned int uiBlock = a_uiMultithreadingOffset;
uiBlock < GetNumberOfBlocks();
uiBlock += a_uiMultithreadingStride)
{
Block4x4 *pblock = &m_pablock[uiBlock];
pblock->PerformEncodingIteration(m_fEffort);
}
}
// ----------------------------------------------------------------------------------------------------
// set the encoding bits (for the output file) based on the best encoding for each block
//
void Image::SetEncodingBits(unsigned int a_uiMultithreadingOffset,
unsigned int a_uiMultithreadingStride)
{
assert(a_uiMultithreadingStride > 0);
for (unsigned int uiBlock = a_uiMultithreadingOffset;
uiBlock < GetNumberOfBlocks();
uiBlock += a_uiMultithreadingStride)
{
Block4x4 *pblock = &m_pablock[uiBlock];
pblock->SetEncodingBitsFromEncoding();
}
}
// ----------------------------------------------------------------------------------------------------
// return the image error
// image error is the sum of all block errors
//
float Image::GetError(void)
{
float fError = 0.0f;
for (unsigned int uiBlock = 0; uiBlock < GetNumberOfBlocks(); uiBlock++)
{
Block4x4 *pblock = &m_pablock[uiBlock];
fError += pblock->GetError();
}
return fError;
}
// ----------------------------------------------------------------------------------------------------
// determine the encoding bits format based on the encoding format
// the encoding bits format is a family of bit encodings that are shared across various encoding formats
//
Block4x4EncodingBits::Format Image::DetermineEncodingBitsFormat(Format a_format)
{
Block4x4EncodingBits::Format encodingbitsformat;
// determine encoding bits format from image format
switch (a_format)
{
case Format::ETC1:
case Format::RGB8:
case Format::SRGB8:
encodingbitsformat = Block4x4EncodingBits::Format::RGB8;
break;
case Format::RGBA8:
case Format::SRGBA8:
encodingbitsformat = Block4x4EncodingBits::Format::RGBA8;
break;
case Format::R11:
case Format::SIGNED_R11:
encodingbitsformat = Block4x4EncodingBits::Format::R11;
break;
case Format::RG11:
case Format::SIGNED_RG11:
encodingbitsformat = Block4x4EncodingBits::Format::RG11;
break;
case Format::RGB8A1:
case Format::SRGB8A1:
encodingbitsformat = Block4x4EncodingBits::Format::RGB8A1;
break;
default:
encodingbitsformat = Block4x4EncodingBits::Format::UNKNOWN;
break;
}
return encodingbitsformat;
}
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

249
extern/EtcLib/Etc/EtcImage.h vendored Normal file
View File

@ -0,0 +1,249 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
//#include "Etc.h"
#include "EtcColorFloatRGBA.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcErrorMetric.h"
namespace Etc
{
class Block4x4;
class EncoderSpec;
class SortedBlockList;
class Image
{
public:
//the differnt warning and errors that can come up during encoding
enum EncodingStatus
{
SUCCESS = 0,
//
WARNING_THRESHOLD = 1 << 0,
//
WARNING_EFFORT_OUT_OF_RANGE = 1 << 1,
WARNING_JOBS_OUT_OF_RANGE = 1 << 2,
WARNING_SOME_NON_OPAQUE_PIXELS = 1 << 3,//just for opaque formats, etc1, rgb8, r11, rg11
WARNING_ALL_OPAQUE_PIXELS = 1 << 4,
WARNING_ALL_TRANSPARENT_PIXELS = 1 << 5,
WARNING_SOME_TRANSLUCENT_PIXELS = 1 << 6,//just for rgb8A1
WARNING_SOME_RGBA_NOT_0_TO_1 = 1 << 7,
WARNING_SOME_BLUE_VALUES_ARE_NOT_ZERO = 1 << 8,
WARNING_SOME_GREEN_VALUES_ARE_NOT_ZERO = 1 << 9,
//
ERROR_THRESHOLD = 1 << 16,
//
ERROR_UNKNOWN_FORMAT = 1 << 17,
ERROR_UNKNOWN_ERROR_METRIC = 1 << 18,
ERROR_ZERO_WIDTH_OR_HEIGHT = 1 << 19,
//
};
enum class Format
{
UNKNOWN,
//
ETC1,
//
// ETC2 formats
RGB8,
SRGB8,
RGBA8,
SRGBA8,
R11,
SIGNED_R11,
RG11,
SIGNED_RG11,
RGB8A1,
SRGB8A1,
//
FORMATS,
//
DEFAULT = SRGB8
};
// constructor using source image
Image(float *a_pafSourceRGBA, unsigned int a_uiSourceWidth,
unsigned int a_uiSourceHeight,
ErrorMetric a_errormetric);
// constructor using encoding bits
Image(Format a_format,
unsigned int a_uiSourceWidth, unsigned int a_uiSourceHeight,
unsigned char *a_paucEncidingBits, unsigned int a_uiEncodingBitsBytes,
Image *a_pimageSource,
ErrorMetric a_errormetric);
~Image(void);
EncodingStatus Encode(Format a_format, ErrorMetric a_errormetric, float a_fEffort,
unsigned int a_uiJobs, unsigned int a_uiMaxJobs);
inline void AddToEncodingStatus(EncodingStatus a_encStatus)
{
m_encodingStatus = (EncodingStatus)((unsigned int)m_encodingStatus | (unsigned int)a_encStatus);
}
inline unsigned int GetSourceWidth(void)
{
return m_uiSourceWidth;
}
inline unsigned int GetSourceHeight(void)
{
return m_uiSourceHeight;
}
inline unsigned int GetExtendedWidth(void)
{
return m_uiExtendedWidth;
}
inline unsigned int GetExtendedHeight(void)
{
return m_uiExtendedHeight;
}
inline unsigned int GetNumberOfBlocks()
{
return m_uiBlockColumns * m_uiBlockRows;
}
inline Block4x4 * GetBlocks()
{
return m_pablock;
}
inline unsigned char * GetEncodingBits(void)
{
return m_paucEncodingBits;
}
inline unsigned int GetEncodingBitsBytes(void)
{
return m_uiEncodingBitsBytes;
}
inline int GetEncodingTimeMs(void)
{
return m_iEncodeTime_ms;
}
float GetError(void);
inline ColorFloatRGBA * GetSourcePixel(unsigned int a_uiH, unsigned int a_uiV)
{
if (a_uiH >= m_uiSourceWidth || a_uiV >= m_uiSourceHeight)
{
return nullptr;
}
return &m_pafrgbaSource[a_uiV*m_uiSourceWidth + a_uiH];
}
inline Format GetFormat(void)
{
return m_format;
}
static Block4x4EncodingBits::Format DetermineEncodingBitsFormat(Format a_format);
inline static unsigned short CalcExtendedDimension(unsigned short a_ushOriginalDimension)
{
return (unsigned short)((a_ushOriginalDimension + 3) & ~3);
}
inline ErrorMetric GetErrorMetric(void)
{
return m_errormetric;
}
static const char * EncodingFormatToString(Image::Format a_format);
const char * EncodingFormatToString(void);
//used to get basic information about the image data
int m_iNumOpaquePixels;
int m_iNumTranslucentPixels;
int m_iNumTransparentPixels;
ColorFloatRGBA m_numColorValues;
ColorFloatRGBA m_numOutOfRangeValues;
bool m_bVerboseOutput;
private:
//add a warning or error to check for while encoding
inline void TrackEncodingWarning(EncodingStatus a_encStatus)
{
m_warningsToCapture = (EncodingStatus)((unsigned int)m_warningsToCapture | (unsigned int)a_encStatus);
}
//report the warning if it is something we care about for this encoding
inline void AddToEncodingStatusIfSignfigant(EncodingStatus a_encStatus)
{
if ((EncodingStatus)((unsigned int)m_warningsToCapture & (unsigned int)a_encStatus) == a_encStatus)
{
AddToEncodingStatus(a_encStatus);
}
}
Image(void);
void FindEncodingWarningTypesForCurFormat();
void FindAndSetEncodingWarnings();
void InitBlocksAndBlockSorter(void);
void RunFirstPass(unsigned int a_uiMultithreadingOffset,
unsigned int a_uiMultithreadingStride);
void SetEncodingBits(unsigned int a_uiMultithreadingOffset,
unsigned int a_uiMultithreadingStride);
unsigned int IterateThroughWorstBlocks(unsigned int a_uiMaxBlocks,
unsigned int a_uiMultithreadingOffset,
unsigned int a_uiMultithreadingStride);
// inputs
ColorFloatRGBA *m_pafrgbaSource;
unsigned int m_uiSourceWidth;
unsigned int m_uiSourceHeight;
unsigned int m_uiExtendedWidth;
unsigned int m_uiExtendedHeight;
unsigned int m_uiBlockColumns;
unsigned int m_uiBlockRows;
// intermediate data
Block4x4 *m_pablock;
// encoding
Format m_format;
Block4x4EncodingBits::Format m_encodingbitsformat;
unsigned int m_uiEncodingBitsBytes; // for entire image
unsigned char *m_paucEncodingBits;
ErrorMetric m_errormetric;
float m_fEffort;
// stats
int m_iEncodeTime_ms;
SortedBlockList *m_psortedblocklist;
//this will hold any warning or errors that happen during encoding
EncodingStatus m_encodingStatus;
//these will be the warnings we are tracking
EncodingStatus m_warningsToCapture;
};
} // namespace Etc

64
extern/EtcLib/Etc/EtcMath.cpp vendored Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "EtcConfig.h"
#include "EtcMath.h"
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
// calculate the line that best fits the set of XY points contained in a_afX[] and a_afY[]
// use a_fSlope and a_fOffset to define that line
//
bool Regression(float a_afX[], float a_afY[], unsigned int a_Points,
float *a_fSlope, float *a_fOffset)
{
float fPoints = (float)a_Points;
float fSumX = 0.0f;
float fSumY = 0.0f;
float fSumXY = 0.0f;
float fSumX2 = 0.0f;
for (unsigned int uiPoint = 0; uiPoint < a_Points; uiPoint++)
{
fSumX += a_afX[uiPoint];
fSumY += a_afY[uiPoint];
fSumXY += a_afX[uiPoint] * a_afY[uiPoint];
fSumX2 += a_afX[uiPoint] * a_afX[uiPoint];
}
float fDivisor = fPoints*fSumX2 - fSumX*fSumX;
// if vertical line
if (fDivisor == 0.0f)
{
*a_fSlope = 0.0f;
*a_fOffset = 0.0f;
return true;
}
*a_fSlope = (fPoints*fSumXY - fSumX*fSumY) / fDivisor;
*a_fOffset = (fSumY - (*a_fSlope)*fSumX) / fPoints;
return false;
}
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

40
extern/EtcLib/Etc/EtcMath.h vendored Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright 2015 The Etc2Comp Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <math.h>
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
// return true if vertical line
bool Regression(float a_afX[], float a_afY[], unsigned int a_Points,
float *a_fSlope, float *a_fOffset);
inline float ConvertMSEToPSNR(float a_fMSE)
{
if (a_fMSE == 0.0f)
{
return INFINITY;
}
return 10.0f * log10f(1.0f / a_fMSE);
}
}