godot/thirdparty/etc2comp/EtcDifferentialTrys.cpp

174 lines
5.0 KiB
C++

/*
* 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.
*/
/*
EtcDifferentialTrys.cpp
Gathers the results of the various encoding trys for both halves of a 4x4 block for Differential mode
*/
#include "EtcConfig.h"
#include "EtcDifferentialTrys.h"
#include <assert.h>
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
// construct a list of trys (encoding attempts)
//
// a_frgbaColor1 is the basecolor for the first half
// a_frgbaColor2 is the basecolor for the second half
// a_pauiPixelMapping1 is the pixel order for the first half
// a_pauiPixelMapping2 is the pixel order for the second half
// a_uiRadius is the amount to vary the base colors
//
DifferentialTrys::DifferentialTrys(ColorFloatRGBA a_frgbaColor1, ColorFloatRGBA a_frgbaColor2,
const unsigned int *a_pauiPixelMapping1,
const unsigned int *a_pauiPixelMapping2,
unsigned int a_uiRadius,
int a_iGrayOffset1, int a_iGrayOffset2)
{
assert(a_uiRadius <= MAX_RADIUS);
m_boolSeverelyBentColors = false;
ColorFloatRGBA frgbaQuantizedColor1 = a_frgbaColor1.QuantizeR5G5B5();
ColorFloatRGBA frgbaQuantizedColor2 = a_frgbaColor2.QuantizeR5G5B5();
// quantize base colors
// ensure that trys with a_uiRadius don't overflow
int iRed1 = MoveAwayFromEdge(frgbaQuantizedColor1.IntRed(31.0f)+a_iGrayOffset1, a_uiRadius);
int iGreen1 = MoveAwayFromEdge(frgbaQuantizedColor1.IntGreen(31.0f) + a_iGrayOffset1, a_uiRadius);
int iBlue1 = MoveAwayFromEdge(frgbaQuantizedColor1.IntBlue(31.0f) + a_iGrayOffset1, a_uiRadius);
int iRed2 = MoveAwayFromEdge(frgbaQuantizedColor2.IntRed(31.0f) + a_iGrayOffset2, a_uiRadius);
int iGreen2 = MoveAwayFromEdge(frgbaQuantizedColor2.IntGreen(31.0f) + a_iGrayOffset2, a_uiRadius);
int iBlue2 = MoveAwayFromEdge(frgbaQuantizedColor2.IntBlue(31.0f) + a_iGrayOffset2, a_uiRadius);
int iDeltaRed = iRed2 - iRed1;
int iDeltaGreen = iGreen2 - iGreen1;
int iDeltaBlue = iBlue2 - iBlue1;
// make sure components are within range
{
if (iDeltaRed > 3)
{
if (iDeltaRed > 7)
{
m_boolSeverelyBentColors = true;
}
iRed1 += (iDeltaRed - 3) / 2;
iRed2 = iRed1 + 3;
iDeltaRed = 3;
}
else if (iDeltaRed < -4)
{
if (iDeltaRed < -8)
{
m_boolSeverelyBentColors = true;
}
iRed1 += (iDeltaRed + 4) / 2;
iRed2 = iRed1 - 4;
iDeltaRed = -4;
}
assert(iRed1 >= (signed)(0 + a_uiRadius) && iRed1 <= (signed)(31 - a_uiRadius));
assert(iRed2 >= (signed)(0 + a_uiRadius) && iRed2 <= (signed)(31 - a_uiRadius));
assert(iDeltaRed >= -4 && iDeltaRed <= 3);
if (iDeltaGreen > 3)
{
if (iDeltaGreen > 7)
{
m_boolSeverelyBentColors = true;
}
iGreen1 += (iDeltaGreen - 3) / 2;
iGreen2 = iGreen1 + 3;
iDeltaGreen = 3;
}
else if (iDeltaGreen < -4)
{
if (iDeltaGreen < -8)
{
m_boolSeverelyBentColors = true;
}
iGreen1 += (iDeltaGreen + 4) / 2;
iGreen2 = iGreen1 - 4;
iDeltaGreen = -4;
}
assert(iGreen1 >= (signed)(0 + a_uiRadius) && iGreen1 <= (signed)(31 - a_uiRadius));
assert(iGreen2 >= (signed)(0 + a_uiRadius) && iGreen2 <= (signed)(31 - a_uiRadius));
assert(iDeltaGreen >= -4 && iDeltaGreen <= 3);
if (iDeltaBlue > 3)
{
if (iDeltaBlue > 7)
{
m_boolSeverelyBentColors = true;
}
iBlue1 += (iDeltaBlue - 3) / 2;
iBlue2 = iBlue1 + 3;
iDeltaBlue = 3;
}
else if (iDeltaBlue < -4)
{
if (iDeltaBlue < -8)
{
m_boolSeverelyBentColors = true;
}
iBlue1 += (iDeltaBlue + 4) / 2;
iBlue2 = iBlue1 - 4;
iDeltaBlue = -4;
}
assert(iBlue1 >= (signed)(0+a_uiRadius) && iBlue1 <= (signed)(31 - a_uiRadius));
assert(iBlue2 >= (signed)(0 + a_uiRadius) && iBlue2 <= (signed)(31 - a_uiRadius));
assert(iDeltaBlue >= -4 && iDeltaBlue <= 3);
}
m_half1.Init(iRed1, iGreen1, iBlue1, a_pauiPixelMapping1, a_uiRadius);
m_half2.Init(iRed2, iGreen2, iBlue2, a_pauiPixelMapping2, a_uiRadius);
}
// ----------------------------------------------------------------------------------------------------
//
void DifferentialTrys::Half::Init(int a_iRed, int a_iGreen, int a_iBlue,
const unsigned int *a_pauiPixelMapping, unsigned int a_uiRadius)
{
m_iRed = a_iRed;
m_iGreen = a_iGreen;
m_iBlue = a_iBlue;
m_pauiPixelMapping = a_pauiPixelMapping;
m_uiRadius = a_uiRadius;
m_uiTrys = 0;
}
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc