Add some external dependencies.

pull/255/head
Ignacio 7 years ago
parent 1004d5d5b5
commit d7612a3b67

@ -4,3 +4,10 @@ IF(WIN32)
ENDIF(WIN32)
ADD_SUBDIRECTORY(poshlib)
ADD_SUBDIRECTORY(EtcLib)
ADD_SUBDIRECTORY(rg_etc1_v104)
ADD_SUBDIRECTORY(etcpack)
ADD_SUBDIRECTORY(butteraugli)

@ -0,0 +1,24 @@
# 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.
project(EtcLib)
include_directories(./Etc)
include_directories(./EtcCodec)
file(GLOB SOURCES
${PROJECT_SOURCE_DIR}/Etc/*.h
${PROJECT_SOURCE_DIR}/EtcCodec/*.h
${PROJECT_SOURCE_DIR}/Etc/*.cpp
${PROJECT_SOURCE_DIR}/EtcCodec/*.cpp)
ADD_LIBRARY(EtcLib ${SOURCES})

@ -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();
}
// ----------------------------------------------------------------------------------------------------
//
}

@ -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);
}

@ -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;
};
}

@ -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;
};
}

@ -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>

@ -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

@ -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

@ -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

@ -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);
}
}

@ -0,0 +1,417 @@
/*
* 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.
*/
/*
EtcBlock4x4.cpp
Implements the state associated with each 4x4 block of pixels in an image
Source images that are not a multiple of 4x4 are extended to fill the Block4x4 using pixels with an
alpha of NAN
*/
#include "EtcConfig.h"
#include "EtcBlock4x4.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcColor.h"
#include "EtcImage.h"
#include "EtcColorFloatRGBA.h"
#include "EtcBlock4x4Encoding_RGB8.h"
#include "EtcBlock4x4Encoding_RGBA8.h"
#include "EtcBlock4x4Encoding_RGB8A1.h"
#include "EtcBlock4x4Encoding_R11.h"
#include "EtcBlock4x4Encoding_RG11.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
namespace Etc
{
// ETC pixels are scanned vertically.
// this mapping is for when someone wants to scan the ETC pixels horizontally
const unsigned int Block4x4::s_auiPixelOrderHScan[PIXELS] = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 };
// ----------------------------------------------------------------------------------------------------
//
Block4x4::Block4x4(void)
{
m_pimageSource = nullptr;
m_uiSourceH = 0;
m_uiSourceV = 0;
m_sourcealphamix = SourceAlphaMix::UNKNOWN;
m_boolBorderPixels = false;
m_boolPunchThroughPixels = false;
m_pencoding = nullptr;
m_errormetric = ErrorMetric::NUMERIC;
}
Block4x4::~Block4x4()
{
m_pimageSource = nullptr;
if (m_pencoding)
{
delete m_pencoding;
m_pencoding = nullptr;
}
}
// ----------------------------------------------------------------------------------------------------
// initialization prior to encoding from a source image
// [a_uiSourceH,a_uiSourceV] is the location of the block in a_pimageSource
// a_paucEncodingBits is the place to store the final encoding
// a_errormetric is used for finding the best encoding
//
void Block4x4::InitFromSource(Image *a_pimageSource,
unsigned int a_uiSourceH, unsigned int a_uiSourceV,
unsigned char *a_paucEncodingBits,
ErrorMetric a_errormetric)
{
Block4x4();
m_pimageSource = a_pimageSource;
m_uiSourceH = a_uiSourceH;
m_uiSourceV = a_uiSourceV;
m_errormetric = a_errormetric;
SetSourcePixels();
// set block encoder function
switch (m_pimageSource->GetFormat())
{
case Image::Format::ETC1:
m_pencoding = new Block4x4Encoding_ETC1;
break;
case Image::Format::RGB8:
case Image::Format::SRGB8:
m_pencoding = new Block4x4Encoding_RGB8;
break;
case Image::Format::RGBA8:
case Image::Format::SRGBA8:
switch (m_sourcealphamix)
{
case SourceAlphaMix::OPAQUE:
m_pencoding = new Block4x4Encoding_RGBA8_Opaque;
break;
case SourceAlphaMix::TRANSPARENT:
m_pencoding = new Block4x4Encoding_RGBA8_Transparent;
break;
case SourceAlphaMix::TRANSLUCENT:
m_pencoding = new Block4x4Encoding_RGBA8;
break;
default:
assert(0);
break;
}
break;
case Image::Format::RGB8A1:
case Image::Format::SRGB8A1:
switch (m_sourcealphamix)
{
case SourceAlphaMix::OPAQUE:
m_pencoding = new Block4x4Encoding_RGB8A1_Opaque;
break;
case SourceAlphaMix::TRANSPARENT:
m_pencoding = new Block4x4Encoding_RGB8A1_Transparent;
break;
case SourceAlphaMix::TRANSLUCENT:
if (m_boolPunchThroughPixels)
{
m_pencoding = new Block4x4Encoding_RGB8A1;
}
else
{
m_pencoding = new Block4x4Encoding_RGB8A1_Opaque;
}
break;
default:
assert(0);
break;
}
break;
case Image::Format::R11:
case Image::Format::SIGNED_R11:
m_pencoding = new Block4x4Encoding_R11;
break;
case Image::Format::RG11:
case Image::Format::SIGNED_RG11:
m_pencoding = new Block4x4Encoding_RG11;
break;
default:
assert(0);
break;
}
m_pencoding->InitFromSource(this, m_afrgbaSource,
a_paucEncodingBits, a_errormetric);
}
// ----------------------------------------------------------------------------------------------------
// initialization of encoding state from a prior encoding using encoding bits
// [a_uiSourceH,a_uiSourceV] is the location of the block in a_pimageSource
// a_paucEncodingBits is the place to read the prior encoding
// a_imageformat is used to determine how to interpret a_paucEncodingBits
// a_errormetric was used for the prior encoding
//
void Block4x4::InitFromEtcEncodingBits(Image::Format a_imageformat,
unsigned int a_uiSourceH, unsigned int a_uiSourceV,
unsigned char *a_paucEncodingBits,
Image *a_pimageSource,
ErrorMetric a_errormetric)
{
Block4x4();
m_pimageSource = a_pimageSource;
m_uiSourceH = a_uiSourceH;
m_uiSourceV = a_uiSourceV;
m_errormetric = a_errormetric;
SetSourcePixels();
// set block encoder function
switch (a_imageformat)
{
case Image::Format::ETC1:
m_pencoding = new Block4x4Encoding_ETC1;
break;
case Image::Format::RGB8:
case Image::Format::SRGB8:
m_pencoding = new Block4x4Encoding_RGB8;
break;
case Image::Format::RGBA8:
case Image::Format::SRGBA8:
m_pencoding = new Block4x4Encoding_RGBA8;
break;
case Image::Format::RGB8A1:
case Image::Format::SRGB8A1:
m_pencoding = new Block4x4Encoding_RGB8A1;
break;
case Image::Format::R11:
case Image::Format::SIGNED_R11:
m_pencoding = new Block4x4Encoding_R11;
break;
case Image::Format::RG11:
case Image::Format::SIGNED_RG11:
m_pencoding = new Block4x4Encoding_RG11;
break;
default:
assert(0);
break;
}
m_pencoding->InitFromEncodingBits(this, a_paucEncodingBits, m_afrgbaSource,
m_pimageSource->GetErrorMetric());
}
// ----------------------------------------------------------------------------------------------------
// set source pixels from m_pimageSource
// set m_alphamix
//
void Block4x4::SetSourcePixels(void)
{
Image::Format imageformat = m_pimageSource->GetFormat();
// alpha census
unsigned int uiTransparentSourcePixels = 0;
unsigned int uiOpaqueSourcePixels = 0;
// copy source to consecutive memory locations
// convert from image horizontal scan to block vertical scan
unsigned int uiPixel = 0;
for (unsigned int uiBlockPixelH = 0; uiBlockPixelH < Block4x4::COLUMNS; uiBlockPixelH++)
{
unsigned int uiSourcePixelH = m_uiSourceH + uiBlockPixelH;
for (unsigned int uiBlockPixelV = 0; uiBlockPixelV < Block4x4::ROWS; uiBlockPixelV++)
{
unsigned int uiSourcePixelV = m_uiSourceV + uiBlockPixelV;
ColorFloatRGBA *pfrgbaSource = m_pimageSource->GetSourcePixel(uiSourcePixelH, uiSourcePixelV);
// if pixel extends beyond source image because of block padding
if (pfrgbaSource == nullptr)
{
m_afrgbaSource[uiPixel] = ColorFloatRGBA(0.0f, 0.0f, 0.0f, NAN); // denotes border pixel
m_boolBorderPixels = true;
uiTransparentSourcePixels++;
}
else
{
//get teh current pixel data, and store some of the attributes
//before capping values to fit the encoder type
m_afrgbaSource[uiPixel] = (*pfrgbaSource).ClampRGBA();
if (m_afrgbaSource[uiPixel].fA == 1.0f)
{
m_pimageSource->m_iNumOpaquePixels++;
}
else if (m_afrgbaSource[uiPixel].fA == 0.0f)
{
m_pimageSource->m_iNumTransparentPixels++;
}
else if(m_afrgbaSource[uiPixel].fA > 0.0f && m_afrgbaSource[uiPixel].fA < 1.0f)
{
m_pimageSource->m_iNumTranslucentPixels++;
}
else
{
m_pimageSource->m_numOutOfRangeValues.fA++;
}
if (m_afrgbaSource[uiPixel].fR != 0.0f)
{
m_pimageSource->m_numColorValues.fR++;
//make sure we are getting a float between 0-1
if (m_afrgbaSource[uiPixel].fR - 1.0f > 0.0f)
{
m_pimageSource->m_numOutOfRangeValues.fR++;
}
}
if (m_afrgbaSource[uiPixel].fG != 0.0f)
{
m_pimageSource->m_numColorValues.fG++;
if (m_afrgbaSource[uiPixel].fG - 1.0f > 0.0f)
{
m_pimageSource->m_numOutOfRangeValues.fG++;
}
}
if (m_afrgbaSource[uiPixel].fB != 0.0f)
{
m_pimageSource->m_numColorValues.fB++;
if (m_afrgbaSource[uiPixel].fB - 1.0f > 0.0f)
{
m_pimageSource->m_numOutOfRangeValues.fB++;
}
}
// for formats with no alpha, set source alpha to 1
if (imageformat == Image::Format::ETC1 ||
imageformat == Image::Format::RGB8 ||
imageformat == Image::Format::SRGB8)
{
m_afrgbaSource[uiPixel].fA = 1.0f;
}
if (imageformat == Image::Format::R11 ||
imageformat == Image::Format::SIGNED_R11)
{
m_afrgbaSource[uiPixel].fA = 1.0f;
m_afrgbaSource[uiPixel].fG = 0.0f;
m_afrgbaSource[uiPixel].fB = 0.0f;
}
if (imageformat == Image::Format::RG11 ||
imageformat == Image::Format::SIGNED_RG11)
{
m_afrgbaSource[uiPixel].fA = 1.0f;
m_afrgbaSource[uiPixel].fB = 0.0f;
}
// for RGB8A1, set source alpha to 0.0 or 1.0
// set punch through flag
if (imageformat == Image::Format::RGB8A1 ||
imageformat == Image::Format::SRGB8A1)
{
if (m_afrgbaSource[uiPixel].fA >= 0.5f)
{
m_afrgbaSource[uiPixel].fA = 1.0f;
}
else
{
m_afrgbaSource[uiPixel].fA = 0.0f;
m_boolPunchThroughPixels = true;
}
}
if (m_afrgbaSource[uiPixel].fA == 1.0f)
{
uiOpaqueSourcePixels++;
}
else if (m_afrgbaSource[uiPixel].fA == 0.0f)
{
uiTransparentSourcePixels++;
}
}
uiPixel += 1;
}
}
if (uiOpaqueSourcePixels == PIXELS)
{
m_sourcealphamix = SourceAlphaMix::OPAQUE;
}
else if (uiTransparentSourcePixels == PIXELS)
{
m_sourcealphamix = SourceAlphaMix::TRANSPARENT;
}
else
{
m_sourcealphamix = SourceAlphaMix::TRANSLUCENT;
}
}
// ----------------------------------------------------------------------------------------------------
// return a name for the encoding mode
//
const char * Block4x4::GetEncodingModeName(void)
{
switch (m_pencoding->GetMode())
{
case Block4x4Encoding::MODE_ETC1:
return "ETC1";
case Block4x4Encoding::MODE_T:
return "T";
case Block4x4Encoding::MODE_H:
return "H";
case Block4x4Encoding::MODE_PLANAR:
return "PLANAR";
default:
return "???";
}
}
// ----------------------------------------------------------------------------------------------------
//
}

@ -0,0 +1,172 @@
/*
* 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 "EtcColor.h"
#include "EtcColorFloatRGBA.h"
#include "EtcErrorMetric.h"
#include "EtcImage.h"
#include "EtcBlock4x4Encoding.h"
namespace Etc
{
class Block4x4EncodingBits;
class Block4x4
{
public:
static const unsigned int ROWS = 4;
static const unsigned int COLUMNS = 4;
static const unsigned int PIXELS = ROWS * COLUMNS;
// the alpha mix for a 4x4 block of pixels
enum class SourceAlphaMix
{
UNKNOWN,
//
OPAQUE, // all 1.0
TRANSPARENT, // all 0.0 or NAN
TRANSLUCENT // not all opaque or transparent
};
typedef void (Block4x4::*EncoderFunctionPtr)(void);
Block4x4(void);
~Block4x4();
void InitFromSource(Image *a_pimageSource,
unsigned int a_uiSourceH,
unsigned int a_uiSourceV,
unsigned char *a_paucEncodingBits,
ErrorMetric a_errormetric);
void InitFromEtcEncodingBits(Image::Format a_imageformat,
unsigned int a_uiSourceH,
unsigned int a_uiSourceV,
unsigned char *a_paucEncodingBits,
Image *a_pimageSource,
ErrorMetric a_errormetric);
// return true if final iteration was performed
inline void PerformEncodingIteration(float a_fEffort)
{
m_pencoding->PerformIteration(a_fEffort);
}
inline void SetEncodingBitsFromEncoding(void)
{
m_pencoding->SetEncodingBits();
}
inline unsigned int GetSourceH(void)
{
return m_uiSourceH;
}
inline unsigned int GetSourceV(void)
{
return m_uiSourceV;
}
inline float GetError(void)
{
return m_pencoding->GetError();
}
static const unsigned int s_auiPixelOrderHScan[PIXELS];
inline ColorFloatRGBA * GetDecodedColors(void)
{
return m_pencoding->GetDecodedColors();
}
inline float * GetDecodedAlphas(void)
{
return m_pencoding->GetDecodedAlphas();
}
inline Block4x4Encoding::Mode GetEncodingMode(void)
{
return m_pencoding->GetMode();
}
inline bool GetFlip(void)
{
return m_pencoding->GetFlip();
}
inline bool IsDifferential(void)
{
return m_pencoding->IsDifferential();
}
inline ColorFloatRGBA * GetSource()
{
return m_afrgbaSource;
}
inline ErrorMetric GetErrorMetric()
{
return m_errormetric;
}
const char * GetEncodingModeName(void);
inline Block4x4Encoding * GetEncoding(void)
{
return m_pencoding;
}
inline SourceAlphaMix GetSourceAlphaMix(void)
{
return m_sourcealphamix;
}
inline Image * GetImageSource(void)
{
return m_pimageSource;
}
inline bool HasBorderPixels(void)
{
return m_boolBorderPixels;
}
inline bool HasPunchThroughPixels(void)
{
return m_boolPunchThroughPixels;
}
private:
void SetSourcePixels(void);
Image *m_pimageSource;
unsigned int m_uiSourceH;
unsigned int m_uiSourceV;
ErrorMetric m_errormetric;
ColorFloatRGBA m_afrgbaSource[PIXELS]; // vertical scan
SourceAlphaMix m_sourcealphamix;
bool m_boolBorderPixels; // marked as rgba(NAN, NAN, NAN, NAN)
bool m_boolPunchThroughPixels; // RGB8A1 or SRGB8A1 with any pixels with alpha < 0.5
Block4x4Encoding *m_pencoding;
};
} // namespace Etc

@ -0,0 +1,250 @@
/*
* 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.
*/
/*
EtcBlock4x4Encoding.cpp
Block4x4Encoding is the abstract base class for the different encoders. Each encoder targets a
particular file format (e.g. ETC1, RGB8, RGBA8, R11)
*/
#include "EtcConfig.h"
#include "EtcBlock4x4Encoding.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcBlock4x4.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
//
const float Block4x4Encoding::LUMA_WEIGHT = 3.0f;
const float Block4x4Encoding::CHROMA_BLUE_WEIGHT = 0.5f;
// ----------------------------------------------------------------------------------------------------
//
Block4x4Encoding::Block4x4Encoding(void)
{
m_pblockParent = nullptr;
m_pafrgbaSource = nullptr;
m_boolBorderPixels = false;
m_fError = -1.0f;
m_mode = MODE_UNKNOWN;
m_uiEncodingIterations = 0;
m_boolDone = false;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA(-1.0f, -1.0f, -1.0f, -1.0f);
m_afDecodedAlphas[uiPixel] = -1.0f;
}
}
// ----------------------------------------------------------------------------------------------------
// initialize the generic encoding for a 4x4 block
// a_pblockParent points to the block associated with this encoding
// a_errormetric is used to choose the best encoding
// init the decoded pixels to -1 to mark them as undefined
// init the error to -1 to mark it as undefined
//
void Block4x4Encoding::Init(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric)
{
m_pblockParent = a_pblockParent;
m_pafrgbaSource = a_pafrgbaSource;
m_boolBorderPixels = m_pblockParent->HasBorderPixels();
m_fError = -1.0f;
m_uiEncodingIterations = 0;
m_errormetric = a_errormetric;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA(-1.0f, -1.0f, -1.0f, -1.0f);
m_afDecodedAlphas[uiPixel] = -1.0f;
}
}
// ----------------------------------------------------------------------------------------------------
// calculate the error for the block by summing the pixel errors
//
void Block4x4Encoding::CalcBlockError(void)
{
m_fError = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_fError += CalcPixelError(m_afrgbaDecodedColors[uiPixel], m_afDecodedAlphas[uiPixel],
m_pafrgbaSource[uiPixel]);
}
}
// ----------------------------------------------------------------------------------------------------
// calculate the error between the source pixel and the decoded pixel
// the error amount is base on the error metric
//
float Block4x4Encoding::CalcPixelError(ColorFloatRGBA a_frgbaDecodedColor, float a_fDecodedAlpha,
ColorFloatRGBA a_frgbaSourcePixel)
{
// if a border pixel
if (isnan(a_frgbaSourcePixel.fA))
{
return 0.0f;
}
if (m_errormetric == ErrorMetric::RGBA)
{
assert(a_fDecodedAlpha >= 0.0f);
float fDRed = (a_fDecodedAlpha * a_frgbaDecodedColor.fR) -
(a_frgbaSourcePixel.fA * a_frgbaSourcePixel.fR);
float fDGreen = (a_fDecodedAlpha * a_frgbaDecodedColor.fG) -
(a_frgbaSourcePixel.fA * a_frgbaSourcePixel.fG);
float fDBlue = (a_fDecodedAlpha * a_frgbaDecodedColor.fB) -
(a_frgbaSourcePixel.fA * a_frgbaSourcePixel.fB);
float fDAlpha = a_fDecodedAlpha - a_frgbaSourcePixel.fA;
return fDRed*fDRed + fDGreen*fDGreen + fDBlue*fDBlue + fDAlpha*fDAlpha;
}
else if (m_errormetric == ErrorMetric::REC709)
{
assert(a_fDecodedAlpha >= 0.0f);
float fLuma1 = a_frgbaSourcePixel.fR*0.2126f + a_frgbaSourcePixel.fG*0.7152f + a_frgbaSourcePixel.fB*0.0722f;
float fChromaR1 = 0.5f * ((a_frgbaSourcePixel.fR - fLuma1) * (1.0f / (1.0f - 0.2126f)));
float fChromaB1 = 0.5f * ((a_frgbaSourcePixel.fB - fLuma1) * (1.0f / (1.0f - 0.0722f)));
float fLuma2 = a_frgbaDecodedColor.fR*0.2126f +
a_frgbaDecodedColor.fG*0.7152f +
a_frgbaDecodedColor.fB*0.0722f;
float fChromaR2 = 0.5f * ((a_frgbaDecodedColor.fR - fLuma2) * (1.0f / (1.0f - 0.2126f)));
float fChromaB2 = 0.5f * ((a_frgbaDecodedColor.fB - fLuma2) * (1.0f / (1.0f - 0.0722f)));
float fDeltaL = a_frgbaSourcePixel.fA * fLuma1 - a_fDecodedAlpha * fLuma2;
float fDeltaCr = a_frgbaSourcePixel.fA * fChromaR1 - a_fDecodedAlpha * fChromaR2;
float fDeltaCb = a_frgbaSourcePixel.fA * fChromaB1 - a_fDecodedAlpha * fChromaB2;
float fDAlpha = a_fDecodedAlpha - a_frgbaSourcePixel.fA;
// Favor Luma accuracy over Chroma, and Red over Blue
return LUMA_WEIGHT*fDeltaL*fDeltaL +
fDeltaCr*fDeltaCr +
CHROMA_BLUE_WEIGHT*fDeltaCb*fDeltaCb +
fDAlpha*fDAlpha;
#if 0
float fDRed = a_frgbaDecodedPixel.fR - a_frgbaSourcePixel.fR;
float fDGreen = a_frgbaDecodedPixel.fG - a_frgbaSourcePixel.fG;
float fDBlue = a_frgbaDecodedPixel.fB - a_frgbaSourcePixel.fB;
return 2.0f * 3.0f * fDeltaL * fDeltaL + fDRed*fDRed + fDGreen*fDGreen + fDBlue*fDBlue;
#endif
}
else if (m_errormetric == ErrorMetric::NORMALXYZ)
{
float fDecodedX = 2.0f * a_frgbaDecodedColor.fR - 1.0f;
float fDecodedY = 2.0f * a_frgbaDecodedColor.fG - 1.0f;
float fDecodedZ = 2.0f * a_frgbaDecodedColor.fB - 1.0f;
float fDecodedLength = sqrtf(fDecodedX*fDecodedX + fDecodedY*fDecodedY + fDecodedZ*fDecodedZ);
if (fDecodedLength < 0.5f)
{
return 1.0f;
}
else if (fDecodedLength == 0.0f)
{
fDecodedX = 1.0f;
fDecodedY = 0.0f;
fDecodedZ = 0.0f;
}
else
{
fDecodedX /= fDecodedLength;
fDecodedY /= fDecodedLength;
fDecodedZ /= fDecodedLength;
}
float fSourceX = 2.0f * a_frgbaSourcePixel.fR - 1.0f;
float fSourceY = 2.0f * a_frgbaSourcePixel.fG - 1.0f;
float fSourceZ = 2.0f * a_frgbaSourcePixel.fB - 1.0f;
float fSourceLength = sqrtf(fSourceX*fSourceX + fSourceY*fSourceY + fSourceZ*fSourceZ);
if (fSourceLength == 0.0f)
{
fSourceX = 1.0f;
fSourceY = 0.0f;
fSourceZ = 0.0f;
}
else
{
fSourceX /= fSourceLength;
fSourceY /= fSourceLength;
fSourceZ /= fSourceLength;
}
float fDotProduct = fSourceX*fDecodedX + fSourceY*fDecodedY + fSourceZ*fDecodedZ;
float fNormalizedDotProduct = 1.0f - 0.5f * (fDotProduct + 1.0f);
float fDotProductError = fNormalizedDotProduct * fNormalizedDotProduct;
float fLength2 = fDecodedX*fDecodedX + fDecodedY*fDecodedY + fDecodedZ*fDecodedZ;
float fLength2Error = fabsf(1.0f - fLength2);
float fDeltaW = a_frgbaDecodedColor.fA - a_frgbaSourcePixel.fA;
float fErrorW = fDeltaW * fDeltaW;
return fDotProductError + fLength2Error + fErrorW;
}
else // ErrorMetric::NUMERIC
{
assert(a_fDecodedAlpha >= 0.0f);
float fDX = a_frgbaDecodedColor.fR - a_frgbaSourcePixel.fR;
float fDY = a_frgbaDecodedColor.fG - a_frgbaSourcePixel.fG;
float fDZ = a_frgbaDecodedColor.fB - a_frgbaSourcePixel.fB;
float fDW = a_frgbaDecodedColor.fA - a_frgbaSourcePixel.fA;
return fDX*fDX + fDY*fDY + fDZ*fDZ + fDW*fDW;
}
}
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

@ -0,0 +1,148 @@
/*
* 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 "EtcColorFloatRGBA.h"
#include "EtcErrorMetric.h"
#include <assert.h>
#include <float.h>
namespace Etc
{
class Block4x4;
// abstract base class for specific encodings
class Block4x4Encoding
{
public:
static const unsigned int ROWS = 4;
static const unsigned int COLUMNS = 4;
static const unsigned int PIXELS = ROWS * COLUMNS;
static const float LUMA_WEIGHT;
static const float CHROMA_BLUE_WEIGHT;
typedef enum
{
MODE_UNKNOWN,
//
MODE_ETC1,
MODE_T,
MODE_H,
MODE_PLANAR,
MODE_R11,
MODE_RG11,
//
MODES
} Mode;
Block4x4Encoding(void);
//virtual ~Block4x4Encoding(void) =0;
virtual ~Block4x4Encoding(void) {}
virtual void InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric) = 0;
virtual void InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric) = 0;
// perform an iteration of the encoding
// the first iteration must generate a complete, valid (if poor) encoding
virtual void PerformIteration(float a_fEffort) = 0;
void CalcBlockError(void);
inline float GetError(void)
{
assert(m_fError >= 0.0f);
return m_fError;
}
inline ColorFloatRGBA * GetDecodedColors(void)
{
return m_afrgbaDecodedColors;
}
inline float * GetDecodedAlphas(void)
{
return m_afDecodedAlphas;
}
virtual void SetEncodingBits(void) = 0;
virtual bool GetFlip(void) = 0;
virtual bool IsDifferential(void) = 0;
virtual bool HasSeverelyBentDifferentialColors(void) const = 0;
inline Mode GetMode(void)
{
return m_mode;
}
inline bool IsDone(void)
{
return m_boolDone;
}
inline void SetDoneIfPerfect()
{
if (GetError() == 0.0f)
{
m_boolDone = true;
}
}
float CalcPixelError(ColorFloatRGBA a_frgbaDecodedColor, float a_fDecodedAlpha,
ColorFloatRGBA a_frgbaSourcePixel);
protected:
void Init(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
Block4x4 *m_pblockParent;
ColorFloatRGBA *m_pafrgbaSource;
bool m_boolBorderPixels; // if block has any border pixels
ColorFloatRGBA m_afrgbaDecodedColors[PIXELS]; // decoded RGB components, ignore Alpha
float m_afDecodedAlphas[PIXELS]; // decoded alpha component
float m_fError; // error for RGBA relative to m_pafrgbaSource
// intermediate encoding
Mode m_mode;
unsigned int m_uiEncodingIterations;
bool m_boolDone; // all iterations have been done
ErrorMetric m_errormetric;
private:
};
} // namespace Etc

@ -0,0 +1,315 @@
/*
* 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 <assert.h>
namespace Etc
{
// ################################################################################
// Block4x4EncodingBits
// Base class for Block4x4EncodingBits_XXXX
// ################################################################################
class Block4x4EncodingBits
{
public:
enum class Format
{
UNKNOWN,
//
RGB8,
RGBA8,
R11,
RG11,
RGB8A1,
//
FORMATS
};
static unsigned int GetBytesPerBlock(Format a_format)
{
switch (a_format)
{
case Format::RGB8:
case Format::R11:
case Format::RGB8A1:
return 8;
break;
case Format::RGBA8:
case Format::RG11:
return 16;
break;
default:
return 0;
break;
}
}
};
// ################################################################################
// Block4x4EncodingBits_RGB8
// Encoding bits for the RGB portion of ETC1, RGB8, RGB8A1 and RGBA8
// ################################################################################
class Block4x4EncodingBits_RGB8
{
public:
static const unsigned int BYTES_PER_BLOCK = 8;
inline Block4x4EncodingBits_RGB8(void)
{
assert(sizeof(Block4x4EncodingBits_RGB8) == BYTES_PER_BLOCK);
for (unsigned int uiByte = 0; uiByte < BYTES_PER_BLOCK; uiByte++)
{
auc[uiByte] = 0;
}
}
typedef struct
{
unsigned red2 : 4;
unsigned red1 : 4;
//
unsigned green2 : 4;
unsigned green1 : 4;
//
unsigned blue2 : 4;
unsigned blue1 : 4;
//
unsigned flip : 1;
unsigned diff : 1;
unsigned cw2 : 3;
unsigned cw1 : 3;
//
unsigned int selectors;
} Individual;
typedef struct
{
signed dred2 : 3;
unsigned red1 : 5;
//
signed dgreen2 : 3;
unsigned green1 : 5;
//
signed dblue2 : 3;
unsigned blue1 : 5;
//
unsigned flip : 1;
unsigned diff : 1;
unsigned cw2 : 3;
unsigned cw1 : 3;
//
unsigned int selectors;
} Differential;
typedef struct
{
unsigned red1b : 2;
unsigned detect2 : 1;
unsigned red1a : 2;
unsigned detect1 : 3;
//
unsigned blue1 : 4;
unsigned green1 : 4;
//
unsigned green2 : 4;
unsigned red2 : 4;
//
unsigned db : 1;
unsigned diff : 1;
unsigned da : 2;
unsigned blue2 : 4;
//
unsigned int selectors;
} T;
typedef struct
{
unsigned green1a : 3;
unsigned red1 : 4;
unsigned detect1 : 1;
//
unsigned blue1b : 2;
unsigned detect3 : 1;
unsigned blue1a : 1;
unsigned green1b : 1;
unsigned detect2 : 3;
//
unsigned green2a : 3;
unsigned red2 : 4;
unsigned blue1c : 1;
//
unsigned db : 1;
unsigned diff : 1;
unsigned da : 1;
unsigned blue2 : 4;
unsigned green2b : 1;
//
unsigned int selectors;
} H;
typedef struct
{
unsigned originGreen1 : 1;
unsigned originRed : 6;
unsigned detect1 : 1;
//
unsigned originBlue1 : 1;
unsigned originGreen2 : 6;
unsigned detect2 : 1;
//
unsigned originBlue3 : 2;
unsigned detect4 : 1;
unsigned originBlue2 : 2;
unsigned detect3 : 3;
//
unsigned horizRed2 : 1;
unsigned diff : 1;
unsigned horizRed1 : 5;
unsigned originBlue4 : 1;
//
unsigned horizBlue1: 1;
unsigned horizGreen : 7;
//
unsigned vertRed1 : 3;
unsigned horizBlue2 : 5;
//
unsigned vertGreen1 : 5;
unsigned vertRed2 : 3;
//
unsigned vertBlue : 6;
unsigned vertGreen2 : 2;
} Planar;
union
{
unsigned char auc[BYTES_PER_BLOCK];
unsigned long int ul;
Individual individual;
Differential differential;
T t;
H h;
Planar planar;
};
};
// ################################################################################
// Block4x4EncodingBits_A8
// Encoding bits for the A portion of RGBA8
// ################################################################################
class Block4x4EncodingBits_A8
{
public:
static const unsigned int BYTES_PER_BLOCK = 8;
static const unsigned int SELECTOR_BYTES = 6;
typedef struct
{
unsigned base : 8;
unsigned table : 4;
unsigned multiplier : 4;
unsigned selectors0 : 8;
unsigned selectors1 : 8;
unsigned selectors2 : 8;
unsigned selectors3 : 8;
unsigned selectors4 : 8;
unsigned selectors5 : 8;
} Data;
Data data;
};
// ################################################################################
// Block4x4EncodingBits_R11
// Encoding bits for the R portion of R11
// ################################################################################
class Block4x4EncodingBits_R11
{
public:
static const unsigned int BYTES_PER_BLOCK = 8;
static const unsigned int SELECTOR_BYTES = 6;
typedef struct
{
unsigned base : 8;
unsigned table : 4;
unsigned multiplier : 4;
unsigned selectors0 : 8;
unsigned selectors1 : 8;
unsigned selectors2 : 8;
unsigned selectors3 : 8;
unsigned selectors4 : 8;
unsigned selectors5 : 8;
} Data;
Data data;
};
class Block4x4EncodingBits_RG11
{
public:
static const unsigned int BYTES_PER_BLOCK = 16;
static const unsigned int SELECTOR_BYTES = 12;
typedef struct
{
//Red portion
unsigned baseR : 8;
unsigned tableIndexR : 4;
unsigned multiplierR : 4;
unsigned selectorsR0 : 8;
unsigned selectorsR1 : 8;
unsigned selectorsR2 : 8;
unsigned selectorsR3 : 8;
unsigned selectorsR4 : 8;
unsigned selectorsR5 : 8;
//Green portion
unsigned baseG : 8;
unsigned tableIndexG : 4;
unsigned multiplierG : 4;
unsigned selectorsG0 : 8;
unsigned selectorsG1 : 8;
unsigned selectorsG2 : 8;
unsigned selectorsG3 : 8;
unsigned selectorsG4 : 8;
unsigned selectorsG5 : 8;
} Data;
Data data;
};
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,186 @@
/*
* 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 "EtcBlock4x4Encoding.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcDifferentialTrys.h"
#include "EtcIndividualTrys.h"
namespace Etc
{
// base class for Block4x4Encoding_RGB8
class Block4x4Encoding_ETC1 : public Block4x4Encoding
{
public:
Block4x4Encoding_ETC1(void);
virtual ~Block4x4Encoding_ETC1(void);
virtual void InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits,
ErrorMetric a_errormetric);
virtual void InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
virtual void PerformIteration(float a_fEffort);
inline virtual bool GetFlip(void)
{
return m_boolFlip;
}
inline virtual bool IsDifferential(void)
{
return m_boolDiff;
}
virtual void SetEncodingBits(void);
void Decode(void);
inline ColorFloatRGBA GetColor1(void) const
{
return m_frgbaColor1;
}
inline ColorFloatRGBA GetColor2(void) const
{
return m_frgbaColor2;
}
inline const unsigned int * GetSelectors(void) const
{
return m_auiSelectors;
}
inline unsigned int GetCW1(void) const
{
return m_uiCW1;
}
inline unsigned int GetCW2(void) const
{
return m_uiCW2;
}
inline bool HasSeverelyBentDifferentialColors(void) const
{
return m_boolSeverelyBentDifferentialColors;
}
protected:
static const unsigned int s_auiPixelOrderFlip0[PIXELS];
static const unsigned int s_auiPixelOrderFlip1[PIXELS];
static const unsigned int s_auiPixelOrderHScan[PIXELS];
static const unsigned int s_auiLeftPixelMapping[8];
static const unsigned int s_auiRightPixelMapping[8];
static const unsigned int s_auiTopPixelMapping[8];
static const unsigned int s_auiBottomPixelMapping[8];
static const unsigned int SELECTOR_BITS = 2;
static const unsigned int SELECTORS = 1 << SELECTOR_BITS;
static const unsigned int CW_BITS = 3;
static const unsigned int CW_RANGES = 1 << CW_BITS;
static float s_aafCwTable[CW_RANGES][SELECTORS];
static unsigned char s_aucDifferentialCwRange[256];
static const int MAX_DIFFERENTIAL = 3;
static const int MIN_DIFFERENTIAL = -4;
void InitFromEncodingBits_Selectors(void);
void PerformFirstIteration(void);
void CalculateMostLikelyFlip(void);
void TryDifferential(bool a_boolFlip, unsigned int a_uiRadius,
int a_iGrayOffset1, int a_iGrayOffset2);
void TryDifferentialHalf(DifferentialTrys::Half *a_phalf);
void TryIndividual(bool a_boolFlip, unsigned int a_uiRadius);
void TryIndividualHalf(IndividualTrys::Half *a_phalf);
void TryDegenerates1(void);
void TryDegenerates2(void);
void TryDegenerates3(void);
void TryDegenerates4(void);
void CalculateSelectors();
void CalculateHalfOfTheSelectors(unsigned int a_uiHalf,
const unsigned int *pauiPixelMapping);
// calculate the distance2 of r_frgbaPixel from r_frgbaTarget's gray line
inline float CalcGrayDistance2(ColorFloatRGBA &r_frgbaPixel,
ColorFloatRGBA &r_frgbaTarget)
{
float fDeltaGray = ((r_frgbaPixel.fR - r_frgbaTarget.fR) +
(r_frgbaPixel.fG - r_frgbaTarget.fG) +
(r_frgbaPixel.fB - r_frgbaTarget.fB)) / 3.0f;
ColorFloatRGBA frgbaPointOnGrayLine = (r_frgbaTarget + fDeltaGray).ClampRGB();
float fDR = r_frgbaPixel.fR - frgbaPointOnGrayLine.fR;
float fDG = r_frgbaPixel.fG - frgbaPointOnGrayLine.fG;
float fDB = r_frgbaPixel.fB - frgbaPointOnGrayLine.fB;
return (fDR*fDR) + (fDG*fDG) + (fDB*fDB);
}
void SetEncodingBits_Selectors(void);
// intermediate encoding
bool m_boolDiff;
bool m_boolFlip;
ColorFloatRGBA m_frgbaColor1;
ColorFloatRGBA m_frgbaColor2;
unsigned int m_uiCW1;
unsigned int m_uiCW2;
unsigned int m_auiSelectors[PIXELS];
// state shared between iterations
ColorFloatRGBA m_frgbaSourceAverageLeft;
ColorFloatRGBA m_frgbaSourceAverageRight;
ColorFloatRGBA m_frgbaSourceAverageTop;
ColorFloatRGBA m_frgbaSourceAverageBottom;
bool m_boolMostLikelyFlip;
// stats
float m_fError1; // error for Etc1 half 1
float m_fError2; // error for Etc1 half 2
bool m_boolSeverelyBentDifferentialColors; // only valid if m_boolDiff;
// final encoding
Block4x4EncodingBits_RGB8 *m_pencodingbitsRGB8; // or RGB8 portion of Block4x4EncodingBits_RGB8A8
private:
void CalculateSourceAverages(void);
};
} // namespace Etc

@ -0,0 +1,429 @@
/*
* 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.
*/
/*
EtcBlock4x4Encoding_R11.cpp
Block4x4Encoding_R11 is the encoder to use when targetting file format R11 and SR11 (signed R11).
*/
#include "EtcConfig.h"
#include "EtcBlock4x4Encoding_R11.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcBlock4x4.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <float.h>
#include <limits>
namespace Etc
{
// modifier values to use for R11, SR11, RG11 and SRG11
float Block4x4Encoding_R11::s_aafModifierTable[MODIFIER_TABLE_ENTRYS][SELECTORS]
{
{ -3.0f / 255.0f, -6.0f / 255.0f, -9.0f / 255.0f, -15.0f / 255.0f, 2.0f / 255.0f, 5.0f / 255.0f, 8.0f / 255.0f, 14.0f / 255.0f },
{ -3.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, -13.0f / 255.0f, 2.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f, 12.0f / 255.0f },
{ -2.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -13.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 12.0f / 255.0f },
{ -2.0f / 255.0f, -4.0f / 255.0f, -6.0f / 255.0f, -13.0f / 255.0f, 1.0f / 255.0f, 3.0f / 255.0f, 5.0f / 255.0f, 12.0f / 255.0f },
{ -3.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -12.0f / 255.0f, 2.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 11.0f / 255.0f },
{ -3.0f / 255.0f, -7.0f / 255.0f, -9.0f / 255.0f, -11.0f / 255.0f, 2.0f / 255.0f, 6.0f / 255.0f, 8.0f / 255.0f, 10.0f / 255.0f },
{ -4.0f / 255.0f, -7.0f / 255.0f, -8.0f / 255.0f, -11.0f / 255.0f, 3.0f / 255.0f, 6.0f / 255.0f, 7.0f / 255.0f, 10.0f / 255.0f },
{ -3.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -11.0f / 255.0f, 2.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 10.0f / 255.0f },
{ -2.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
{ -2.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
{ -2.0f / 255.0f, -4.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 3.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
{ -2.0f / 255.0f, -5.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f },
{ -3.0f / 255.0f, -4.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f },
{ -1.0f / 255.0f, -2.0f / 255.0f, -3.0f / 255.0f, -10.0f / 255.0f, 0.0f / 255.0f, 1.0f / 255.0f, 2.0f / 255.0f, 9.0f / 255.0f },
{ -4.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -9.0f / 255.0f, 3.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 8.0f / 255.0f },
{ -3.0f / 255.0f, -5.0f / 255.0f, -7.0f / 255.0f, -9.0f / 255.0f, 2.0f / 255.0f, 4.0f / 255.0f, 6.0f / 255.0f, 8.0f / 255.0f }
};
// ----------------------------------------------------------------------------------------------------
//
Block4x4Encoding_R11::Block4x4Encoding_R11(void)
{
m_pencodingbitsR11 = nullptr;
}
Block4x4Encoding_R11::~Block4x4Encoding_R11(void) {}
// ----------------------------------------------------------------------------------------------------
// initialization prior to encoding
// a_pblockParent points to the block associated with this encoding
// a_errormetric is used to choose the best encoding
// a_pafrgbaSource points to a 4x4 block subset of the source image
// a_paucEncodingBits points to the final encoding bits
//
void Block4x4Encoding_R11::InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric)
{
Block4x4Encoding::Init(a_pblockParent, a_pafrgbaSource,a_errormetric);
m_pencodingbitsR11 = (Block4x4EncodingBits_R11 *)a_paucEncodingBits;
}
// ----------------------------------------------------------------------------------------------------
// initialization from the encoding bits of a previous encoding
// a_pblockParent points to the block associated with this encoding
// a_errormetric is used to choose the best encoding
// a_pafrgbaSource points to a 4x4 block subset of the source image
// a_paucEncodingBits points to the final encoding bits of a previous encoding
//
void Block4x4Encoding_R11::InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric)
{
m_pencodingbitsR11 = (Block4x4EncodingBits_R11 *)a_paucEncodingBits;
// init RGB portion
Block4x4Encoding_RGB8::InitFromEncodingBits(a_pblockParent,
(unsigned char *)m_pencodingbitsR11,
a_pafrgbaSource,
a_errormetric);
// init R11 portion
{
m_mode = MODE_R11;
if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
m_fRedBase = (float)(signed char)m_pencodingbitsR11->data.base;
}
else
{
m_fRedBase = (float)(unsigned char)m_pencodingbitsR11->data.base;
}
m_fRedMultiplier = (float)m_pencodingbitsR11->data.multiplier;
m_uiRedModifierTableIndex = m_pencodingbitsR11->data.table;
unsigned long long int ulliSelectorBits = 0;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors0 << 40;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors1 << 32;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors2 << 24;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors3 << 16;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors4 << 8;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors5;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
unsigned int uiShift = 45 - (3 * uiPixel);
m_auiRedSelectors[uiPixel] = (ulliSelectorBits >> uiShift) & (SELECTORS - 1);
}
// decode the red channel
// calc red error
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
float fDecodedPixelData = 0.0f;
if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::R11 || a_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
{
fDecodedPixelData = DecodePixelRed(m_fRedBase, m_fRedMultiplier,
m_uiRedModifierTableIndex,
m_auiRedSelectors[uiPixel]);
}
else if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
fDecodedPixelData = DecodePixelRed(m_fRedBase + 128, m_fRedMultiplier,
m_uiRedModifierTableIndex,
m_auiRedSelectors[uiPixel]);
}
else
{
assert(0);
}
m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA(fDecodedPixelData, 0.0f, 0.0f, 1.0f);
}
CalcBlockError();
}
}
// ----------------------------------------------------------------------------------------------------
// perform a single encoding iteration
// replace the encoding if a better encoding was found
// subsequent iterations generally take longer for each iteration
// set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
//
void Block4x4Encoding_R11::PerformIteration(float a_fEffort)
{
assert(!m_boolDone);
m_mode = MODE_R11;
switch (m_uiEncodingIterations)
{
case 0:
m_fError = FLT_MAX;
m_fRedBlockError = FLT_MAX; // artificially high value
CalculateR11(8, 0.0f, 0.0f);
m_fError = m_fRedBlockError;
break;
case 1:
CalculateR11(8, 2.0f, 1.0f);
m_fError = m_fRedBlockError;
if (a_fEffort <= 24.5f)
{
m_boolDone = true;
}
break;
case 2:
CalculateR11(8, 12.0f, 1.0f);
m_fError = m_fRedBlockError;
if (a_fEffort <= 49.5f)
{
m_boolDone = true;
}
break;
case 3:
CalculateR11(7, 6.0f, 1.0f);
m_fError = m_fRedBlockError;
break;
case 4:
CalculateR11(6, 3.0f, 1.0f);
m_fError = m_fRedBlockError;
break;
case 5:
CalculateR11(5, 1.0f, 0.0f);
m_fError = m_fRedBlockError;
m_boolDone = true;
break;
default:
assert(0);
break;
}
m_uiEncodingIterations++;
SetDoneIfPerfect();
}
// ----------------------------------------------------------------------------------------------------
// find the best combination of base color, multiplier and selectors
//
// a_uiSelectorsUsed limits the number of selector combinations to try
// a_fBaseRadius limits the range of base colors to try
// a_fMultiplierRadius limits the range of multipliers to try
//
void Block4x4Encoding_R11::CalculateR11(unsigned int a_uiSelectorsUsed,
float a_fBaseRadius, float a_fMultiplierRadius)
{
// maps from virtual (monotonic) selector to ETC selector
static const unsigned int auiVirtualSelectorMap[8] = {3, 2, 1, 0, 4, 5, 6, 7};
// find min/max red
float fMinRed = 1.0f;
float fMaxRed = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
// ignore border pixels
float fAlpha = m_pafrgbaSource[uiPixel].fA;
if (isnan(fAlpha))
{
continue;
}
float fRed = m_pafrgbaSource[uiPixel].fR;
if (fRed < fMinRed)
{
fMinRed = fRed;
}
if (fRed > fMaxRed)
{
fMaxRed = fRed;
}
}
assert(fMinRed <= fMaxRed);
float fRedRange = (fMaxRed - fMinRed);
// try each modifier table entry
for (unsigned int uiTableEntry = 0; uiTableEntry < MODIFIER_TABLE_ENTRYS; uiTableEntry++)
{
for (unsigned int uiMinVirtualSelector = 0;
uiMinVirtualSelector <= (8- a_uiSelectorsUsed);
uiMinVirtualSelector++)
{
unsigned int uiMaxVirtualSelector = uiMinVirtualSelector + a_uiSelectorsUsed - 1;
unsigned int uiMinSelector = auiVirtualSelectorMap[uiMinVirtualSelector];
unsigned int uiMaxSelector = auiVirtualSelectorMap[uiMaxVirtualSelector];
float fTableEntryCenter = -s_aafModifierTable[uiTableEntry][uiMinSelector];
float fTableEntryRange = s_aafModifierTable[uiTableEntry][uiMaxSelector] -
s_aafModifierTable[uiTableEntry][uiMinSelector];
float fCenterRatio = fTableEntryCenter / fTableEntryRange;
float fCenter = fMinRed + fCenterRatio*fRedRange;
fCenter = roundf(255.0f * fCenter) / 255.0f;
float fMinBase = fCenter - (a_fBaseRadius / 255.0f);
if (fMinBase < 0.0f)
{
fMinBase = 0.0f;
}
float fMaxBase = fCenter + (a_fBaseRadius / 255.0f);
if (fMaxBase > 1.0f)
{
fMaxBase = 1.0f;
}
for (float fBase = fMinBase; fBase <= fMaxBase; fBase += (0.999999f / 255.0f))
{
float fRangeMultiplier = roundf(fRedRange / fTableEntryRange);
float fMinMultiplier = fRangeMultiplier - a_fMultiplierRadius;
if (fMinMultiplier < 1.0f)
{
fMinMultiplier = 0.0f;
}
else if (fMinMultiplier > 15.0f)
{
fMinMultiplier = 15.0f;
}
float fMaxMultiplier = fRangeMultiplier + a_fMultiplierRadius;
if (fMaxMultiplier < 1.0f)
{
fMaxMultiplier = 1.0f;
}
else if (fMaxMultiplier > 15.0f)
{
fMaxMultiplier = 15.0f;
}
for (float fMultiplier = fMinMultiplier; fMultiplier <= fMaxMultiplier; fMultiplier += 1.0f)
{
// find best selector for each pixel
unsigned int auiBestSelectors[PIXELS];
float afBestRedError[PIXELS];
float afBestPixelRed[PIXELS];
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
float fBestPixelRedError = FLT_MAX;
for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
{
float fPixelRed = DecodePixelRed(fBase * 255.0f, fMultiplier, uiTableEntry, uiSelector);
ColorFloatRGBA frgba(fPixelRed, m_pafrgbaSource[uiPixel].fG,0.0f,1.0f);
float fPixelRedError = CalcPixelError(frgba, 1.0f, m_pafrgbaSource[uiPixel]);
if (fPixelRedError < fBestPixelRedError)
{
fBestPixelRedError = fPixelRedError;
auiBestSelectors[uiPixel] = uiSelector;
afBestRedError[uiPixel] = fBestPixelRedError;
afBestPixelRed[uiPixel] = fPixelRed;
}
}
}
float fBlockError = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
fBlockError += afBestRedError[uiPixel];
}
if (fBlockError < m_fRedBlockError)
{
m_fRedBlockError = fBlockError;
if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
{
m_fRedBase = 255.0f * fBase;
}
else if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
m_fRedBase = (fBase * 255) - 128;
}
else
{
assert(0);
}
m_fRedMultiplier = fMultiplier;
m_uiRedModifierTableIndex = uiTableEntry;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_auiRedSelectors[uiPixel] = auiBestSelectors[uiPixel];
float fBestPixelRed = afBestPixelRed[uiPixel];
m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA(fBestPixelRed, 0.0f, 0.0f, 1.0f);
m_afDecodedAlphas[uiPixel] = 1.0f;
}
}
}
}
}
}
}
// ----------------------------------------------------------------------------------------------------
// set the encoding bits based on encoding state
//
void Block4x4Encoding_R11::SetEncodingBits(void)
{
if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
{
m_pencodingbitsR11->data.base = (unsigned char)roundf(m_fRedBase);
}
else if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
m_pencodingbitsR11->data.base = (signed char)roundf(m_fRedBase);
}
else
{
assert(0);
}
m_pencodingbitsR11->data.table = m_uiRedModifierTableIndex;
m_pencodingbitsR11->data.multiplier = (unsigned char)roundf(m_fRedMultiplier);
unsigned long long int ulliSelectorBits = 0;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
unsigned int uiShift = 45 - (3 * uiPixel);
ulliSelectorBits |= ((unsigned long long int)m_auiRedSelectors[uiPixel]) << uiShift;
}
m_pencodingbitsR11->data.selectors0 = ulliSelectorBits >> 40;
m_pencodingbitsR11->data.selectors1 = ulliSelectorBits >> 32;
m_pencodingbitsR11->data.selectors2 = ulliSelectorBits >> 24;
m_pencodingbitsR11->data.selectors3 = ulliSelectorBits >> 16;
m_pencodingbitsR11->data.selectors4 = ulliSelectorBits >> 8;
m_pencodingbitsR11->data.selectors5 = ulliSelectorBits;
}
// ----------------------------------------------------------------------------------------------------
//
}

@ -0,0 +1,122 @@
/*
* 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 "EtcBlock4x4Encoding_RGB8.h"
namespace Etc
{
class Block4x4EncodingBits_R11;
// ################################################################################
// Block4x4Encoding_R11
// ################################################################################
class Block4x4Encoding_R11 : public Block4x4Encoding_RGB8
{
public:
Block4x4Encoding_R11(void);
virtual ~Block4x4Encoding_R11(void);
virtual void InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric);
virtual void InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
virtual void PerformIteration(float a_fEffort);
virtual void SetEncodingBits(void);
inline float GetRedBase(void) const
{
return m_fRedBase;
}
inline float GetRedMultiplier(void) const
{
return m_fRedMultiplier;
}
inline int GetRedTableIndex(void) const
{
return m_uiRedModifierTableIndex;
}
inline const unsigned int * GetRedSelectors(void) const
{
return m_auiRedSelectors;
}
protected:
static const unsigned int MODIFIER_TABLE_ENTRYS = 16;
static const unsigned int SELECTOR_BITS = 3;
static const unsigned int SELECTORS = 1 << SELECTOR_BITS;
static float s_aafModifierTable[MODIFIER_TABLE_ENTRYS][SELECTORS];
void CalculateR11(unsigned int a_uiSelectorsUsed,
float a_fBaseRadius, float a_fMultiplierRadius);
inline float DecodePixelRed(float a_fBase, float a_fMultiplier,
unsigned int a_uiTableIndex, unsigned int a_uiSelector)
{
float fMultiplier = a_fMultiplier;
if (fMultiplier <= 0.0f)
{
fMultiplier = 1.0f / 8.0f;
}
float fPixelRed = a_fBase * 8 + 4 +
8 * fMultiplier*s_aafModifierTable[a_uiTableIndex][a_uiSelector]*255;
fPixelRed /= 2047.0f;
if (fPixelRed < 0.0f)
{
fPixelRed = 0.0f;
}
else if (fPixelRed > 1.0f)
{
fPixelRed = 1.0f;
}
return fPixelRed;
}
Block4x4EncodingBits_R11 *m_pencodingbitsR11;
float m_fRedBase;
float m_fRedMultiplier;
float m_fRedBlockError;
unsigned int m_uiRedModifierTableIndex;
unsigned int m_auiRedSelectors[PIXELS];
};
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

@ -0,0 +1,447 @@
/*
* 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.
*/
/*
EtcBlock4x4Encoding_RG11.cpp
Block4x4Encoding_RG11 is the encoder to use when targetting file format RG11 and SRG11 (signed RG11).
*/
#include "EtcConfig.h"
#include "EtcBlock4x4Encoding_RG11.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcBlock4x4.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <float.h>
#include <limits>
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
//
Block4x4Encoding_RG11::Block4x4Encoding_RG11(void)
{
m_pencodingbitsRG11 = nullptr;
}
Block4x4Encoding_RG11::~Block4x4Encoding_RG11(void) {}
// ----------------------------------------------------------------------------------------------------
// initialization prior to encoding
// a_pblockParent points to the block associated with this encoding
// a_errormetric is used to choose the best encoding
// a_pafrgbaSource points to a 4x4 block subset of the source image
// a_paucEncodingBits points to the final encoding bits
//
void Block4x4Encoding_RG11::InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric)
{
Block4x4Encoding::Init(a_pblockParent, a_pafrgbaSource,a_errormetric);
m_pencodingbitsRG11 = (Block4x4EncodingBits_RG11 *)a_paucEncodingBits;
}
// ----------------------------------------------------------------------------------------------------
// initialization from the encoding bits of a previous encoding
// a_pblockParent points to the block associated with this encoding
// a_errormetric is used to choose the best encoding
// a_pafrgbaSource points to a 4x4 block subset of the source image
// a_paucEncodingBits points to the final encoding bits of a previous encoding
//
void Block4x4Encoding_RG11::InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric)
{
m_pencodingbitsRG11 = (Block4x4EncodingBits_RG11 *)a_paucEncodingBits;
// init RGB portion
Block4x4Encoding_RGB8::InitFromEncodingBits(a_pblockParent,
(unsigned char *)m_pencodingbitsRG11,
a_pafrgbaSource,
a_errormetric);
m_fError = 0.0f;
{
m_mode = MODE_RG11;
if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
m_fRedBase = (float)(signed char)m_pencodingbitsRG11->data.baseR;
m_fGrnBase = (float)(signed char)m_pencodingbitsRG11->data.baseG;
}
else
{
m_fRedBase = (float)(unsigned char)m_pencodingbitsRG11->data.baseR;
m_fGrnBase = (float)(unsigned char)m_pencodingbitsRG11->data.baseG;
}
m_fRedMultiplier = (float)m_pencodingbitsRG11->data.multiplierR;
m_fGrnMultiplier = (float)m_pencodingbitsRG11->data.multiplierG;
m_uiRedModifierTableIndex = m_pencodingbitsRG11->data.tableIndexR;
m_uiGrnModifierTableIndex = m_pencodingbitsRG11->data.tableIndexG;
unsigned long long int ulliSelectorBitsR = 0;
ulliSelectorBitsR |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsR0 << 40;
ulliSelectorBitsR |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsR1 << 32;
ulliSelectorBitsR |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsR2 << 24;
ulliSelectorBitsR |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsR3 << 16;
ulliSelectorBitsR |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsR4 << 8;
ulliSelectorBitsR |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsR5;
unsigned long long int ulliSelectorBitsG = 0;
ulliSelectorBitsG |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsG0 << 40;
ulliSelectorBitsG |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsG1 << 32;
ulliSelectorBitsG |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsG2 << 24;
ulliSelectorBitsG |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsG3 << 16;
ulliSelectorBitsG |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsG4 << 8;
ulliSelectorBitsG |= (unsigned long long int)m_pencodingbitsRG11->data.selectorsG5;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
unsigned int uiShift = 45 - (3 * uiPixel);
m_auiRedSelectors[uiPixel] = (ulliSelectorBitsR >> uiShift) & (SELECTORS - 1);
m_auiGrnSelectors[uiPixel] = (ulliSelectorBitsG >> uiShift) & (SELECTORS - 1);
}
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
float fRedDecodedData = 0.0f;
float fGrnDecodedData = 0.0f;
if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
{
fRedDecodedData = DecodePixelRed(m_fRedBase, m_fRedMultiplier, m_uiRedModifierTableIndex, m_auiRedSelectors[uiPixel]);
fGrnDecodedData = DecodePixelRed(m_fGrnBase, m_fGrnMultiplier, m_uiGrnModifierTableIndex, m_auiGrnSelectors[uiPixel]);
}
else if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
fRedDecodedData = DecodePixelRed(m_fRedBase + 128, m_fRedMultiplier, m_uiRedModifierTableIndex, m_auiRedSelectors[uiPixel]);
fGrnDecodedData = DecodePixelRed(m_fGrnBase + 128, m_fGrnMultiplier, m_uiGrnModifierTableIndex, m_auiGrnSelectors[uiPixel]);
}
else
{
assert(0);
}
m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA(fRedDecodedData, fGrnDecodedData, 0.0f, 1.0f);
}
}
CalcBlockError();
}
// ----------------------------------------------------------------------------------------------------
// perform a single encoding iteration
// replace the encoding if a better encoding was found
// subsequent iterations generally take longer for each iteration
// set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
//
void Block4x4Encoding_RG11::PerformIteration(float a_fEffort)
{
assert(!m_boolDone);
switch (m_uiEncodingIterations)
{
case 0:
m_fError = FLT_MAX;
m_fGrnBlockError = FLT_MAX; // artificially high value
m_fRedBlockError = FLT_MAX;
CalculateR11(8, 0.0f, 0.0f);
CalculateG11(8, 0.0f, 0.0f);
m_fError = (m_fGrnBlockError + m_fRedBlockError);
break;
case 1:
CalculateR11(8, 2.0f, 1.0f);
CalculateG11(8, 2.0f, 1.0f);
m_fError = (m_fGrnBlockError + m_fRedBlockError);
if (a_fEffort <= 24.5f)
{
m_boolDone = true;
}
break;
case 2:
CalculateR11(8, 12.0f, 1.0f);
CalculateG11(8, 12.0f, 1.0f);
m_fError = (m_fGrnBlockError + m_fRedBlockError);
if (a_fEffort <= 49.5f)
{
m_boolDone = true;
}
break;
case 3:
CalculateR11(7, 6.0f, 1.0f);
CalculateG11(7, 6.0f, 1.0f);
m_fError = (m_fGrnBlockError + m_fRedBlockError);
break;
case 4:
CalculateR11(6, 3.0f, 1.0f);
CalculateG11(6, 3.0f, 1.0f);
m_fError = (m_fGrnBlockError + m_fRedBlockError);
break;
case 5:
CalculateR11(5, 1.0f, 0.0f);
CalculateG11(5, 1.0f, 0.0f);
m_fError = (m_fGrnBlockError + m_fRedBlockError);
m_boolDone = true;
break;
default:
assert(0);
break;
}
m_uiEncodingIterations++;
SetDoneIfPerfect();
}
// ----------------------------------------------------------------------------------------------------
// find the best combination of base color, multiplier and selectors
//
// a_uiSelectorsUsed limits the number of selector combinations to try
// a_fBaseRadius limits the range of base colors to try
// a_fMultiplierRadius limits the range of multipliers to try
//
void Block4x4Encoding_RG11::CalculateG11(unsigned int a_uiSelectorsUsed,
float a_fBaseRadius, float a_fMultiplierRadius)
{
// maps from virtual (monotonic) selector to etc selector
static const unsigned int auiVirtualSelectorMap[8] = { 3, 2, 1, 0, 4, 5, 6, 7 };
// find min/max Grn
float fMinGrn = 1.0f;
float fMaxGrn = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
// ignore border pixels
float fAlpha = m_pafrgbaSource[uiPixel].fA;
if (isnan(fAlpha))
{
continue;
}
float fGrn = m_pafrgbaSource[uiPixel].fG;
if (fGrn < fMinGrn)
{
fMinGrn = fGrn;
}
if (fGrn > fMaxGrn)
{
fMaxGrn = fGrn;
}
}
assert(fMinGrn <= fMaxGrn);
float fGrnRange = (fMaxGrn - fMinGrn);
// try each modifier table entry
for (unsigned int uiTableEntry = 0; uiTableEntry < MODIFIER_TABLE_ENTRYS; uiTableEntry++)
{
for (unsigned int uiMinVirtualSelector = 0;
uiMinVirtualSelector <= (8 - a_uiSelectorsUsed);
uiMinVirtualSelector++)
{
unsigned int uiMaxVirtualSelector = uiMinVirtualSelector + a_uiSelectorsUsed - 1;
unsigned int uiMinSelector = auiVirtualSelectorMap[uiMinVirtualSelector];
unsigned int uiMaxSelector = auiVirtualSelectorMap[uiMaxVirtualSelector];
float fTableEntryCenter = -s_aafModifierTable[uiTableEntry][uiMinSelector];
float fTableEntryRange = s_aafModifierTable[uiTableEntry][uiMaxSelector] -
s_aafModifierTable[uiTableEntry][uiMinSelector];
float fCenterRatio = fTableEntryCenter / fTableEntryRange;
float fCenter = fMinGrn + fCenterRatio*fGrnRange;
fCenter = roundf(255.0f * fCenter) / 255.0f;
float fMinBase = fCenter - (a_fBaseRadius / 255.0f);
if (fMinBase < 0.0f)
{
fMinBase = 0.0f;
}
float fMaxBase = fCenter + (a_fBaseRadius / 255.0f);
if (fMaxBase > 1.0f)
{
fMaxBase = 1.0f;
}
for (float fBase = fMinBase; fBase <= fMaxBase; fBase += (0.999999f / 255.0f))
{
float fRangeMultiplier = roundf(fGrnRange / fTableEntryRange);
float fMinMultiplier = fRangeMultiplier - a_fMultiplierRadius;
if (fMinMultiplier < 1.0f)
{
fMinMultiplier = 0.0f;
}
else if (fMinMultiplier > 15.0f)
{
fMinMultiplier = 15.0f;
}
float fMaxMultiplier = fRangeMultiplier + a_fMultiplierRadius;
if (fMaxMultiplier < 1.0f)
{
fMaxMultiplier = 1.0f;
}
else if (fMaxMultiplier > 15.0f)
{
fMaxMultiplier = 15.0f;
}
for (float fMultiplier = fMinMultiplier; fMultiplier <= fMaxMultiplier; fMultiplier += 1.0f)
{
// find best selector for each pixel
unsigned int auiBestSelectors[PIXELS];
float afBestGrnError[PIXELS];
float afBestPixelGrn[PIXELS];
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
float fBestPixelGrnError = FLT_MAX;
for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
{
//DecodePixelRed is not red channel specific
float fPixelGrn = DecodePixelRed(fBase * 255.0f, fMultiplier, uiTableEntry, uiSelector);
ColorFloatRGBA frgba(m_pafrgbaSource[uiPixel].fR, fPixelGrn, 0.0f, 1.0f);
float fPixelGrnError = CalcPixelError(frgba, 1.0f, m_pafrgbaSource[uiPixel]);
if (fPixelGrnError < fBestPixelGrnError)
{
fBestPixelGrnError = fPixelGrnError;
auiBestSelectors[uiPixel] = uiSelector;
afBestGrnError[uiPixel] = fBestPixelGrnError;
afBestPixelGrn[uiPixel] = fPixelGrn;
}
}
}
float fBlockError = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
fBlockError += afBestGrnError[uiPixel];
}
if (fBlockError < m_fGrnBlockError)
{
m_fGrnBlockError = fBlockError;
if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
{
m_fGrnBase = 255.0f * fBase;
}
else if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
m_fGrnBase = (fBase * 255) - 128;
}
else
{
assert(0);
}
m_fGrnMultiplier = fMultiplier;
m_uiGrnModifierTableIndex = uiTableEntry;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_auiGrnSelectors[uiPixel] = auiBestSelectors[uiPixel];
m_afrgbaDecodedColors[uiPixel].fG = afBestPixelGrn[uiPixel];
m_afDecodedAlphas[uiPixel] = 1.0f;
}
}
}
}
}
}
}
// ----------------------------------------------------------------------------------------------------
// set the encoding bits based on encoding state
//
void Block4x4Encoding_RG11::SetEncodingBits(void)
{
unsigned long long int ulliSelectorBitsR = 0;
unsigned long long int ulliSelectorBitsG = 0;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
unsigned int uiShift = 45 - (3 * uiPixel);
ulliSelectorBitsR |= ((unsigned long long int)m_auiRedSelectors[uiPixel]) << uiShift;
ulliSelectorBitsG |= ((unsigned long long int)m_auiGrnSelectors[uiPixel]) << uiShift;
}
if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
{
m_pencodingbitsRG11->data.baseR = (unsigned char)roundf(m_fRedBase);
}
else if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
m_pencodingbitsRG11->data.baseR = (signed char)roundf(m_fRedBase);
}
else
{
assert(0);
}
m_pencodingbitsRG11->data.tableIndexR = m_uiRedModifierTableIndex;
m_pencodingbitsRG11->data.multiplierR = (unsigned char)roundf(m_fRedMultiplier);
m_pencodingbitsRG11->data.selectorsR0 = ulliSelectorBitsR >> 40;
m_pencodingbitsRG11->data.selectorsR1 = ulliSelectorBitsR >> 32;
m_pencodingbitsRG11->data.selectorsR2 = ulliSelectorBitsR >> 24;
m_pencodingbitsRG11->data.selectorsR3 = ulliSelectorBitsR >> 16;
m_pencodingbitsRG11->data.selectorsR4 = ulliSelectorBitsR >> 8;
m_pencodingbitsRG11->data.selectorsR5 = ulliSelectorBitsR;
if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
{
m_pencodingbitsRG11->data.baseG = (unsigned char)roundf(m_fGrnBase);
}
else if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
{
m_pencodingbitsRG11->data.baseG = (signed char)roundf(m_fGrnBase);
}
else
{
assert(0);
}
m_pencodingbitsRG11->data.tableIndexG = m_uiGrnModifierTableIndex;
m_pencodingbitsRG11->data.multiplierG = (unsigned char)roundf(m_fGrnMultiplier);
m_pencodingbitsRG11->data.selectorsG0 = ulliSelectorBitsG >> 40;
m_pencodingbitsRG11->data.selectorsG1 = ulliSelectorBitsG >> 32;
m_pencodingbitsRG11->data.selectorsG2 = ulliSelectorBitsG >> 24;
m_pencodingbitsRG11->data.selectorsG3 = ulliSelectorBitsG >> 16;
m_pencodingbitsRG11->data.selectorsG4 = ulliSelectorBitsG >> 8;
m_pencodingbitsRG11->data.selectorsG5 = ulliSelectorBitsG;
}
// ----------------------------------------------------------------------------------------------------
//
}

@ -0,0 +1,86 @@
/*
* 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 "EtcBlock4x4Encoding_RGB8.h"
#include "EtcBlock4x4Encoding_R11.h"
namespace Etc
{
class Block4x4EncodingBits_RG11;
// ################################################################################
// Block4x4Encoding_RG11
// ################################################################################
class Block4x4Encoding_RG11 : public Block4x4Encoding_R11
{
float m_fGrnBase;
float m_fGrnMultiplier;
float m_fGrnBlockError;
unsigned int m_auiGrnSelectors[PIXELS];
unsigned int m_uiGrnModifierTableIndex;
public:
Block4x4Encoding_RG11(void);
virtual ~Block4x4Encoding_RG11(void);
virtual void InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric);
virtual void InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
virtual void PerformIteration(float a_fEffort);
virtual void SetEncodingBits(void);
Block4x4EncodingBits_RG11 *m_pencodingbitsRG11;
void CalculateG11(unsigned int a_uiSelectorsUsed, float a_fBaseRadius, float a_fMultiplierRadius);
inline float GetGrnBase(void) const
{
return m_fGrnBase;
}
inline float GetGrnMultiplier(void) const
{
return m_fGrnMultiplier;
}
inline int GetGrnTableIndex(void) const
{
return m_uiGrnModifierTableIndex;
}
inline const unsigned int * GetGrnSelectors(void) const
{
return m_auiGrnSelectors;
}
};
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

File diff suppressed because it is too large Load Diff

@ -0,0 +1,96 @@
/*
* 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 "EtcBlock4x4Encoding_ETC1.h"
namespace Etc
{
class Block4x4Encoding_RGB8 : public Block4x4Encoding_ETC1
{
public:
Block4x4Encoding_RGB8(void);
virtual ~Block4x4Encoding_RGB8(void);
virtual void InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
virtual void PerformIteration(float a_fEffort);
virtual void SetEncodingBits(void);
inline ColorFloatRGBA GetColor3(void) const
{
return m_frgbaColor3;
}
protected:
static const unsigned int PLANAR_CORNER_COLORS = 3;
static const unsigned int MAX_PLANAR_REGRESSION_SIZE = 4;
static const unsigned int TH_DISTANCES = 8;
static float s_afTHDistanceTable[TH_DISTANCES];
void TryPlanar(unsigned int a_uiRadius);
void TryTAndH(unsigned int a_uiRadius);
void InitFromEncodingBits_Planar(void);
ColorFloatRGBA m_frgbaColor3; // used for planar
void SetEncodingBits_T(void);
void SetEncodingBits_H(void);
void SetEncodingBits_Planar(void);
// state shared between iterations
ColorFloatRGBA m_frgbaOriginalColor1_TAndH;
ColorFloatRGBA m_frgbaOriginalColor2_TAndH;
void CalculateBaseColorsForTAndH(void);
void TryT(unsigned int a_uiRadius);
void TryT_BestSelectorCombination(void);
void TryH(unsigned int a_uiRadius);
void TryH_BestSelectorCombination(void);
private:
void InitFromEncodingBits_T(void);
void InitFromEncodingBits_H(void);
void CalculatePlanarCornerColors(void);
void ColorRegression(ColorFloatRGBA *a_pafrgbaPixels, unsigned int a_uiPixels,
ColorFloatRGBA *a_pfrgbaSlope, ColorFloatRGBA *a_pfrgbaOffset);
bool TwiddlePlanar(void);
bool TwiddlePlanarR();
bool TwiddlePlanarG();
bool TwiddlePlanarB();
void DecodePixels_T(void);
void DecodePixels_H(void);
void DecodePixels_Planar(void);
};
} // namespace Etc

File diff suppressed because it is too large Load Diff

@ -0,0 +1,129 @@
/*
* 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 "EtcBlock4x4Encoding_RGB8.h"
#include "EtcErrorMetric.h"
#include "EtcBlock4x4EncodingBits.h"
namespace Etc
{
// ################################################################################
// Block4x4Encoding_RGB8A1
// RGB8A1 if not completely opaque or transparent
// ################################################################################
class Block4x4Encoding_RGB8A1 : public Block4x4Encoding_RGB8
{
public:
static const unsigned int TRANSPARENT_SELECTOR = 2;
Block4x4Encoding_RGB8A1(void);
virtual ~Block4x4Encoding_RGB8A1(void);
virtual void InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits,
ErrorMetric a_errormetric);
virtual void InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
virtual void PerformIteration(float a_fEffort);
virtual void SetEncodingBits(void);
void InitFromEncodingBits_ETC1(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
void InitFromEncodingBits_T(void);
void InitFromEncodingBits_H(void);
void PerformFirstIteration(void);
void Decode_ETC1(void);
void DecodePixels_T(void);
void DecodePixels_H(void);
void SetEncodingBits_ETC1(void);
void SetEncodingBits_T(void);
void SetEncodingBits_H(void);
protected:
bool m_boolOpaque; // all source pixels have alpha >= 0.5
bool m_boolTransparent; // all source pixels have alpha < 0.5
bool m_boolPunchThroughPixels; // some source pixels have alpha < 0.5
static float s_aafCwOpaqueUnsetTable[CW_RANGES][SELECTORS];
private:
void TryDifferential(bool a_boolFlip, unsigned int a_uiRadius,
int a_iGrayOffset1, int a_iGrayOffset2);
void TryDifferentialHalf(DifferentialTrys::Half *a_phalf);
void TryT(unsigned int a_uiRadius);
void TryT_BestSelectorCombination(void);
void TryH(unsigned int a_uiRadius);
void TryH_BestSelectorCombination(void);
void TryDegenerates1(void);
void TryDegenerates2(void);
void TryDegenerates3(void);
void TryDegenerates4(void);
};
// ################################################################################
// Block4x4Encoding_RGB8A1_Opaque
// RGB8A1 if all pixels have alpha==1
// ################################################################################
class Block4x4Encoding_RGB8A1_Opaque : public Block4x4Encoding_RGB8A1
{
public:
virtual void PerformIteration(float a_fEffort);
void PerformFirstIteration(void);
private:
};
// ################################################################################
// Block4x4Encoding_RGB8A1_Transparent
// RGB8A1 if all pixels have alpha==0
// ################################################################################
class Block4x4Encoding_RGB8A1_Transparent : public Block4x4Encoding_RGB8A1
{
public:
virtual void PerformIteration(float a_fEffort);
private:
};
} // namespace Etc

@ -0,0 +1,474 @@
/*
* 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.
*/
/*
EtcBlock4x4Encoding_RGBA8.cpp contains:
Block4x4Encoding_RGBA8
Block4x4Encoding_RGBA8_Opaque
Block4x4Encoding_RGBA8_Transparent
These encoders are used when targetting file format RGBA8.
Block4x4Encoding_RGBA8_Opaque is used when all pixels in the 4x4 block are opaque
Block4x4Encoding_RGBA8_Transparent is used when all pixels in the 4x4 block are transparent
Block4x4Encoding_RGBA8 is used when there is a mixture of alphas in the 4x4 block
*/
#include "EtcConfig.h"
#include "EtcBlock4x4Encoding_RGBA8.h"
#include "EtcBlock4x4EncodingBits.h"
#include "EtcBlock4x4.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <float.h>
#include <limits>
namespace Etc
{
// ####################################################################################################
// Block4x4Encoding_RGBA8
// ####################################################################################################
float Block4x4Encoding_RGBA8::s_aafModifierTable[MODIFIER_TABLE_ENTRYS][ALPHA_SELECTORS]
{
{ -3.0f / 255.0f, -6.0f / 255.0f, -9.0f / 255.0f, -15.0f / 255.0f, 2.0f / 255.0f, 5.0f / 255.0f, 8.0f / 255.0f, 14.0f / 255.0f },
{ -3.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, -13.0f / 255.0f, 2.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f, 12.0f / 255.0f },
{ -2.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -13.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 12.0f / 255.0f },
{ -2.0f / 255.0f, -4.0f / 255.0f, -6.0f / 255.0f, -13.0f / 255.0f, 1.0f / 255.0f, 3.0f / 255.0f, 5.0f / 255.0f, 12.0f / 255.0f },
{ -3.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -12.0f / 255.0f, 2.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 11.0f / 255.0f },
{ -3.0f / 255.0f, -7.0f / 255.0f, -9.0f / 255.0f, -11.0f / 255.0f, 2.0f / 255.0f, 6.0f / 255.0f, 8.0f / 255.0f, 10.0f / 255.0f },
{ -4.0f / 255.0f, -7.0f / 255.0f, -8.0f / 255.0f, -11.0f / 255.0f, 3.0f / 255.0f, 6.0f / 255.0f, 7.0f / 255.0f, 10.0f / 255.0f },
{ -3.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -11.0f / 255.0f, 2.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 10.0f / 255.0f },
{ -2.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
{ -2.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
{ -2.0f / 255.0f, -4.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 3.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
{ -2.0f / 255.0f, -5.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f },
{ -3.0f / 255.0f, -4.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f },
{ -1.0f / 255.0f, -2.0f / 255.0f, -3.0f / 255.0f, -10.0f / 255.0f, 0.0f / 255.0f, 1.0f / 255.0f, 2.0f / 255.0f, 9.0f / 255.0f },
{ -4.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -9.0f / 255.0f, 3.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 8.0f / 255.0f },
{ -3.0f / 255.0f, -5.0f / 255.0f, -7.0f / 255.0f, -9.0f / 255.0f, 2.0f / 255.0f, 4.0f / 255.0f, 6.0f / 255.0f, 8.0f / 255.0f }
};
// ----------------------------------------------------------------------------------------------------
//
Block4x4Encoding_RGBA8::Block4x4Encoding_RGBA8(void)
{
m_pencodingbitsA8 = nullptr;
}
Block4x4Encoding_RGBA8::~Block4x4Encoding_RGBA8(void) {}
// ----------------------------------------------------------------------------------------------------
// initialization prior to encoding
// a_pblockParent points to the block associated with this encoding
// a_errormetric is used to choose the best encoding
// a_pafrgbaSource points to a 4x4 block subset of the source image
// a_paucEncodingBits points to the final encoding bits
//
void Block4x4Encoding_RGBA8::InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric)
{
Block4x4Encoding::Init(a_pblockParent, a_pafrgbaSource,a_errormetric);
m_pencodingbitsA8 = (Block4x4EncodingBits_A8 *)a_paucEncodingBits;
m_pencodingbitsRGB8 = (Block4x4EncodingBits_RGB8 *)(a_paucEncodingBits + sizeof(Block4x4EncodingBits_A8));
}
// ----------------------------------------------------------------------------------------------------
// initialization from the encoding bits of a previous encoding
// a_pblockParent points to the block associated with this encoding
// a_errormetric is used to choose the best encoding
// a_pafrgbaSource points to a 4x4 block subset of the source image
// a_paucEncodingBits points to the final encoding bits of a previous encoding
//
void Block4x4Encoding_RGBA8::InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric)
{
m_pencodingbitsA8 = (Block4x4EncodingBits_A8 *)a_paucEncodingBits;
m_pencodingbitsRGB8 = (Block4x4EncodingBits_RGB8 *)(a_paucEncodingBits + sizeof(Block4x4EncodingBits_A8));
// init RGB portion
Block4x4Encoding_RGB8::InitFromEncodingBits(a_pblockParent,
(unsigned char *) m_pencodingbitsRGB8,
a_pafrgbaSource,
a_errormetric);
// init A8 portion
// has to be done after InitFromEncodingBits()
{
m_fBase = m_pencodingbitsA8->data.base / 255.0f;
m_fMultiplier = (float)m_pencodingbitsA8->data.multiplier;
m_uiModifierTableIndex = m_pencodingbitsA8->data.table;
unsigned long long int ulliSelectorBits = 0;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsA8->data.selectors0 << 40;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsA8->data.selectors1 << 32;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsA8->data.selectors2 << 24;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsA8->data.selectors3 << 16;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsA8->data.selectors4 << 8;
ulliSelectorBits |= (unsigned long long int)m_pencodingbitsA8->data.selectors5;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
unsigned int uiShift = 45 - (3 * uiPixel);
m_auiAlphaSelectors[uiPixel] = (ulliSelectorBits >> uiShift) & (ALPHA_SELECTORS - 1);
}
// decode the alphas
// calc alpha error
m_fError = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_afDecodedAlphas[uiPixel] = DecodePixelAlpha(m_fBase, m_fMultiplier,
m_uiModifierTableIndex,
m_auiAlphaSelectors[uiPixel]);
float fDeltaAlpha = m_afDecodedAlphas[uiPixel] - m_pafrgbaSource[uiPixel].fA;
m_fError += fDeltaAlpha * fDeltaAlpha;
}
}
// redo error calc to include alpha
CalcBlockError();
}
// ----------------------------------------------------------------------------------------------------
// perform a single encoding iteration
// replace the encoding if a better encoding was found
// subsequent iterations generally take longer for each iteration
// set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
//
// similar to Block4x4Encoding_RGB8_Base::Encode_RGB8(), but with alpha added
//
void Block4x4Encoding_RGBA8::PerformIteration(float a_fEffort)
{
assert(!m_boolDone);
if (m_uiEncodingIterations == 0)
{
if (a_fEffort < 24.9f)
{
CalculateA8(0.0f);
}
else if (a_fEffort < 49.9f)
{
CalculateA8(1.0f);
}
else
{
CalculateA8(2.0f);
}
}
Block4x4Encoding_RGB8::PerformIteration(a_fEffort);
}
// ----------------------------------------------------------------------------------------------------
// find the best combination of base alpga, multiplier and selectors
//
// a_fRadius limits the range of base alpha to try
//
void Block4x4Encoding_RGBA8::CalculateA8(float a_fRadius)
{
// find min/max alpha
float fMinAlpha = 1.0f;
float fMaxAlpha = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
float fAlpha = m_pafrgbaSource[uiPixel].fA;
// ignore border pixels
if (isnan(fAlpha))
{
continue;
}
if (fAlpha < fMinAlpha)
{
fMinAlpha = fAlpha;
}
if (fAlpha > fMaxAlpha)
{
fMaxAlpha = fAlpha;
}
}
assert(fMinAlpha <= fMaxAlpha);
float fAlphaRange = fMaxAlpha - fMinAlpha;
// try each modifier table entry
m_fError = FLT_MAX; // artificially high value
for (unsigned int uiTableEntry = 0; uiTableEntry < MODIFIER_TABLE_ENTRYS; uiTableEntry++)
{
static const unsigned int MIN_VALUE_SELECTOR = 3;
static const unsigned int MAX_VALUE_SELECTOR = 7;
float fTableEntryCenter = -s_aafModifierTable[uiTableEntry][MIN_VALUE_SELECTOR];
float fTableEntryRange = s_aafModifierTable[uiTableEntry][MAX_VALUE_SELECTOR] -
s_aafModifierTable[uiTableEntry][MIN_VALUE_SELECTOR];
float fCenterRatio = fTableEntryCenter / fTableEntryRange;
float fCenter = fMinAlpha + fCenterRatio*fAlphaRange;
fCenter = roundf(255.0f * fCenter) / 255.0f;
float fMinBase = fCenter - (a_fRadius / 255.0f);
if (fMinBase < 0.0f)
{
fMinBase = 0.0f;
}
float fMaxBase = fCenter + (a_fRadius / 255.0f);
if (fMaxBase > 1.0f)
{
fMaxBase = 1.0f;
}
for (float fBase = fMinBase; fBase <= fMaxBase; fBase += (0.999999f / 255.0f))
{
float fRangeMultiplier = roundf(fAlphaRange / fTableEntryRange);
float fMinMultiplier = fRangeMultiplier - a_fRadius;
if (fMinMultiplier < 1.0f)
{
fMinMultiplier = 1.0f;
}
else if (fMinMultiplier > 15.0f)
{
fMinMultiplier = 15.0f;
}
float fMaxMultiplier = fRangeMultiplier + a_fRadius;
if (fMaxMultiplier < 1.0f)
{
fMaxMultiplier = 1.0f;
}
else if (fMaxMultiplier > 15.0f)
{
fMaxMultiplier = 15.0f;
}
for (float fMultiplier = fMinMultiplier; fMultiplier <= fMaxMultiplier; fMultiplier += 1.0f)
{
// find best selector for each pixel
unsigned int auiBestSelectors[PIXELS];
float afBestAlphaError[PIXELS];
float afBestDecodedAlphas[PIXELS];
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
float fBestPixelAlphaError = FLT_MAX;
for (unsigned int uiSelector = 0; uiSelector < ALPHA_SELECTORS; uiSelector++)
{
float fDecodedAlpha = DecodePixelAlpha(fBase, fMultiplier, uiTableEntry, uiSelector);
// border pixels (NAN) should have zero error
float fPixelDeltaAlpha = isnan(m_pafrgbaSource[uiPixel].fA) ?
0.0f :
fDecodedAlpha - m_pafrgbaSource[uiPixel].fA;
float fPixelAlphaError = fPixelDeltaAlpha * fPixelDeltaAlpha;
if (fPixelAlphaError < fBestPixelAlphaError)
{
fBestPixelAlphaError = fPixelAlphaError;
auiBestSelectors[uiPixel] = uiSelector;
afBestAlphaError[uiPixel] = fBestPixelAlphaError;
afBestDecodedAlphas[uiPixel] = fDecodedAlpha;
}
}
}
float fBlockError = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
fBlockError += afBestAlphaError[uiPixel];
}
if (fBlockError < m_fError)
{
m_fError = fBlockError;
m_fBase = fBase;
m_fMultiplier = fMultiplier;
m_uiModifierTableIndex = uiTableEntry;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_auiAlphaSelectors[uiPixel] = auiBestSelectors[uiPixel];
m_afDecodedAlphas[uiPixel] = afBestDecodedAlphas[uiPixel];
}
}
}
}
}
}
// ----------------------------------------------------------------------------------------------------
// set the encoding bits based on encoding state
//
void Block4x4Encoding_RGBA8::SetEncodingBits(void)
{
// set the RGB8 portion
Block4x4Encoding_RGB8::SetEncodingBits();
// set the A8 portion
{
m_pencodingbitsA8->data.base = (unsigned char)roundf(255.0f * m_fBase);
m_pencodingbitsA8->data.table = m_uiModifierTableIndex;
m_pencodingbitsA8->data.multiplier = (unsigned char)roundf(m_fMultiplier);
unsigned long long int ulliSelectorBits = 0;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
unsigned int uiShift = 45 - (3 * uiPixel);
ulliSelectorBits |= ((unsigned long long int)m_auiAlphaSelectors[uiPixel]) << uiShift;
}
m_pencodingbitsA8->data.selectors0 = ulliSelectorBits >> 40;
m_pencodingbitsA8->data.selectors1 = ulliSelectorBits >> 32;
m_pencodingbitsA8->data.selectors2 = ulliSelectorBits >> 24;
m_pencodingbitsA8->data.selectors3 = ulliSelectorBits >> 16;
m_pencodingbitsA8->data.selectors4 = ulliSelectorBits >> 8;
m_pencodingbitsA8->data.selectors5 = ulliSelectorBits;
}
}
// ####################################################################################################
// Block4x4Encoding_RGBA8_Opaque
// ####################################################################################################
// ----------------------------------------------------------------------------------------------------
// perform a single encoding iteration
// replace the encoding if a better encoding was found
// subsequent iterations generally take longer for each iteration
// set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
//
void Block4x4Encoding_RGBA8_Opaque::PerformIteration(float a_fEffort)
{
assert(!m_boolDone);
if (m_uiEncodingIterations == 0)
{
m_fError = 0.0f;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_afDecodedAlphas[uiPixel] = 1.0f;
}
}
Block4x4Encoding_RGB8::PerformIteration(a_fEffort);
}
// ----------------------------------------------------------------------------------------------------
// set the encoding bits based on encoding state
//
void Block4x4Encoding_RGBA8_Opaque::SetEncodingBits(void)
{
// set the RGB8 portion
Block4x4Encoding_RGB8::SetEncodingBits();
// set the A8 portion
m_pencodingbitsA8->data.base = 255;
m_pencodingbitsA8->data.table = 15;
m_pencodingbitsA8->data.multiplier = 15;
m_pencodingbitsA8->data.selectors0 = 0xFF;
m_pencodingbitsA8->data.selectors1 = 0xFF;
m_pencodingbitsA8->data.selectors2 = 0xFF;
m_pencodingbitsA8->data.selectors3 = 0xFF;
m_pencodingbitsA8->data.selectors4 = 0xFF;
m_pencodingbitsA8->data.selectors5 = 0xFF;
}
// ####################################################################################################
// Block4x4Encoding_RGBA8_Transparent
// ####################################################################################################
// ----------------------------------------------------------------------------------------------------
// perform a single encoding iteration
// replace the encoding if a better encoding was found
// subsequent iterations generally take longer for each iteration
// set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
//
void Block4x4Encoding_RGBA8_Transparent::PerformIteration(float )
{
assert(!m_boolDone);
assert(m_uiEncodingIterations == 0);
m_mode = MODE_ETC1;
m_boolDiff = true;
m_boolFlip = false;
for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
{
m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA();
m_afDecodedAlphas[uiPixel] = 0.0f;
}
m_fError = 0.0f;
m_boolDone = true;
m_uiEncodingIterations++;
}
// ----------------------------------------------------------------------------------------------------
// set the encoding bits based on encoding state
//
void Block4x4Encoding_RGBA8_Transparent::SetEncodingBits(void)
{
Block4x4Encoding_RGB8::SetEncodingBits();
// set the A8 portion
m_pencodingbitsA8->data.base = 0;
m_pencodingbitsA8->data.table = 0;
m_pencodingbitsA8->data.multiplier = 1;
m_pencodingbitsA8->data.selectors0 = 0;
m_pencodingbitsA8->data.selectors1 = 0;
m_pencodingbitsA8->data.selectors2 = 0;
m_pencodingbitsA8->data.selectors3 = 0;
m_pencodingbitsA8->data.selectors4 = 0;
m_pencodingbitsA8->data.selectors5 = 0;
}
// ----------------------------------------------------------------------------------------------------
//
}

@ -0,0 +1,121 @@
/*
* 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 "EtcBlock4x4Encoding_RGB8.h"
namespace Etc
{
class Block4x4EncodingBits_A8;
// ################################################################################
// Block4x4Encoding_RGBA8
// RGBA8 if not completely opaque or transparent
// ################################################################################
class Block4x4Encoding_RGBA8 : public Block4x4Encoding_RGB8
{
public:
Block4x4Encoding_RGBA8(void);
virtual ~Block4x4Encoding_RGBA8(void);
virtual void InitFromSource(Block4x4 *a_pblockParent,
ColorFloatRGBA *a_pafrgbaSource,
unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric);
virtual void InitFromEncodingBits(Block4x4 *a_pblockParent,
unsigned char *a_paucEncodingBits,
ColorFloatRGBA *a_pafrgbaSource,
ErrorMetric a_errormetric);
virtual void PerformIteration(float a_fEffort);
virtual void SetEncodingBits(void);
protected:
static const unsigned int MODIFIER_TABLE_ENTRYS = 16;
static const unsigned int ALPHA_SELECTOR_BITS = 3;
static const unsigned int ALPHA_SELECTORS = 1 << ALPHA_SELECTOR_BITS;
static float s_aafModifierTable[MODIFIER_TABLE_ENTRYS][ALPHA_SELECTORS];
void CalculateA8(float a_fRadius);
Block4x4EncodingBits_A8 *m_pencodingbitsA8; // A8 portion of Block4x4EncodingBits_RGBA8
float m_fBase;
float m_fMultiplier;
unsigned int m_uiModifierTableIndex;
unsigned int m_auiAlphaSelectors[PIXELS];
private:
inline float DecodePixelAlpha(float a_fBase, float a_fMultiplier,
unsigned int a_uiTableIndex, unsigned int a_uiSelector)
{
float fPixelAlpha = a_fBase +
a_fMultiplier*s_aafModifierTable[a_uiTableIndex][a_uiSelector];
if (fPixelAlpha < 0.0f)
{
fPixelAlpha = 0.0f;
}
else if (fPixelAlpha > 1.0f)
{
fPixelAlpha = 1.0f;
}
return fPixelAlpha;
}
};
// ################################################################################
// Block4x4Encoding_RGBA8_Opaque
// RGBA8 if all pixels have alpha==1
// ################################################################################
class Block4x4Encoding_RGBA8_Opaque : public Block4x4Encoding_RGBA8
{
public:
virtual void PerformIteration(float a_fEffort);
virtual void SetEncodingBits(void);
};
// ################################################################################
// Block4x4Encoding_RGBA8_Transparent
// RGBA8 if all pixels have alpha==0
// ################################################################################
class Block4x4Encoding_RGBA8_Transparent : public Block4x4Encoding_RGBA8
{
public:
virtual void PerformIteration(float a_fEffort);
virtual void SetEncodingBits(void);
};
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

@ -0,0 +1,173 @@
/*
* 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

@ -0,0 +1,97 @@
/*
* 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 "EtcColorFloatRGBA.h"
namespace Etc
{
class DifferentialTrys
{
public:
static const unsigned int MAX_RADIUS = 2;
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);
inline static int MoveAwayFromEdge(int a_i, int a_iDistance)
{
if (a_i < (0+ a_iDistance))
{
return (0 + a_iDistance);
}
else if (a_i > (31- a_iDistance))
{
return (31 - a_iDistance);
}
return a_i;
}
class Try
{
public :
static const unsigned int SELECTORS = 8; // per half
int m_iRed;
int m_iGreen;
int m_iBlue;
unsigned int m_uiCW;
unsigned int m_auiSelectors[SELECTORS];
float m_fError;
};
class Half
{
public:
static const unsigned int MAX_TRYS = 125;
void Init(int a_iRed, int a_iGreen, int a_iBlue,
const unsigned int *a_pauiPixelMapping,
unsigned int a_uiRadius);
// center of trys
int m_iRed;
int m_iGreen;
int m_iBlue;
const unsigned int *m_pauiPixelMapping;
unsigned int m_uiRadius;
unsigned int m_uiTrys;
Try m_atry[MAX_TRYS];
Try *m_ptryBest;
};
Half m_half1;
Half m_half2;
bool m_boolSeverelyBentColors;
};
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

@ -0,0 +1,51 @@
/*
* 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
namespace Etc
{
enum ErrorMetric
{
RGBA,
REC709,
NUMERIC,
NORMALXYZ,
//
ERROR_METRICS,
//
BT709 = REC709
};
inline const char *ErrorMetricToString(ErrorMetric errorMetric)
{
switch (errorMetric)
{
case RGBA:
return "RGBA";
case REC709:
return "REC709";
case NUMERIC:
return "NUMERIC";
case NORMALXYZ:
return "NORMALXYZ";
case ERROR_METRICS:
default:
return "UNKNOWN";
}
}
} // namespace Etc

@ -0,0 +1,85 @@
/*
* 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.
*/
/*
EtcIndividualTrys.cpp
Gathers the results of the various encoding trys for both halves of a 4x4 block for Individual mode
*/
#include "EtcConfig.h"
#include "EtcIndividualTrys.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
//
IndividualTrys::IndividualTrys(ColorFloatRGBA a_frgbaColor1, ColorFloatRGBA a_frgbaColor2,
const unsigned int *a_pauiPixelMapping1,
const unsigned int *a_pauiPixelMapping2,
unsigned int a_uiRadius)
{
assert(a_uiRadius <= MAX_RADIUS);
ColorFloatRGBA frgbaQuantizedColor1 = a_frgbaColor1.QuantizeR4G4B4();
ColorFloatRGBA frgbaQuantizedColor2 = a_frgbaColor2.QuantizeR4G4B4();
// quantize base colors
// ensure that trys with a_uiRadius don't overflow
int iRed1 = MoveAwayFromEdge(frgbaQuantizedColor1.IntRed(15.0f), a_uiRadius);
int iGreen1 = MoveAwayFromEdge(frgbaQuantizedColor1.IntGreen(15.0f), a_uiRadius);
int iBlue1 = MoveAwayFromEdge(frgbaQuantizedColor1.IntBlue(15.0f), a_uiRadius);
int iRed2 = MoveAwayFromEdge(frgbaQuantizedColor2.IntRed(15.0f), a_uiRadius);
int iGreen2 = MoveAwayFromEdge(frgbaQuantizedColor2.IntGreen(15.0f), a_uiRadius);
int iBlue2 = MoveAwayFromEdge(frgbaQuantizedColor2.IntBlue(15.0f), a_uiRadius);
m_half1.Init(iRed1, iGreen1, iBlue1, a_pauiPixelMapping1, a_uiRadius);
m_half2.Init(iRed2, iGreen2, iBlue2, a_pauiPixelMapping2, a_uiRadius);
}
// ----------------------------------------------------------------------------------------------------
//
void IndividualTrys::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

@ -0,0 +1,95 @@
/*
* 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 "EtcColorFloatRGBA.h"
namespace Etc
{
class IndividualTrys
{
public:
static const unsigned int MAX_RADIUS = 1;
IndividualTrys(ColorFloatRGBA a_frgbaColor1,
ColorFloatRGBA a_frgbaColor2,
const unsigned int *a_pauiPixelMapping1,
const unsigned int *a_pauiPixelMapping2,
unsigned int a_uiRadius);
inline static int MoveAwayFromEdge(int a_i, int a_iDistance)
{
if (a_i < (0+ a_iDistance))
{
return (0 + a_iDistance);
}
else if (a_i > (15- a_iDistance))
{
return (15 - a_iDistance);
}
return a_i;
}
class Try
{
public :
static const unsigned int SELECTORS = 8; // per half
int m_iRed;
int m_iGreen;
int m_iBlue;
unsigned int m_uiCW;
unsigned int m_auiSelectors[SELECTORS];
float m_fError;
};
class Half
{
public:
static const unsigned int MAX_TRYS = 27;
void Init(int a_iRed, int a_iGreen, int a_iBlue,
const unsigned int *a_pauiPixelMapping,
unsigned int a_uiRadius);
// center of trys
int m_iRed;
int m_iGreen;
int m_iBlue;
const unsigned int *m_pauiPixelMapping;
unsigned int m_uiRadius;
unsigned int m_uiTrys;
Try m_atry[MAX_TRYS];
Try *m_ptryBest;
};
Half m_half1;
Half m_half2;
};
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

@ -0,0 +1,228 @@
/*
* 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.
*/
/*
EtcSortedBlockList.cpp
SortedBlockList is a list of 4x4 blocks that can be used by the "effort" system to prioritize
the encoding of the 4x4 blocks.
The sorting is done with buckets, where each bucket is an indication of how much error each 4x4 block has
*/
#include "EtcConfig.h"
#include "EtcSortedBlockList.h"
#include "EtcBlock4x4.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
namespace Etc
{
// ----------------------------------------------------------------------------------------------------
// construct an empty list
//
// allocate enough memory to add all of the image's 4x4 blocks later
// allocate enough buckets to sort the blocks
//
SortedBlockList::SortedBlockList(unsigned int a_uiImageBlocks, unsigned int a_uiBuckets)
{
m_uiImageBlocks = a_uiImageBlocks;
m_iBuckets = (int)a_uiBuckets;
m_uiAddedBlocks = 0;
m_uiSortedBlocks = 0;
m_palinkPool = new Link[m_uiImageBlocks];
m_pabucket = new Bucket[m_iBuckets];
m_fMaxError = 0.0f;
InitBuckets();
}
// ----------------------------------------------------------------------------------------------------
//
SortedBlockList::~SortedBlockList(void)
{
delete[] m_palinkPool;
delete[] m_pabucket;
}
// ----------------------------------------------------------------------------------------------------
// add a 4x4 block to the list
// the 4x4 block will be sorted later
//
void SortedBlockList::AddBlock(Block4x4 *a_pblock)
{
assert(m_uiAddedBlocks < m_uiImageBlocks);
Link *plink = &m_palinkPool[m_uiAddedBlocks++];
plink->Init(a_pblock);
}
// ----------------------------------------------------------------------------------------------------
// sort all of the 4x4 blocks that have been added to the list
//
// first, determine the maximum error, then assign an error range to each bucket
// next, determine which bucket each 4x4 block belongs to based on the 4x4 block's error
// add the 4x4 block to the appropriate bucket
// lastly, walk thru the buckets and add each bucket to a sorted linked list
//
// the resultant sorting is an approximate sorting from most to least error
//
void SortedBlockList::Sort(void)
{
assert(m_uiAddedBlocks == m_uiImageBlocks);
InitBuckets();
// find max block error
m_fMaxError = -1.0f;
for (unsigned int uiLink = 0; uiLink < m_uiAddedBlocks; uiLink++)
{
Link *plinkBlock = &m_palinkPool[uiLink];
float fBlockError = plinkBlock->GetBlock()->GetError();
if (fBlockError > m_fMaxError)
{
m_fMaxError = fBlockError;
}
}
// prevent divide by zero or divide by negative
if (m_fMaxError <= 0.0f)
{
m_fMaxError = 1.0f;
}
//used for debugging
//int numDone = 0;
// put all of the blocks with unfinished encodings into the appropriate bucket
m_uiSortedBlocks = 0;
for (unsigned int uiLink = 0; uiLink < m_uiAddedBlocks; uiLink++)
{
Link *plinkBlock = &m_palinkPool[uiLink];
// if the encoding is done, don't add it to the list
if (plinkBlock->GetBlock()->GetEncoding()->IsDone())
{
//numDone++;
continue;
}
// calculate the appropriate sort bucket
float fBlockError = plinkBlock->GetBlock()->GetError();
int iBucket = (int) floorf(m_iBuckets * fBlockError / m_fMaxError);
// clamp to bucket index
iBucket = iBucket < 0 ? 0 : iBucket >= m_iBuckets ? m_iBuckets - 1 : iBucket;
// add block to bucket
{
Bucket *pbucket = &m_pabucket[iBucket];
if (pbucket->plinkLast)
{
pbucket->plinkLast->SetNext(plinkBlock);
pbucket->plinkLast = plinkBlock;
}
else
{
pbucket->plinkFirst = pbucket->plinkLast = plinkBlock;
}
plinkBlock->SetNext(nullptr);
}
m_uiSortedBlocks++;
if (0)
{
printf("%u: e=%.3f\n", uiLink, fBlockError);
Print();
printf("\n\n\n");
}
}
//printf("num blocks already done: %d\n",numDone);
//link the blocks together across buckets
m_plinkFirst = nullptr;
m_plinkLast = nullptr;
for (int iBucket = m_iBuckets - 1; iBucket >= 0; iBucket--)
{
Bucket *pbucket = &m_pabucket[iBucket];
if (pbucket->plinkFirst)
{
if (m_plinkFirst == nullptr)
{
m_plinkFirst = pbucket->plinkFirst;
}
else
{
assert(pbucket->plinkLast->GetNext() == nullptr);
m_plinkLast->SetNext(pbucket->plinkFirst);
}
m_plinkLast = pbucket->plinkLast;
}
}
}
// ----------------------------------------------------------------------------------------------------
// clear all of the buckets. normally done in preparation for a sort
//
void SortedBlockList::InitBuckets(void)
{
for (int iBucket = 0; iBucket < m_iBuckets; iBucket++)
{
Bucket *pbucket = &m_pabucket[iBucket];
pbucket->plinkFirst = 0;
pbucket->plinkLast = 0;
}
}
// ----------------------------------------------------------------------------------------------------
// print out the list of sorted 4x4 blocks
// normally used for debugging
//
void SortedBlockList::Print(void)
{
for (int iBucket = m_iBuckets-1; iBucket >= 0; iBucket--)
{
Bucket *pbucket = &m_pabucket[iBucket];
unsigned int uiBlocks = 0;
for (Link *plink = pbucket->plinkFirst; plink != nullptr; plink = plink->GetNext() )
{
uiBlocks++;
if (plink == pbucket->plinkLast)
{
break;
}
}
float fBucketError = m_fMaxError * iBucket / m_iBuckets;
float fBucketRMS = sqrtf(fBucketError / (4.0f*16.0f) );
printf("%3d: e=%.3f rms=%.6f %u\n", iBucket, fBucketError, fBucketRMS, uiBlocks);
}
}
// ----------------------------------------------------------------------------------------------------
//
} // namespace Etc

@ -0,0 +1,124 @@
/*
* 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
namespace Etc
{
class Block4x4;
class SortedBlockList
{
public:
class Link
{
public:
inline void Init(Block4x4 *a_pblock)
{
m_pblock = a_pblock;
m_plinkNext = nullptr;
}
inline Block4x4 * GetBlock(void)
{
return m_pblock;
}
inline void SetNext(Link *a_plinkNext)
{
m_plinkNext = a_plinkNext;
}
inline Link * GetNext(void)
{
return m_plinkNext;
}
inline Link * Advance(unsigned int a_uiSteps = 1)
{
Link *plink = this;
for (unsigned int uiStep = 0; uiStep < a_uiSteps; uiStep++)
{
if (plink == nullptr)
{
break;
}
plink = plink->m_plinkNext;
}
return plink;
}
private:
Block4x4 *m_pblock;
Link *m_plinkNext;
};
SortedBlockList(unsigned int a_uiImageBlocks, unsigned int a_uiBuckets);
~SortedBlockList(void);
void AddBlock(Block4x4 *a_pblock);
void Sort(void);
inline Link * GetLinkToFirstBlock(void)
{
return m_plinkFirst;
}
inline unsigned int GetNumberOfAddedBlocks(void)
{
return m_uiAddedBlocks;
}
inline unsigned int GetNumberOfSortedBlocks(void)
{
return m_uiSortedBlocks;
}
void Print(void);
private:
void InitBuckets(void);
class Bucket
{
public:
Link *plinkFirst;
Link *plinkLast;
};
unsigned int m_uiImageBlocks;
int m_iBuckets;
unsigned int m_uiAddedBlocks;
unsigned int m_uiSortedBlocks;
Link *m_palinkPool;
Bucket *m_pabucket;
float m_fMaxError;
Link *m_plinkFirst;
Link *m_plinkLast;
};
} // namespace Etc

@ -0,0 +1,7 @@
SET(BUTTERAUGLI_SRCS
butteraugli.cc
butteraugli.h)
ADD_LIBRARY(butteraugli STATIC ${BUTTERAUGLI_SRCS})

File diff suppressed because it is too large Load Diff

@ -0,0 +1,560 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.
//
// Disclaimer: This is not an official Google product.
//
// Author: Jyrki Alakuijala (jyrki.alakuijala@gmail.com)
#ifndef BUTTERAUGLI_BUTTERAUGLI_H_
#define BUTTERAUGLI_BUTTERAUGLI_H_
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <vector>
#ifndef PROFILER_ENABLED
#define PROFILER_ENABLED 0
#endif
#if PROFILER_ENABLED
#else
#define PROFILER_FUNC
#define PROFILER_ZONE(name)
#endif
#define BUTTERAUGLI_ENABLE_CHECKS 0
// This is the main interface to butteraugli image similarity
// analysis function.
namespace butteraugli {
template<typename T>
class Image;
using Image8 = Image<uint8_t>;
using ImageF = Image<float>;
using ImageD = Image<double>;
// ButteraugliInterface defines the public interface for butteraugli.
//
// It calculates the difference between rgb0 and rgb1.
//
// rgb0 and rgb1 contain the images. rgb0[c][px] and rgb1[c][px] contains
// the red image for c == 0, green for c == 1, blue for c == 2. Location index
// px is calculated as y * xsize + x.
//
// Value of pixels of images rgb0 and rgb1 need to be represented as raw
// intensity. Most image formats store gamma corrected intensity in pixel
// values. This gamma correction has to be removed, by applying the following
// function:
// butteraugli_val = 255.0 * pow(png_val / 255.0, gamma);
// A typical value of gamma is 2.2. It is usually stored in the image header.
// Take care not to confuse that value with its inverse. The gamma value should
// be always greater than one.
// Butteraugli does not work as intended if the caller does not perform
// gamma correction.
//
// diffmap will contain an image of the size xsize * ysize, containing
// localized differences for values px (indexed with the px the same as rgb0
// and rgb1). diffvalue will give a global score of similarity.
//
// A diffvalue smaller than kButteraugliGood indicates that images can be
// observed as the same image.
// diffvalue larger than kButteraugliBad indicates that a difference between
// the images can be observed.
// A diffvalue between kButteraugliGood and kButteraugliBad indicates that
// a subtle difference can be observed between the images.
//
// Returns true on success.
bool ButteraugliInterface(const std::vector<ImageF> &rgb0,
const std::vector<ImageF> &rgb1,
ImageF &diffmap,
double &diffvalue);
const double kButteraugliQuantLow = 0.26;
const double kButteraugliQuantHigh = 1.454;
// Converts the butteraugli score into fuzzy class values that are continuous
// at the class boundary. The class boundary location is based on human
// raters, but the slope is arbitrary. Particularly, it does not reflect
// the expectation value of probabilities of the human raters. It is just
// expected that a smoother class boundary will allow for higher-level
// optimization algorithms to work faster.
//
// Returns 2.0 for a perfect match, and 1.0 for 'ok', 0.0 for bad. Because the
// scoring is fuzzy, a butteraugli score of 0.96 would return a class of
// around 1.9.
double ButteraugliFuzzyClass(double score);
// Input values should be in range 0 (bad) to 2 (good). Use
// kButteraugliNormalization as normalization.
double ButteraugliFuzzyInverse(double seek);
// Returns a map which can be used for adaptive quantization. Values can
// typically range from kButteraugliQuantLow to kButteraugliQuantHigh. Low
// values require coarse quantization (e.g. near random noise), high values
// require fine quantization (e.g. in smooth bright areas).
bool ButteraugliAdaptiveQuantization(size_t xsize, size_t ysize,
const std::vector<std::vector<float> > &rgb, std::vector<float> &quant);
// Implementation details, don't use anything below or your code will
// break in the future.
#ifdef _MSC_VER
#define BUTTERAUGLI_RESTRICT __restrict
#else
#define BUTTERAUGLI_RESTRICT __restrict__
#endif
#ifdef _MSC_VER
#define BUTTERAUGLI_CACHE_ALIGNED_RETURN /* not supported */
#else
#define BUTTERAUGLI_CACHE_ALIGNED_RETURN __attribute__((assume_aligned(64)))
#endif
// Alias for unchangeable, non-aliased pointers. T is a pointer type,
// possibly to a const type. Example: ConstRestrict<uint8_t*> ptr = nullptr.
// The conventional syntax uint8_t* const RESTRICT is more confusing - it is
// not immediately obvious that the pointee is non-const.
template <typename T>
using ConstRestrict = T const BUTTERAUGLI_RESTRICT;
// Functions that depend on the cache line size.
class CacheAligned {
public:
static constexpr size_t kPointerSize = sizeof(void *);
static constexpr size_t kCacheLineSize = 64;
// The aligned-return annotation is only allowed on function declarations.
static void *Allocate(const size_t bytes) BUTTERAUGLI_CACHE_ALIGNED_RETURN;
static void Free(void *aligned_pointer);
};
template <typename T>
using CacheAlignedUniquePtrT = std::unique_ptr<T[], void (*)(void *)>;
using CacheAlignedUniquePtr = CacheAlignedUniquePtrT<uint8_t>;
template <typename T = uint8_t>
static inline CacheAlignedUniquePtrT<T> Allocate(const size_t entries) {
return CacheAlignedUniquePtrT<T>(
static_cast<ConstRestrict<T *>>(
CacheAligned::Allocate(entries * sizeof(T))),
CacheAligned::Free);
}
// Returns the smallest integer not less than "amount" that is divisible by
// "multiple", which must be a power of two.
template <size_t multiple>
static inline size_t Align(const size_t amount) {
static_assert(multiple != 0 && ((multiple & (multiple - 1)) == 0),
"Align<> argument must be a power of two");
return (amount + multiple - 1) & ~(multiple - 1);
}
// Single channel, contiguous (cache-aligned) rows separated by padding.
// T must be POD.
//
// Rationale: vectorization benefits from aligned operands - unaligned loads and
// especially stores are expensive when the address crosses cache line
// boundaries. Introducing padding after each row ensures the start of a row is
// aligned, and that row loops can process entire vectors (writes to the padding
// are allowed and ignored).
//
// We prefer a planar representation, where channels are stored as separate
// 2D arrays, because that simplifies vectorization (repeating the same
// operation on multiple adjacent components) without the complexity of a
// hybrid layout (8 R, 8 G, 8 B, ...). In particular, clients can easily iterate
// over all components in a row and Image requires no knowledge of the pixel
// format beyond the component type "T". The downside is that we duplicate the
// xsize/ysize members for each channel.
//
// This image layout could also be achieved with a vector and a row accessor
// function, but a class wrapper with support for "deleter" allows wrapping
// existing memory allocated by clients without copying the pixels. It also
// provides convenient accessors for xsize/ysize, which shortens function
// argument lists. Supports move-construction so it can be stored in containers.
template <typename ComponentType>
class Image {
// Returns cache-aligned row stride, being careful to avoid 2K aliasing.
static size_t BytesPerRow(const size_t xsize) {
// Allow reading one extra AVX-2 vector on the right margin.
const size_t row_size = xsize * sizeof(T) + 32;
const size_t align = CacheAligned::kCacheLineSize;
size_t bytes_per_row = (row_size + align - 1) & ~(align - 1);
// During the lengthy window before writes are committed to memory, CPUs
// guard against read after write hazards by checking the address, but
// only the lower 11 bits. We avoid a false dependency between writes to
// consecutive rows by ensuring their sizes are not multiples of 2 KiB.
if (bytes_per_row % 2048 == 0) {
bytes_per_row += align;
}
return bytes_per_row;
}
public:
using T = ComponentType;
Image() : xsize_(0), ysize_(0), bytes_per_row_(0), bytes_(nullptr, Ignore) {}
Image(const size_t xsize, const size_t ysize)
: xsize_(xsize),
ysize_(ysize),
bytes_per_row_(BytesPerRow(xsize)),
bytes_(Allocate(bytes_per_row_ * ysize)) {}
Image(const size_t xsize, const size_t ysize, ConstRestrict<uint8_t *> bytes,
const size_t bytes_per_row)
: xsize_(xsize),
ysize_(ysize),
bytes_per_row_(bytes_per_row),
bytes_(bytes, Ignore) {}
// Move constructor (required for returning Image from function)
Image(Image &&other)
: xsize_(other.xsize_),
ysize_(other.ysize_),
bytes_per_row_(other.bytes_per_row_),
bytes_(std::move(other.bytes_)) {}
// Move assignment (required for std::vector)
Image &operator=(Image &&other) {
xsize_ = other.xsize_;
ysize_ = other.ysize_;
bytes_per_row_ = other.bytes_per_row_;
bytes_ = std::move(other.bytes_);
return *this;
}
void Swap(Image &other) {
std::swap(xsize_, other.xsize_);
std::swap(ysize_, other.ysize_);
std::swap(bytes_per_row_, other.bytes_per_row_);
std::swap(bytes_, other.bytes_);
}
// How many pixels.
size_t xsize() const { return xsize_; }
size_t ysize() const { return ysize_; }
ConstRestrict<T *> Row(const size_t y) BUTTERAUGLI_CACHE_ALIGNED_RETURN {
#ifdef BUTTERAUGLI_ENABLE_CHECKS
if (y >= ysize_) {
printf("Row %zu out of bounds (ysize=%zu)\n", y, ysize_);
abort();
}
#endif
return reinterpret_cast<T *>(bytes_.get() + y * bytes_per_row_);
}
ConstRestrict<const T *> Row(const size_t y) const
BUTTERAUGLI_CACHE_ALIGNED_RETURN {
#ifdef BUTTERAUGLI_ENABLE_CHECKS
if (y >= ysize_) {
printf("Const row %zu out of bounds (ysize=%zu)\n", y, ysize_);
abort();
}
#endif
return reinterpret_cast<const T *>(bytes_.get() + y * bytes_per_row_);
}
// Raw access to byte contents, for interfacing with other libraries.
// Unsigned char instead of char to avoid surprises (sign extension).
ConstRestrict<uint8_t *> bytes() { return bytes_.get(); }
ConstRestrict<const uint8_t *> bytes() const { return bytes_.get(); }
size_t bytes_per_row() const { return bytes_per_row_; }
// Returns number of pixels (some of which are padding) per row. Useful for
// computing other rows via pointer arithmetic.
intptr_t PixelsPerRow() const {
static_assert(CacheAligned::kCacheLineSize % sizeof(T) == 0,
"Padding must be divisible by the pixel size.");
return static_cast<intptr_t>(bytes_per_row_ / sizeof(T));
}
private:
// Deleter used when bytes are not owned.
static void Ignore(void *ptr) {}
// (Members are non-const to enable assignment during move-assignment.)
size_t xsize_; // original intended pixels, not including any padding.
size_t ysize_;
size_t bytes_per_row_; // [bytes] including padding.
CacheAlignedUniquePtr bytes_;
};
// Returns newly allocated planes of the given dimensions.
template <typename T>
static inline std::vector<Image<T>> CreatePlanes(const size_t xsize,
const size_t ysize,
const size_t num_planes) {
std::vector<Image<T>> planes;
planes.reserve(num_planes);
for (size_t i = 0; i < num_planes; ++i) {
planes.emplace_back(xsize, ysize);
}
return planes;
}
// Returns a new image with the same dimensions and pixel values.
template <typename T>
static inline Image<T> CopyPixels(const Image<T> &other) {
Image<T> copy(other.xsize(), other.ysize());
const void *BUTTERAUGLI_RESTRICT from = other.bytes();
void *BUTTERAUGLI_RESTRICT to = copy.bytes();
memcpy(to, from, other.ysize() * other.bytes_per_row());
return copy;
}
// Returns new planes with the same dimensions and pixel values.
template <typename T>
static inline std::vector<Image<T>> CopyPlanes(
const std::vector<Image<T>> &planes) {
std::vector<Image<T>> copy;
copy.reserve(planes.size());
for (const Image<T> &plane : planes) {
copy.push_back(CopyPixels(plane));
}
return copy;
}
// Compacts a padded image into a preallocated packed vector.
template <typename T>
static inline void CopyToPacked(const Image<T> &from, std::vector<T> *to) {
const size_t xsize = from.xsize();
const size_t ysize = from.ysize();
#if BUTTERAUGLI_ENABLE_CHECKS
if (to->size() < xsize * ysize) {
printf("%zu x %zu exceeds %zu capacity\n", xsize, ysize, to->size());
abort();
}
#endif
for (size_t y = 0; y < ysize; ++y) {
ConstRestrict<const float*> row_from = from.Row(y);
ConstRestrict<float*> row_to = to->data() + y * xsize;
memcpy(row_to, row_from, xsize * sizeof(T));
}
}
// Expands a packed vector into a preallocated padded image.
template <typename T>
static inline void CopyFromPacked(const std::vector<T> &from, Image<T> *to) {
const size_t xsize = to->xsize();
const size_t ysize = to->ysize();
assert(from.size() == xsize * ysize);
for (size_t y = 0; y < ysize; ++y) {
ConstRestrict<const float*> row_from = from.data() + y * xsize;
ConstRestrict<float*> row_to = to->Row(y);
memcpy(row_to, row_from, xsize * sizeof(T));
}
}
template <typename T>
static inline std::vector<Image<T>> PlanesFromPacked(
const size_t xsize, const size_t ysize,
const std::vector<std::vector<T>> &packed) {
std::vector<Image<T>> planes;
planes.reserve(packed.size());
for (const std::vector<T> &p : packed) {
planes.push_back(Image<T>(xsize, ysize));
CopyFromPacked(p, &planes.back());
}
return planes;
}
template <typename T>
static inline std::vector<std::vector<T>> PackedFromPlanes(
const std::vector<Image<T>> &planes) {
assert(!planes.empty());
const size_t num_pixels = planes[0].xsize() * planes[0].ysize();
std::vector<std::vector<T>> packed;
packed.reserve(planes.size());
for (const Image<T> &image : planes) {
packed.push_back(std::vector<T>(num_pixels));
CopyToPacked(image, &packed.back());
}
return packed;
}
class ButteraugliComparator {
public:
ButteraugliComparator(size_t xsize, size_t ysize, int step);
// Computes the butteraugli map between rgb0 and rgb1 and updates result.
void Diffmap(const std::vector<ImageF> &rgb0,
const std::vector<ImageF> &rgb1,
ImageF &result);
// Same as above, but OpsinDynamicsImage() was already applied to
// rgb0 and rgb1.
void DiffmapOpsinDynamicsImage(const std::vector<ImageF> &rgb0,
const std::vector<ImageF> &rgb1,
ImageF &result);
private:
void BlockDiffMap(const std::vector<std::vector<float> > &rgb0,
const std::vector<std::vector<float> > &rgb1,
std::vector<float>* block_diff_dc,
std::vector<float>* block_diff_ac);
void EdgeDetectorMap(const std::vector<std::vector<float> > &rgb0,
const std::vector<std::vector<float> > &rgb1,
std::vector<float>* edge_detector_map);
void EdgeDetectorLowFreq(const std::vector<std::vector<float> > &rgb0,
const std::vector<std::vector<float> > &rgb1,
std::vector<float>* block_diff_ac);
void CombineChannels(const std::vector<std::vector<float> >& scale_xyb,
const std::vector<std::vector<float> >& scale_xyb_dc,
const std::vector<float>& block_diff_dc,
const std::vector<float>& block_diff_ac,
const std::vector<float>& edge_detector_map,
std::vector<float>* result);
const size_t xsize_;
const size_t ysize_;
const size_t num_pixels_;
const int step_;
const size_t res_xsize_;
const size_t res_ysize_;
};
void ButteraugliDiffmap(const std::vector<ImageF> &rgb0,
const std::vector<ImageF> &rgb1,
ImageF &diffmap);
double ButteraugliScoreFromDiffmap(const ImageF& distmap);
// Compute values of local frequency and dc masking based on the activity
// in the two images.
void Mask(const std::vector<std::vector<float> > &rgb0,
const std::vector<std::vector<float> > &rgb1,
size_t xsize, size_t ysize,
std::vector<std::vector<float> > *mask,
std::vector<std::vector<float> > *mask_dc);
// Computes difference metrics for one 8x8 block.
void ButteraugliBlockDiff(double rgb0[192],
double rgb1[192],
double diff_xyb_dc[3],
double diff_xyb_ac[3],
double diff_xyb_edge_dc[3]);
void OpsinAbsorbance(const double in[3], double out[3]);
void OpsinDynamicsImage(size_t xsize, size_t ysize,
std::vector<std::vector<float> > &rgb);
void MaskHighIntensityChange(
size_t xsize, size_t ysize,
const std::vector<std::vector<float> > &c0,
const std::vector<std::vector<float> > &c1,
std::vector<std::vector<float> > &rgb0,
std::vector<std::vector<float> > &rgb1);
void Blur(size_t xsize, size_t ysize, float* channel, double sigma,
double border_ratio = 0.0);
void RgbToXyb(double r, double g, double b,
double *valx, double *valy, double *valz);
double SimpleGamma(double v);
double GammaMinArg();
double GammaMaxArg();
// Polynomial evaluation via Clenshaw's scheme (similar to Horner's).
// Template enables compile-time unrolling of the recursion, but must reside
// outside of a class due to the specialization.
template <int INDEX>
static inline void ClenshawRecursion(const double x, const double *coefficients,
double *b1, double *b2) {
const double x_b1 = x * (*b1);
const double t = (x_b1 + x_b1) - (*b2) + coefficients[INDEX];
*b2 = *b1;
*b1 = t;
ClenshawRecursion<INDEX - 1>(x, coefficients, b1, b2);
}
// Base case
template <>
inline void ClenshawRecursion<0>(const double x, const double *coefficients,
double *b1, double *b2) {
const double x_b1 = x * (*b1);
// The final iteration differs - no 2 * x_b1 here.
*b1 = x_b1 - (*b2) + coefficients[0];
}
// Rational polynomial := dividing two polynomial evaluations. These are easier
// to find than minimax polynomials.
struct RationalPolynomial {
template <int N>
static double EvaluatePolynomial(const double x,
const double (&coefficients)[N]) {
double b1 = 0.0;
double b2 = 0.0;
ClenshawRecursion<N - 1>(x, coefficients, &b1, &b2);
return b1;
}
// Evaluates the polynomial at x (in [min_value, max_value]).
inline double operator()(const float x) const {
// First normalize to [0, 1].
const double x01 = (x - min_value) / (max_value - min_value);
// And then to [-1, 1] domain of Chebyshev polynomials.
const double xc = 2.0 * x01 - 1.0;
const double yp = EvaluatePolynomial(xc, p);
const double yq = EvaluatePolynomial(xc, q);
if (yq == 0.0) return 0.0;
return static_cast<float>(yp / yq);
}
// Domain of the polynomials; they are undefined elsewhere.
double min_value;
double max_value;
// Coefficients of T_n (Chebyshev polynomials of the first kind).
// Degree 5/5 is a compromise between accuracy (0.1%) and numerical stability.
double p[5 + 1];
double q[5 + 1];
};
static inline float GammaPolynomial(float value) {
// Generated by gamma_polynomial.m from equispaced x/gamma(x) samples.
static const RationalPolynomial r = {
0.770000000000000, 274.579999999999984,
{
881.979476556478289, 1496.058452015812463, 908.662212739659481,
373.566100223287378, 85.840860336314364, 6.683258861509244,
},
{
12.262350348616792, 20.557285797683576, 12.161463238367844,
4.711532733641639, 0.899112889751053, 0.035662329617191,
}};
return r(value);
}
} // namespace butteraugli
#endif // BUTTERAUGLI_BUTTERAUGLI_H_

@ -0,0 +1,10 @@
SET(ETCPACK_SRCS
etcdec.cxx
etcpack.cxx
image.cxx
image.h)
add_definitions("-DPGMOUT=0")
ADD_LIBRARY(etcpack STATIC ${ETCPACK_SRCS})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,461 @@
//// etcpack v2.74
////
//// NO WARRANTY
////
//// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE THE PROGRAM IS PROVIDED
//// "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF ANY KIND, EXTENDS NO
//// WARRANTIES OR CONDITIONS OF ANY KIND; EITHER EXPRESS, IMPLIED OR
//// STATUTORY; INCLUDING, BUT NOT LIMITED TO, EXPRESS, IMPLIED OR
//// STATUTORY WARRANTIES OR CONDITIONS OF TITLE, MERCHANTABILITY,
//// SATISFACTORY QUALITY, SUITABILITY AND FITNESS FOR A PARTICULAR
//// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
//// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
//// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
//// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, OFFERING FOR SALE,
//// DISTRIBUTION, LEASE, USE OR IMPORTATION UNDER THE LICENSE WILL BE FREE
//// FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL
//// PROPERTY RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE IS SUBJECT
//// TO YOUR SOLE RESPONSIBILITY TO MAKE SUCH DETERMINATION AND ACQUIRE
//// SUCH LICENSES AS MAY BE NECESSARY WITH RESPECT TO PATENTS, COPYRIGHT
//// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES.
////
//// FOR THE AVOIDANCE OF DOUBT THE PROGRAM (I) IS NOT LICENSED FOR; (II)
//// IS NOT DESIGNED FOR OR INTENDED FOR; AND (III) MAY NOT BE USED FOR;
//// ANY MISSION CRITICAL APPLICATIONS SUCH AS, BUT NOT LIMITED TO
//// OPERATION OF NUCLEAR OR HEALTHCARE COMPUTER SYSTEMS AND/OR NETWORKS,
//// AIRCRAFT OR TRAIN CONTROL AND/OR COMMUNICATION SYSTEMS OR ANY OTHER
//// COMPUTER SYSTEMS AND/OR NETWORKS OR CONTROL AND/OR COMMUNICATION
//// SYSTEMS ALL IN WHICH CASE THE FAILURE OF THE PROGRAM COULD LEAD TO
//// DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL, MATERIAL OR ENVIRONMENTAL
//// DAMAGE. YOUR RIGHTS UNDER THIS LICENSE WILL TERMINATE AUTOMATICALLY
//// AND IMMEDIATELY WITHOUT NOTICE IF YOU FAIL TO COMPLY WITH THIS
//// PARAGRAPH.
////
//// IN NO EVENT WILL ERICSSON, BE LIABLE FOR ANY DAMAGES WHATSOEVER,
//// INCLUDING BUT NOT LIMITED TO PERSONAL INJURY, ANY GENERAL, SPECIAL,
//// INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN
//// CONNECTION WITH THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
//// NOT LIMITED TO LOSS OF PROFITS, BUSINESS INTERUPTIONS, OR ANY OTHER
//// COMMERCIAL DAMAGES OR LOSSES, LOSS OF DATA OR DATA BEING RENDERED
//// INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
//// THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) REGARDLESS OF THE
//// THEORY OF LIABILITY (CONTRACT, TORT OR OTHERWISE), EVEN IF SUCH HOLDER
//// OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
////
//// (C) Ericsson AB 2005-2013. All Rights Reserved.
////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "image.h"
// Remove warnings for unsafe functions such as strcpy
#pragma warning(disable : 4996)
// Remove warnings for conversions between different time variables
#pragma warning(disable : 4244)
// Removes comments in a .ppm file
// (i.e., lines starting with #)
// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
void removeComments(FILE *f1)
{
int c;
while((c = getc(f1)) == '#')
{
char line[1024];
fgets(line, 1024, f1);
}
ungetc(c, f1);
}
// Removes white spaces in a .ppm file
// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
void removeSpaces(FILE *f1)
{
int c;
c = getc(f1);
while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r')
{
c = getc(f1);
}
ungetc(c, f1);
}
// fReadPPM
//
// reads a ppm file with P6 header (meaning binary, as opposed to P5, which is ascII)
// and returns the image in pixels.
//
// The header must look like this:
//
// P6
// # Comments (not necessary)
// width height
// 255
//
// after that follows RGBRGBRGB...
//
// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
bool fReadPPM(char *filename, int &width, int &height, unsigned char *&pixels, int targetbitrate)
{
FILE *f1;
int maximum;
f1 = fopen(filename, "rb");
if(f1)
{
char line[255];
removeSpaces(f1);
removeComments(f1);
removeSpaces(f1);
fscanf(f1, "%s", line);
if(strcmp(line, "P6")!=0)
{
printf("Error: %s is not binary\n");
printf("(Binary .ppm files start with P6).\n");
fclose(f1);
return false;
}
removeSpaces(f1);
removeComments(f1);
removeSpaces(f1);
fscanf(f1, "%d %d", &width, &height);
if( width<=0 || height <=0)
{
printf("Error: width or height negative. File: %s\n",filename);
fclose(f1);
return false;
}
removeSpaces(f1);
removeComments(f1);
removeSpaces(f1);
fscanf(f1, "%d", &maximum);
if( maximum!= 255&&maximum!=(1<<16)-1)
{
printf("Error: Color resolution must be 255. File: %s\n",filename);
fclose(f1);
return false;
}
//printf("maximum is %d\n",maximum);
int bitrate=8;
if(maximum!=255)
bitrate=16;
// We need to remove the newline.
char c = 0;
while(c != '\n')
fscanf(f1, "%c", &c);
unsigned char* readbuffer = (unsigned char*) malloc(3*width*height*bitrate/8);
if(!readbuffer)
{
printf("Error: Could not allocate memory for image. File: %s\n", filename);
fclose(f1);
return false;
}
if(fread(readbuffer, 3*width*height*bitrate/8, 1, f1) != 1)
{
printf("Error: Could not read all pixels. File: %s\n", filename);
free(pixels);
fclose(f1);
return false;
}
// If we have reached this point, we have successfully loaded the image.
//now, convert it to the target bitrate
if(targetbitrate==bitrate)
pixels=readbuffer;
else
{
pixels = (unsigned char*) malloc(3*width*height*targetbitrate/8);
if(targetbitrate<bitrate)
{
//cut least significant bits to go from 16 -> 8 bits..
printf("converting 16 bit input to 8 bits\n");
for(int x=0; x<width; x++)
{
for(int y=0; y<height; y++)
{
for(int c=0; c<3; c++)
{
pixels[3*(x+y*width)+c]=readbuffer[6*(x+y*width)+2*c];
}
}
}
}
else
{
//replicate 8 bits to go from 8 -> 16 bits...
printf("converting 8 bit input to 16 bits\n");
for(int x=0; x<width; x++)
{
for(int y=0; y<height; y++)
{
for(int c=0; c<3; c++)
{
pixels[6*(x+y*width)+2*c]=readbuffer[3*(x+y*width)+c];
pixels[6*(x+y*width)+2*c+1]=readbuffer[3*(x+y*width)+c];
}
}
}
}
free(readbuffer);
}
fclose(f1);
return true;
}
else
{
printf("Error: Coult not open file %s\n", filename);
return false;
}
}
// Write PPM
// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
bool fWritePPM(char *filename, int width, int height, unsigned char *pixels, int bitrate, bool reverse_y)
{
FILE *fsave;
fsave = fopen(filename, "wb");
int max = (1<<bitrate)-1;
int fac = bitrate/8;
if(fsave)
{
int q;
fprintf(fsave, "P6\n%d %d\n%d\n", width, height,max);
for(q = 0; q< height; q++)
{
unsigned char *adr;
if(reverse_y)
adr = pixels+3*width*(height-1-q)*fac;
else
adr = pixels+3*width*q*fac;
fwrite(adr, 3*width*fac, 1, fsave);
}
fclose(fsave);
return true;
}
else
{
printf("Error: Could not open the file %s.\n",filename);
return(false);
}
}
// WritePGM
// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
bool fWritePGM(char *filename, int width, int height, unsigned char *pixels,bool reverse_y, int bitdepth)
{
FILE *f;
f=fopen(filename,"wb");
if(f)
{
int q;
int max = (1<<bitdepth)-1;
fprintf(f,"P5\n%d %d\n%d\n",width,height,max);
if(bitdepth==16)
width*=2; //ugly way of doubling the number of bytes to write, since we write one line at a time..
for(q=0;q<height;q++)
{
unsigned char *adr;
if(reverse_y) adr=pixels+width*(height-1-q);
else adr=pixels+width*q;
fwrite(adr,width,1,f);
}
fclose(f);
return true;
}
else
{
printf("Error: could not open file <%s>.\n",filename);
return false;
}
}
/* reads a ppm file with the P6 header (means raw RGB), puts data into pixel pointer and returns bit depth (8 or 16 bpp) */
/* the header looks like this:
*---------
* P5
* # comments if you want to
* width height
* 255
*---------
* then follows RGBRGBRGBRGBRGB...
*/
// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
int fReadPGM(char *filename, int &width, int &height, unsigned char *&pixels, int wantedBitDepth)
{
FILE *f;
int colres;
int bitdepth=8;
f=fopen(filename,"rb");
if(f)
{
char str[100];
removeSpaces(f);
removeComments(f);
removeSpaces(f);
fscanf(f,"%s",str);
if(strcmp(str,"P5")!=0)
{
printf("Error: the alpha image file must be of raw color PGM format,\n");
printf("i.e., it must have P5 in the header. File: %s\n",filename);
fclose(f);
return 0;
}
removeSpaces(f);
removeComments(f);
removeSpaces(f);
fscanf(f,"%d %d",&width,&height);
if(width<=0 || height<=0)
{
printf("Error: width and height of the image must be greater than zero. File: %s\n",filename);
fclose(f);
return 0;
}
removeSpaces(f);
removeComments(f);
removeSpaces(f);
fscanf(f,"%d",&colres);
if(colres!=255&&colres!=65535)
{
printf("Error: color resolution must be 255 or 65535.File: %s\n",filename);
fclose(f);
return 0;
}
if(colres==65535)
bitdepth=16;
/* gotta eat the newline too */
char ch=0;
while(ch!='\n') fscanf(f,"%c",&ch);
pixels=(unsigned char*)malloc(width*height*bitdepth/8);
if(!pixels)
{
printf("Error: could not allocate memory for the pixels of the texture. File: %s\n",filename);
fclose(f);
return 0;
}
if(fread(pixels,width*height*bitdepth/8,1,f)!=1)
{
printf("Error: could not read %d bytes of pixel info. File: %s\n",width*height*bitdepth/8,filename);
free(pixels);
fclose(f);
return 0;
}
fclose(f);
printf("read %d-bit alpha channel",bitdepth);
if(bitdepth!=wantedBitDepth)
{
printf(", converting to %d-bit!",wantedBitDepth);
unsigned char* newpixels = (unsigned char*)malloc(width*height*wantedBitDepth/8);
for(int x=0; x<width; x++)
{
for(int y=0; y<height; y++)
{
if(bitdepth<wantedBitDepth)
{
//do bit-replication to get 2-bytes per pixel
newpixels[2*(x+y*width)]=pixels[x+y*width];
newpixels[2*(x+y*width)+1]=pixels[x+y*width];
}
else
{
//simply truncate the extra data..
newpixels[(x+y*width)]=pixels[2*(x+y*width)];
}
}
}
free(pixels);
pixels=newpixels;
}
printf("\n");
return bitdepth;
}
else
{
printf("Error: could not open %s.\n",filename);
return 0;
}
}
/* writes a .tga file from two arrays --- one RGB array and one alpha-array */
/* */
// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2012. All Rights Reserved.
bool fWriteTGAfromRGBandA(char *filename, int width, int height, unsigned char *pixelsRGB, unsigned char *pixelsA, bool reverse_y)
{
FILE *f1;
if( (f1 = fopen(filename,"wb")) == NULL)
{
return false;
}
// First write header
unsigned char myByteVal;
short myShortVal;
myByteVal = 0;
fwrite(&myByteVal, 1, 1, f1); // ID field (0)
fwrite(&myByteVal, 1, 1, f1); // Palette? (no=0)
myByteVal = 2;
fwrite(&myByteVal, 1, 1, f1); // Image type (rgb=2)
myShortVal = 0;
fwrite(&myShortVal, 2, 1, f1); // Palette stuff... 0
fwrite(&myShortVal, 2, 1, f1); // Palette stuff... 0
myByteVal = 0;
fwrite(&myByteVal, 1, 1, f1); // Palette stuff... 0
myShortVal = 0;
fwrite(&myShortVal, 2, 1, f1); // x-origin
myShortVal = 0;
fwrite(&myShortVal, 2, 1, f1); // y-origin
myShortVal = width;
fwrite(&myShortVal, 2, 1, f1); // width
myShortVal = height;
fwrite(&myShortVal, 2, 1, f1); // height
myByteVal = 32;
fwrite(&myByteVal, 1, 1, f1); // Bits per pixel = 32
myByteVal = 8;
fwrite(&myByteVal, 1, 1, f1); // flip bits = 8
// Write pixels in BGRA format
if(reverse_y)
{
int xx, yy;
for(yy = height-1; yy>=0; yy--)
{
for(xx = 0; xx<width; xx++)
{
fwrite(&pixelsRGB[3*(yy*width+xx)+2], sizeof(unsigned char), 1, f1); // B
fwrite(&pixelsRGB[3*(yy*width+xx)+1], sizeof(unsigned char), 1, f1); // G
fwrite(&pixelsRGB[3*(yy*width+xx)+0], sizeof(unsigned char), 1, f1); // R
fwrite(&pixelsA[(yy*width+xx)], sizeof(unsigned char), 1, f1); // A
}
}
}
else
{
for(int q = 0; q< width * height; q++)
{
fwrite(&pixelsRGB[3*q+2], sizeof(unsigned char), 1, f1); // B
fwrite(&pixelsRGB[3*q+1], sizeof(unsigned char), 1, f1); // G
fwrite(&pixelsRGB[3*q+0], sizeof(unsigned char), 1, f1); // R
fwrite(&pixelsA[1*q], sizeof(unsigned char), 1, f1); // A
}
}
fclose(f1);
return true;
}

@ -0,0 +1,65 @@
//// etcpack v2.74
////
//// NO WARRANTY
////
//// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE THE PROGRAM IS PROVIDED
//// "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF ANY KIND, EXTENDS NO
//// WARRANTIES OR CONDITIONS OF ANY KIND; EITHER EXPRESS, IMPLIED OR
//// STATUTORY; INCLUDING, BUT NOT LIMITED TO, EXPRESS, IMPLIED OR
//// STATUTORY WARRANTIES OR CONDITIONS OF TITLE, MERCHANTABILITY,
//// SATISFACTORY QUALITY, SUITABILITY AND FITNESS FOR A PARTICULAR
//// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
//// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
//// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
//// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, OFFERING FOR SALE,
//// DISTRIBUTION, LEASE, USE OR IMPORTATION UNDER THE LICENSE WILL BE FREE
//// FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL
//// PROPERTY RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE IS SUBJECT
//// TO YOUR SOLE RESPONSIBILITY TO MAKE SUCH DETERMINATION AND ACQUIRE
//// SUCH LICENSES AS MAY BE NECESSARY WITH RESPECT TO PATENTS, COPYRIGHT
//// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES.
////
//// FOR THE AVOIDANCE OF DOUBT THE PROGRAM (I) IS NOT LICENSED FOR; (II)
//// IS NOT DESIGNED FOR OR INTENDED FOR; AND (III) MAY NOT BE USED FOR;
//// ANY MISSION CRITICAL APPLICATIONS SUCH AS, BUT NOT LIMITED TO
//// OPERATION OF NUCLEAR OR HEALTHCARE COMPUTER SYSTEMS AND/OR NETWORKS,
//// AIRCRAFT OR TRAIN CONTROL AND/OR COMMUNICATION SYSTEMS OR ANY OTHER
//// COMPUTER SYSTEMS AND/OR NETWORKS OR CONTROL AND/OR COMMUNICATION
//// SYSTEMS ALL IN WHICH CASE THE FAILURE OF THE PROGRAM COULD LEAD TO
//// DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL, MATERIAL OR ENVIRONMENTAL
//// DAMAGE. YOUR RIGHTS UNDER THIS LICENSE WILL TERMINATE AUTOMATICALLY
//// AND IMMEDIATELY WITHOUT NOTICE IF YOU FAIL TO COMPLY WITH THIS
//// PARAGRAPH.
////
//// IN NO EVENT WILL ERICSSON, BE LIABLE FOR ANY DAMAGES WHATSOEVER,
//// INCLUDING BUT NOT LIMITED TO PERSONAL INJURY, ANY GENERAL, SPECIAL,
//// INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN
//// CONNECTION WITH THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
//// NOT LIMITED TO LOSS OF PROFITS, BUSINESS INTERUPTIONS, OR ANY OTHER
//// COMMERCIAL DAMAGES OR LOSSES, LOSS OF DATA OR DATA BEING RENDERED
//// INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
//// THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) REGARDLESS OF THE
//// THEORY OF LIABILITY (CONTRACT, TORT OR OTHERWISE), EVEN IF SUCH HOLDER
//// OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
////
//// (C) Ericsson AB 2005-2013. All Rights Reserved.
////
#ifndef IMAGE_H
#define IMAGE_H
bool fReadPPM(char *filename, int &width, int &height, unsigned char *&pixels, int targetbitrate);
bool fWritePPM(char *filename, int width, int height, unsigned char *pixels, int bitrate, bool reverse_y);
bool fReadPFM(char *filename, int &width, int &height, float *&pixels);
bool fWritePFM(char *filename, int width, int height, float *pixels,bool reverse_y);
// write a grey scale image
bool fWritePGM(char *filename, int width, int height, unsigned char *pixels,bool reverse_y, int bitdepth);
int fReadPGM(char *filename, int &width, int &height, unsigned char *&pixels, int wantedBitDepth);
// write a TGA image with both RGB and alpha
bool fWriteTGAfromRGBandA(char *filename, int width, int height, unsigned char *pixelsRGB, unsigned char *pixelsA, bool reverse_y);
#endif

@ -332,7 +332,7 @@ LLVM:
# define POSH_OS_STRING "MinGW"
#endif
#if defined GO32 && defined DJGPP && defined __MSDOS__
#if defined GO32 && defined DJGPP && defined __MSDOS__
# define POSH_OS_GO32 1
# define POSH_OS_STRING "GO32/MS-DOS"
#endif

@ -0,0 +1,568 @@
/******************************************************************************
@File PVRTArray.h
@Title PVRTArray
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description Expanding array template class. Allows appending and direct
access. Mixing access methods should be approached with caution.
******************************************************************************/
#ifndef __PVRTARRAY_H__
#define __PVRTARRAY_H__
//ACS: PVRTGlobal.h was dragging in too much stuff (like windows.h & crtdbg.h)
// so I split the relevant stuff out into a new file, PVRTTypes.h
//#include "PVRTGlobal.h"
#include "PVRTTypes.h"
#include "PVRTError.h"
/*!****************************************************************************
Class
******************************************************************************/
/*!***************************************************************************
* @Class CPVRTArray
* @Brief Expanding array template class.
* @Description Expanding array template class.
*****************************************************************************/
template<typename T>
class CPVRTArray
{
public:
/*!***************************************************************************
@Function CPVRTArray
@Description Blank constructor. Makes a default sized array.
*****************************************************************************/
CPVRTArray() : m_uiSize(0), m_uiCapacity(GetDefaultSize())
{
m_pArray = new T[m_uiCapacity];
}
/*!***************************************************************************
@Function CPVRTArray
@Input uiSize intial size of array
@Description Constructor taking initial size of array in elements.
*****************************************************************************/
CPVRTArray(const unsigned int uiSize) : m_uiSize(0), m_uiCapacity(uiSize)
{
_ASSERT(uiSize != 0);
m_pArray = new T[uiSize];
}
/*!***************************************************************************
@Function CPVRTArray
@Input original the other dynamic array
@Description Copy constructor.
*****************************************************************************/
CPVRTArray(const CPVRTArray& original) : m_uiSize(original.m_uiSize),
m_uiCapacity(original.m_uiCapacity)
{
m_pArray = new T[m_uiCapacity];
for(unsigned int i=0;i<m_uiSize;i++)
{
m_pArray[i]=original.m_pArray[i];
}
}
/*!***************************************************************************
@Function CPVRTArray
@Input pArray an ordinary array
@Input uiSize number of elements passed
@Description constructor from ordinary array.
*****************************************************************************/
CPVRTArray(const T* const pArray, const unsigned int uiSize) : m_uiSize(uiSize),
m_uiCapacity(uiSize)
{
_ASSERT(uiSize != 0);
m_pArray = new T[uiSize];
for(unsigned int i=0;i<m_uiSize;i++)
{
m_pArray[i]=pArray[i];
}
}
/*!***************************************************************************
@Function CPVRTArray
@Input uiSize initial capacity
@Input val value to populate with
@Description constructor from a capacity and initial value.
*****************************************************************************/
CPVRTArray(const unsigned int uiSize, const T& val) : m_uiSize(uiSize),
m_uiCapacity(uiSize)
{
_ASSERT(uiSize != 0);
m_pArray = new T[uiSize];
for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex)
{
m_pArray[uiIndex] = val;
}
}
/*!***************************************************************************
@Function ~CPVRTArray
@Description Destructor.
*****************************************************************************/
virtual ~CPVRTArray()
{
if(m_pArray)
delete [] m_pArray;
}
/*!***************************************************************************
@Function Insert
@Input pos The position to insert the new element at
@Input addT The element to insert
@Return The index of the new item or -1 on failure.
@Description Inserts an element into the array, expanding it
if necessary.
*****************************************************************************/
int Insert(const unsigned int pos, const T& addT)
{
unsigned int uiIndex = pos;
if(pos >= m_uiSize) // Are we adding to the end
uiIndex = Append(addT);
else
{
unsigned int uiNewCapacity = 0;
T* pArray = m_pArray;
if(m_uiSize > m_uiCapacity)
{
uiNewCapacity = m_uiCapacity + 10; // Expand the array by 10.
pArray = new T[uiNewCapacity]; // New Array
if(!pArray)
return -1; // Failed to allocate memory!
// Copy the first half to the new array
for(unsigned int i = 0; i < pos; ++i)
{
pArray[i] = m_pArray[i];
}
}
// Copy last half to the new array
for(unsigned int i = m_uiSize; i > pos; --i)
{
pArray[i] = m_pArray[i - 1];
}
// Insert our new element
pArray[pos] = addT;
uiIndex = pos;
// Increase our size
++m_uiSize;
// Switch pointers and free memory if needed
if(pArray != m_pArray)
{
m_uiCapacity = uiNewCapacity;
delete[] m_pArray;
m_pArray = pArray;
}
}
return uiIndex;
}
/*!***************************************************************************
@Function Append
@Input addT The element to append
@Return The index of the new item.
@Description Appends an element to the end of the array, expanding it
if necessary.
*****************************************************************************/
unsigned int Append(const T& addT)
{
unsigned int uiIndex = Append();
m_pArray[uiIndex] = addT;
return uiIndex;
}
/*!***************************************************************************
@Function Append
@Return The index of the new item.
@Description Creates space for a new item, but doesn't add. Instead
returns the index of the new item.
*****************************************************************************/
unsigned int Append()
{
unsigned int uiIndex = m_uiSize;
SetCapacity(m_uiSize+1);
m_uiSize++;
return uiIndex;
}
/*!***************************************************************************
@Function Clear
@Description Clears the array.
*****************************************************************************/
void Clear()
{
m_uiSize = 0U;
}
/*!***************************************************************************
@Function Resize
@Input uiSize New size of array
@Description Changes the array to the new size
*****************************************************************************/
EPVRTError Resize(const unsigned int uiSize)
{
EPVRTError err = SetCapacity(uiSize);
if(err != PVR_SUCCESS)
return err;
m_uiSize = uiSize;
return PVR_SUCCESS;
}
/*!***************************************************************************
@Function SetCapacity
@Input uiSize New capacity of array
@Description Expands array to new capacity
*****************************************************************************/
EPVRTError SetCapacity(const unsigned int uiSize)
{
if(uiSize <= m_uiCapacity)
return PVR_SUCCESS; // nothing to be done
unsigned int uiNewCapacity;
if(uiSize < m_uiCapacity*2)
{
uiNewCapacity = m_uiCapacity*2; // Ignore the new size. Expand to twice the previous size.
}
else
{
uiNewCapacity = uiSize;
}
T* pNewArray = new T[uiNewCapacity]; // New Array
if(!pNewArray)
return PVR_FAIL; // Failed to allocate memory!
// Copy source data to new array
for(unsigned int i = 0; i < m_uiSize; ++i)
{
pNewArray[i] = m_pArray[i];
}
// Switch pointers and free memory
m_uiCapacity = uiNewCapacity;
T* pOldArray = m_pArray;
m_pArray = pNewArray;
delete [] pOldArray;
return PVR_SUCCESS;
}
/*!***************************************************************************
@Function Copy
@Input other The CPVRTArray needing copied
@Description A copy function. Will attempt to copy from other CPVRTArrays
if this is possible.
*****************************************************************************/
template<typename T2>
void Copy(const CPVRTArray<T2>& other)
{
T* pNewArray = new T[other.GetCapacity()];
if(pNewArray)
{
// Copy data
for(unsigned int i = 0; i < other.GetSize(); i++)
{
pNewArray[i] = other[i];
}
// Free current array
if(m_pArray)
delete [] m_pArray;
// Swap pointers
m_pArray = pNewArray;
m_uiCapacity = other.GetCapacity();
m_uiSize = other.GetSize();
}
}
/*!***************************************************************************
@Function =
@Input other The CPVRTArray needing copied
@Description assignment operator.
*****************************************************************************/
CPVRTArray& operator=(const CPVRTArray<T>& other)
{
if(&other != this)
Copy(other);
return *this;
}
/*!***************************************************************************
@Function operator+=
@Input other the array to append.
@Description appends an existing CPVRTArray on to this one.
*****************************************************************************/
CPVRTArray& operator+=(const CPVRTArray<T>& other)
{
if(&other != this)
{
for(unsigned int uiIndex = 0; uiIndex < other.GetSize(); ++uiIndex)
{
Append(other[uiIndex]);
}
}
return *this;
}
/*!***************************************************************************
@Function []
@Input uiIndex index of element in array
@Return the element indexed
@Description indexed access into array. Note that this has no error
checking whatsoever
*****************************************************************************/
T& operator[](const unsigned int uiIndex)
{
_ASSERT(uiIndex < m_uiCapacity);
return m_pArray[uiIndex];
}
/*!***************************************************************************
@Function []
@Input uiIndex index of element in array
@Return The element indexed
@Description Indexed access into array. Note that this has no error
checking whatsoever
*****************************************************************************/
const T& operator[](const unsigned int uiIndex) const
{
_ASSERT(uiIndex < m_uiCapacity);
return m_pArray[uiIndex];
}
/*!***************************************************************************
@Function GetSize
@Return Size of array
@Description Gives current size of array/number of elements
*****************************************************************************/
unsigned int GetSize() const
{
return m_uiSize;
}
/*!***************************************************************************
@Function GetDefaultSize
@Return Default size of array
@Description Gives the default size of array/number of elements
*****************************************************************************/
static unsigned int GetDefaultSize()
{
return 16U;
}
/*!***************************************************************************
@Function GetCapacity
@Return Capacity of array
@Description Gives current allocated size of array/number of elements
*****************************************************************************/
unsigned int GetCapacity() const
{
return m_uiCapacity;
}
/*!***************************************************************************
@Function Contains
@Input object The object to check in the array
@Return true if object is contained in this array.
@Description Indicates whether the given object resides inside the
array.
*****************************************************************************/
bool Contains(const T& object) const
{
for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex)
{
if(m_pArray[uiIndex] == object)
return true;
}
return false;
}
/*!***************************************************************************
@Function Find
@Input object The object to check in the array
@Return pointer to the found object or NULL.
@Description Attempts to find the object in the array and returns a
pointer if it is found, or NULL if not found. The time
taken is O(N).
*****************************************************************************/
T* Find(const T& object) const
{
for(unsigned int uiIndex = 0; uiIndex < m_uiSize; ++uiIndex)
{
if(m_pArray[uiIndex] == object)
return &m_pArray[uiIndex];
}
return NULL;
}
/*!***************************************************************************
@Function Sort
@Input predicate The object which defines "bool operator()"
@Description Simple bubble-sort of the array. Pred should be an object that
defines a bool operator().
*****************************************************************************/
template<class Pred>
void Sort(Pred predicate)
{
bool bSwap;
for(unsigned int i=0; i < m_uiSize; ++i)
{
bSwap = false;
for(unsigned int j=0; j < m_uiSize-1; ++j)
{
if(predicate(m_pArray[j], m_pArray[j+1]))
{
PVRTswap(m_pArray[j], m_pArray[j+1]);
bSwap = true;
}
}
if(!bSwap)
return;
}
}
/*!***************************************************************************
@Function Remove
@Input uiIndex The index to remove
@Return success or failure
@Description Removes an element from the array.
*****************************************************************************/
virtual EPVRTError Remove(unsigned int uiIndex)
{
_ASSERT(uiIndex < m_uiSize);
if(m_uiSize == 0)
return PVR_FAIL;
if(uiIndex == m_uiSize-1)
{
return RemoveLast();
}
m_uiSize--;
// Copy the data. memmove will only work for built-in types.
for(unsigned int uiNewIdx = uiIndex; uiNewIdx < m_uiSize; ++uiNewIdx)
{
m_pArray[uiNewIdx] = m_pArray[uiNewIdx+1];
}
return PVR_SUCCESS;
}
/*!***************************************************************************
@Function RemoveLast
@Return success or failure
@Description Removes the last element. Simply decrements the size value
*****************************************************************************/
virtual EPVRTError RemoveLast()
{
if(m_uiSize > 0)
{
m_uiSize--;
return PVR_SUCCESS;
}
else
{
return PVR_FAIL;
}
}
protected:
unsigned int m_uiSize; /*! current size of contents of array */
unsigned int m_uiCapacity; /*! currently allocated size of array */
T *m_pArray; /*! the actual array itself */
};
// note "this" is required for ISO standard C++ and gcc complains otherwise
// http://lists.apple.com/archives/Xcode-users//2005/Dec/msg00644.html
template<typename T>
class CPVRTArrayManagedPointers : public CPVRTArray<T*>
{
public:
virtual ~CPVRTArrayManagedPointers()
{
if(this->m_pArray)
{
for(unsigned int i=0;i<this->m_uiSize;i++)
{
delete(this->m_pArray[i]);
}
}
}
/*!***************************************************************************
@Function Remove
@Input uiIndex The index to remove
@Return success or failure
@Description Removes an element from the array.
*****************************************************************************/
virtual EPVRTError Remove(unsigned int uiIndex)
{
_ASSERT(uiIndex < this->m_uiSize);
if(this->m_uiSize == 0)
return PVR_FAIL;
if(uiIndex == this->m_uiSize-1)
{
return this->RemoveLast();
}
unsigned int uiSize = (this->m_uiSize - (uiIndex+1)) * sizeof(T*);
delete this->m_pArray[uiIndex];
memmove(this->m_pArray + uiIndex, this->m_pArray + (uiIndex+1), uiSize);
this->m_uiSize--;
return PVR_SUCCESS;
}
/*!***************************************************************************
@Function RemoveLast
@Return success or failure
@Description Removes the last element. Simply decrements the size value
*****************************************************************************/
virtual EPVRTError RemoveLast()
{
if(this->m_uiSize > 0 && this->m_pArray)
{
delete this->m_pArray[this->m_uiSize-1];
this->m_uiSize--;
return PVR_SUCCESS;
}
else
{
return PVR_FAIL;
}
}
};
#endif // __PVRTARRAY_H__
/*****************************************************************************
End of file (PVRTArray.h)
*****************************************************************************/

@ -0,0 +1,58 @@
/******************************************************************************
@File PVRTDecompress.h
@Title PVRTDecompress
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description PVRTC and ETC Texture Decompression.
******************************************************************************/
#ifndef _PVRTDECOMPRESS_H_
#define _PVRTDECOMPRESS_H_
/*!***********************************************************************
@Function PVRTDecompressPVRTC
@Input pCompressedData The PVRTC texture data to decompress
@Input Do2bitMode Signifies whether the data is PVRTC2 or PVRTC4
@Input XDim X dimension of the texture
@Input YDim Y dimension of the texture
@Return Returns the amount of data that was decompressed.
@Modified pResultImage The decompressed texture data
@Description Decompresses PVRTC to RGBA 8888
*************************************************************************/
int PVRTDecompressPVRTC(const void *pCompressedData,
const int Do2bitMode,
const int XDim,
const int YDim,
unsigned char* pResultImage);
/*!***********************************************************************
@Function PVRTDecompressETC
@Input pSrcData The ETC texture data to decompress
@Input x X dimension of the texture
@Input y Y dimension of the texture
@Modified pDestData The decompressed texture data
@Input nMode The format of the data
@Returns The number of bytes of ETC data decompressed
@Description Decompresses ETC to RGBA 8888
*************************************************************************/
int PVRTDecompressETC(const void * const pSrcData,
const unsigned int &x,
const unsigned int &y,
void *pDestData,
const int &nMode);
#endif /* _PVRTDECOMPRESS_H_ */
/*****************************************************************************
End of file (PVRTBoneBatch.h)
*****************************************************************************/

@ -0,0 +1,71 @@
/******************************************************************************
@File PVRTError.h
@Title PVRTError
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description
******************************************************************************/
#ifndef _PVRTERROR_H_
#define _PVRTERROR_H_
#if defined(ANDROID)
#include <android/log.h>
#else
#if defined(_WIN32)
#include <windows.h>
#else
#include <stdio.h>
#endif
#endif
/*!***************************************************************************
Macros
*****************************************************************************/
/*! Outputs a string to the standard error if built for debugging. */
#if !defined(PVRTERROR_OUTPUT_DEBUG)
#if defined(_DEBUG) || defined(DEBUG)
#if defined(ANDROID)
#define PVRTERROR_OUTPUT_DEBUG(A) __android_log_print(ANDROID_LOG_INFO, "PVRTools", A);
#elif defined(_WIN32)
#define PVRTERROR_OUTPUT_DEBUG(A) OutputDebugStringA(A);
#else
#define PVRTERROR_OUTPUT_DEBUG(A) fprintf(stderr,A);
#endif
#else
#define PVRTERROR_OUTPUT_DEBUG(A)
#endif
#endif
/*!***************************************************************************
Enums
*****************************************************************************/
/*! Enum error codes */
enum EPVRTError
{
PVR_SUCCESS = 0,
PVR_FAIL = 1,
PVR_OVERFLOW = 2
};
/*!***************************************************************************
@Function PVRTErrorOutputDebug
@Input format printf style format followed by arguments it requires
@Description Outputs a string to the standard error.
*****************************************************************************/
void PVRTErrorOutputDebug(char const * const format, ...);
#endif // _PVRTERROR_H_
/*****************************************************************************
End of file (PVRTError.h)
*****************************************************************************/

@ -0,0 +1,278 @@
/******************************************************************************
@File PVRTGlobal.h
@Title PVRTGlobal
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description Global defines and typedefs for PVRTools
******************************************************************************/
#ifndef _PVRTGLOBAL_H_
#define _PVRTGLOBAL_H_
/*!***************************************************************************
Macros
*****************************************************************************/
#define PVRT_MIN(a,b) (((a) < (b)) ? (a) : (b))
#define PVRT_MAX(a,b) (((a) > (b)) ? (a) : (b))
#define PVRT_CLAMP(x, l, h) (PVRT_MIN((h), PVRT_MAX((x), (l))))
// avoid warning about unused parameter
#define PVRT_UNREFERENCED_PARAMETER(x) ((void) x)
#if defined(_WIN32) && !defined(__QT__) /* Windows desktop */
#if !defined(_CRTDBG_MAP_ALLOC)
#define _CRTDBG_MAP_ALLOC
#endif
#include <windows.h>
#include <crtdbg.h>
#include <tchar.h>
#endif
#if defined(_WIN32) && !defined(__QT__)
#else
#if defined(__linux__) || defined(__APPLE__)
#define _ASSERT(a)((void)0)
#define _ASSERTE(a)((void)0)
#ifdef _DEBUG
#ifndef _RPT0
#define _RPT0(a,b) printf(b)
#endif
#ifndef _RPT1
#define _RPT1(a,b,c) printf(b,c)
#endif
#else
#ifndef _RPT0
#define _RPT0(a,b)((void)0)
#endif
#ifndef _RPT1
#define _RPT1(a,b,c)((void)0)
#endif
#endif
#define _RPT2(a,b,c,d)((void)0)
#define _RPT3(a,b,c,d,e)((void)0)
#define _RPT4(a,b,c,d,e,f)((void)0)
#include <stdlib.h>
#include <string.h>
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned int
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
#define BOOL int
#if !defined(TRUE)
#define TRUE 1
#endif
#if !defined(FALSE)
#define FALSE 0
#endif
#else
#define _CRT_WARN 0
#define _RPT0(a,b)
#define _RPT1(a,b,c)
#define _RPT2(a,b,c,d)
#define _RPT3(a,b,c,d,e)
#define _RPT4(a,b,c,d,e,f)
#define _ASSERT(X)
#define _ASSERTE(X)
#endif
#endif
#include <stdio.h>
#define FREE(X) { if(X) { free(X); (X) = 0; } }
#if 1 //ACS: I split this out into PVRTTypes.h
#include "PVRTTypes.h"
#else
// This macro is used to check at compile time that types are of a certain size
// If the size does not equal the expected size, this typedefs an array of size 0
// which causes a compile error
#define PVRTSIZEASSERT(T, size) typedef int (sizeof_##T)[sizeof(T) == (size)]
#define PVRTCOMPILEASSERT(T, expr) typedef int (assert_##T)[expr]
/****************************************************************************
** Integer types
****************************************************************************/
typedef char PVRTchar8;
typedef signed char PVRTint8;
typedef signed short PVRTint16;
typedef signed int PVRTint32;
typedef unsigned char PVRTuint8;
typedef unsigned short PVRTuint16;
typedef unsigned int PVRTuint32;
typedef float PVRTfloat32;
#if (defined(__int64) || defined(_WIN32))
typedef signed __int64 PVRTint64;
typedef unsigned __int64 PVRTuint64;
#elif defined(TInt64)
typedef TInt64 PVRTint64;
typedef TUInt64 PVRTuint64;
#else
typedef signed long long PVRTint64;
typedef unsigned long long PVRTuint64;
#endif
#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000
#define PVRTSIZEOFWCHAR 4
#else
#define PVRTSIZEOFWCHAR 2
#endif
PVRTSIZEASSERT(PVRTchar8, 1);
PVRTSIZEASSERT(PVRTint8, 1);
PVRTSIZEASSERT(PVRTuint8, 1);
PVRTSIZEASSERT(PVRTint16, 2);
PVRTSIZEASSERT(PVRTuint16, 2);
PVRTSIZEASSERT(PVRTint32, 4);
PVRTSIZEASSERT(PVRTuint32, 4);
PVRTSIZEASSERT(PVRTint64, 8);
PVRTSIZEASSERT(PVRTuint64, 8);
PVRTSIZEASSERT(PVRTfloat32, 4);
/*!**************************************************************************
@Enum ETextureFilter
@Brief Enum values for defining texture filtering
****************************************************************************/
enum ETextureFilter
{
eFilter_Nearest,
eFilter_Linear,
eFilter_None,
eFilter_Size,
eFilter_Default = eFilter_Nearest,
eFilter_MipDefault = eFilter_None
};
/*!**************************************************************************
@Enum ETextureWrap
@Brief Enum values for defining texture wrapping
****************************************************************************/
enum ETextureWrap
{
eWrap_Clamp,
eWrap_Repeat,
eWrap_Size,
eWrap_Default = eWrap_Repeat
};
#endif
/****************************************************************************
** swap template function
****************************************************************************/
/*!***************************************************************************
@Function PVRTswap
@Input a Type a
@Input b Type b
@Description A swap template function that swaps a and b
*****************************************************************************/
template <typename T>
inline void PVRTswap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
/*!***************************************************************************
@Function PVRTClamp
@Input val Value to clamp
@Input min Minimum legal value
@Input max Maximum legal value
@Description A clamp template function that clamps val between min and max.
*****************************************************************************/
template <typename T>
inline T PVRTClamp(const T& val, const T& min, const T& max)
{
if(val > max)
return max;
if(val < min)
return min;
return val;
}
/*!***************************************************************************
@Function PVRTByteSwap
@Input pBytes A number
@Input i32ByteNo Number of bytes in pBytes
@Description Swaps the endianness of pBytes in place
*****************************************************************************/
inline void PVRTByteSwap(unsigned char* pBytes, int i32ByteNo)
{
int i = 0, j = i32ByteNo - 1;
while(i < j)
PVRTswap<unsigned char>(pBytes[i++], pBytes[j--]);
}
/*!***************************************************************************
@Function PVRTByteSwap32
@Input ui32Long A number
@Returns ui32Long with its endianness changed
@Description Converts the endianness of an unsigned int
*****************************************************************************/
inline unsigned int PVRTByteSwap32(unsigned int ui32Long)
{
return ((ui32Long&0x000000FF)<<24) + ((ui32Long&0x0000FF00)<<8) + ((ui32Long&0x00FF0000)>>8) + ((ui32Long&0xFF000000) >> 24);
}
/*!***************************************************************************
@Function PVRTByteSwap16
@Input ui16Short A number
@Returns ui16Short with its endianness changed
@Description Converts the endianness of a unsigned short
*****************************************************************************/
inline unsigned short PVRTByteSwap16(unsigned short ui16Short)
{
return (ui16Short>>8) | (ui16Short<<8);
}
/*!***************************************************************************
@Function PVRTIsLittleEndian
@Returns True if the platform the code is ran on is little endian
@Description Returns true if the platform the code is ran on is little endian
*****************************************************************************/
inline bool PVRTIsLittleEndian()
{
static bool bLittleEndian;
static bool bIsInit = false;
if(!bIsInit)
{
short int word = 0x0001;
char *byte = (char*) &word;
bLittleEndian = byte[0] ? true : false;
bIsInit = true;
}
return bLittleEndian;
}
#endif // _PVRTGLOBAL_H_
/*****************************************************************************
End of file (Tools.h)
*****************************************************************************/

@ -0,0 +1,222 @@
/******************************************************************************
@File PVRTMap.h
@Title PVRTArray
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description A simple and easy to use implementation of a map.
******************************************************************************/
#ifndef __PVRTMAP_H__
#define __PVRTMAP_H__
#include "PVRTArray.h"
/*!****************************************************************************
Class
******************************************************************************/
/*!***************************************************************************
* @Class CPVRTMap
* @Brief Expanding map template class.
* @Description A simple and easy to use implementation of a map.
*****************************************************************************/
template <typename KeyType, typename DataType>
class CPVRTMap
{
public:
/*!***********************************************************************
@Function CPVRTMap
@Return A new CPVRTMap.
@Description Constructor for a CPVRTMap.
*************************************************************************/
CPVRTMap() : m_Keys(), m_Data(), m_uiSize(0)
{}
/*!***********************************************************************
@Function ~CPVRTMap
@Description Destructor for a CPVRTMap.
*************************************************************************/
~CPVRTMap()
{
//Clear the map, that's enough - the CPVRTArray members will tidy everything else up.
Clear();
}
EPVRTError Reserve(const PVRTuint32 uiSize)
{
//Sets the capacity of each member array to the requested size. The array used will only expand.
//Returns the most serious error from either method.
return PVRT_MAX(m_Keys.SetCapacity(uiSize),m_Data.SetCapacity(uiSize));
}
/*!***********************************************************************
@Function GetSize
@Return Number of meaningful members in the map.
@Description Returns the number of meaningful members in the map.
*************************************************************************/
PVRTuint32 GetSize() const
{
//Return the size.
return m_uiSize;
}
/*!***********************************************************************
@Function GetIndexOf
@Input key
@Return The index value for a mapped item.
@Description Gets the position of a particular key/data within the map.
If the return value is exactly equal to the value of
GetSize() then the item has not been found.
*************************************************************************/
PVRTuint32 GetIndexOf(const KeyType key) const
{
//Loop through all the valid keys.
for (PVRTuint32 i=0; i<m_uiSize; ++i)
{
//Check if a key matches.
if (m_Keys[i]==key)
{
//If a matched key is found, return the position.
return i;
}
}
//If not found, return the number of meaningful members.
return m_uiSize;
}
/*!***********************************************************************
@Function GetDataAtIndex
@Input uiIndex
@Return Data type at the specified position.
@Description Returns a pointer to the Data at a particular index.
If the index supplied is not valid, NULL is returned
instead. Deletion of data at this pointer will lead
to undefined behaviour.
*************************************************************************/
const DataType* GetDataAtIndex(const PVRTuint32 uiIndex) const
{
return &(m_Data[uiIndex]);
}
/*!***********************************************************************
@Function operator[]
@Input key
@Return Data that is mapped to 'key'.
@Description If a mapping already exists for 'key' then it will return
the associated data. If no mapping currently exists, a new
element is created in place.
*************************************************************************/
DataType& operator[] (const KeyType key)
{
//Get the index of the key.
PVRTuint32 uiIndex = GetIndexOf(key);
//Check the index is valid
if (uiIndex != m_uiSize)
{
//Return mapped data if the index is valid.
return m_Data[uiIndex];
}
else
{
//Append the key to the Keys array.
m_Keys.Append(key);
//Create a new DataType.
DataType sNewData;
//Append the new pointer to the Data array.
m_Data.Append(sNewData);
//Increment the size of meaningful data.
++m_uiSize;
//Return the contents of pNewData.
return m_Data[m_Keys.GetSize()-1];
}
}
/*!***********************************************************************
@Function Remove
@Input key
@Return Returns PVR_FAIL if item doesn't exist.
Otherwise returns PVR_SUCCESS.
@Description Removes an element from the map if it exists.
*************************************************************************/
EPVRTError Remove(const KeyType key)
{
//Finds the index of the key.
PVRTuint32 uiIndex=GetIndexOf(key);
//If the key is invalid, fail.
if (uiIndex==m_uiSize)
{
//Return failure.
return PVR_FAIL;
}
//Decrement the size of the map to ignore the last element in each array.
m_uiSize--;
//Copy the last key over the deleted key. There are now two copies of one element,
//but the one at the end of the array is ignored.
m_Keys[uiIndex]=m_Keys[m_uiSize-1];
//Copy the last data over the deleted data in the same way as the keys.
m_Data[uiIndex]=m_Data[m_uiSize-1];
//Return success.
return PVR_SUCCESS;
}
/*!***********************************************************************
@Function Clear
@Description Clears the Map of all data values.
*************************************************************************/
void Clear()
{
//Set the size to 0.
m_uiSize=0;
m_Keys.Clear();
m_Data.Clear();
}
/*!***********************************************************************
@Function Exists
@Input key
@Return Whether data exists for the specified key or not.
@Description Checks whether or not data exists for the specified key.
*************************************************************************/
bool Exists(const KeyType key) const
{
//Checks for a valid index for key, if not, returns false.
return (GetIndexOf(key) != m_uiSize);
}
private:
//Array of all the keys. Indices match m_Data.
CPVRTArray<KeyType> m_Keys;
//Array of pointers to all the allocated data.
CPVRTArray<DataType> m_Data;
//The number of meaningful members in the map.
PVRTuint32 m_uiSize;
};
#endif // __PVRTMAP_H__
/*****************************************************************************
End of file (PVRTMap.h)
*****************************************************************************/

@ -0,0 +1,985 @@
/******************************************************************************
@File PVRTString.h
@Title PVRTString
@Version @Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description A string class that can be used as drop-in replacement for
std::string on platforms/compilers that don't provide a full C++
standard library.
******************************************************************************/
#ifndef _PVRTSTRING_H_
#define _PVRTSTRING_H_
#include <stdio.h>
#define _USING_PVRTSTRING_
/*!***************************************************************************
@Class CPVRTString
@Brief A string class
*****************************************************************************/
class CPVRTString
{
private:
// Checking printf and scanf format strings
#if defined(_CC_GNU_) || defined(__GNUG__) || defined(__GNUC__)
#define FX_PRINTF(fmt,arg) __attribute__((format(printf,fmt,arg)))
#define FX_SCANF(fmt,arg) __attribute__((format(scanf,fmt,arg)))
#else
#define FX_PRINTF(fmt,arg)
#define FX_SCANF(fmt,arg)
#endif
public:
typedef size_t size_type;
typedef char value_type;
typedef char& reference;
typedef const char& const_reference;
static const size_type npos;
/*!***********************************************************************
@Function CPVRTString
@Input _Ptr A string
@Input _Count Length of _Ptr
@Description Constructor
************************************************************************/
CPVRTString(const char* _Ptr, size_t _Count = npos);
/*!***********************************************************************
@Function CPVRTString
@Input _Right A string
@Input _Roff Offset into _Right
@Input _Count Number of chars from _Right to assign to the new string
@Description Constructor
************************************************************************/
CPVRTString(const CPVRTString& _Right, size_t _Roff = 0, size_t _Count = npos);
/*!***********************************************************************
@Function CPVRTString
@Input _Count Length of new string
@Input _Ch A char to fill it with
@Description Constructor
*************************************************************************/
CPVRTString(size_t _Count, const char _Ch);
/*!***********************************************************************
@Function CPVRTString
@Input _Ch A char
@Description Constructor
*************************************************************************/
CPVRTString(const char _Ch);
/*!***********************************************************************
@Function CPVRTString
@Description Constructor
************************************************************************/
CPVRTString();
/*!***********************************************************************
@Function ~CPVRTString
@Description Destructor
************************************************************************/
virtual ~CPVRTString();
/*!***********************************************************************
@Function append
@Input _Ptr A string
@Returns Updated string
@Description Appends a string
*************************************************************************/
CPVRTString& append(const char* _Ptr);
/*!***********************************************************************
@Function append
@Input _Ptr A string
@Input _Count String length
@Returns Updated string
@Description Appends a string of length _Count
*************************************************************************/
CPVRTString& append(const char* _Ptr, size_t _Count);
/*!***********************************************************************
@Function append
@Input _Str A string
@Returns Updated string
@Description Appends a string
*************************************************************************/
CPVRTString& append(const CPVRTString& _Str);
/*!***********************************************************************
@Function append
@Input _Str A string
@Input _Off A position in string
@Input _Count Number of letters to append
@Returns Updated string
@Description Appends _Count letters of _Str from _Off in _Str
*************************************************************************/
CPVRTString& append(const CPVRTString& _Str, size_t _Off, size_t _Count);
/*!***********************************************************************
@Function append
@Input _Ch A char
@Input _Count Number of times to append _Ch
@Returns Updated string
@Description Appends _Ch _Count times
*************************************************************************/
CPVRTString& append(size_t _Count, const char _Ch);
//template<class InputIterator> CPVRTString& append(InputIterator _First, InputIterator _Last);
/*!***********************************************************************
@Function assign
@Input _Ptr A string
@Returns Updated string
@Description Assigns the string to the string _Ptr
*************************************************************************/
CPVRTString& assign(const char* _Ptr);
/*!***********************************************************************
@Function assign
@Input _Ptr A string
@Input _Count Length of _Ptr
@Returns Updated string
@Description Assigns the string to the string _Ptr
*************************************************************************/
CPVRTString& assign(const char* _Ptr, size_t _Count);
/*!***********************************************************************
@Function assign
@Input _Str A string
@Returns Updated string
@Description Assigns the string to the string _Str
*************************************************************************/
CPVRTString& assign(const CPVRTString& _Str);
/*!***********************************************************************
@Function assign
@Input _Str A string
@Input _Off First char to start assignment from
@Input _Count Length of _Str
@Returns Updated string
@Description Assigns the string to _Count characters in string _Str starting at _Off
*************************************************************************/
CPVRTString& assign(const CPVRTString& _Str, size_t _Off, size_t _Count=npos);
/*!***********************************************************************
@Function assign
@Input _Ch A string
@Input _Count Number of times to repeat _Ch
@Returns Updated string
@Description Assigns the string to _Count copies of _Ch
*************************************************************************/
CPVRTString& assign(size_t _Count, char _Ch);
//template<class InputIterator> CPVRTString& assign(InputIterator _First, InputIterator _Last);
//const_reference at(size_t _Off) const;
//reference at(size_t _Off);
// const_iterator begin() const;
// iterator begin();
/*!***********************************************************************
@Function c_str
@Returns const char* pointer of the string
@Description Returns a const char* pointer of the string
*************************************************************************/
const char* c_str() const;
/*!***********************************************************************
@Function capacity
@Returns The size of the character array reserved
@Description Returns the size of the character array reserved
*************************************************************************/
size_t capacity() const;
/*!***********************************************************************
@Function clear
@Description Clears the string
*************************************************************************/
void clear();
/*!***********************************************************************
@Function compare
@Input _Str A string to compare with
@Returns 0 if the strings match
@Description Compares the string with _Str
*************************************************************************/
int compare(const CPVRTString& _Str) const;
/*!***********************************************************************
@Function compare
@Input _Pos1 Position to start comparing from
@Input _Num1 Number of chars to compare
@Input _Str A string to compare with
@Returns 0 if the strings match
@Description Compares the string with _Str
*************************************************************************/
int compare(size_t _Pos1, size_t _Num1, const CPVRTString& _Str) const;
/*!***********************************************************************
@Function compare
@Input _Pos1 Position to start comparing from
@Input _Num1 Number of chars to compare
@Input _Str A string to compare with
@Input _Off Position in _Str to compare from
@Input _Count Number of chars in _Str to compare with
@Returns 0 if the strings match
@Description Compares the string with _Str
*************************************************************************/
int compare(size_t _Pos1, size_t _Num1, const CPVRTString& _Str, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function compare
@Input _Ptr A string to compare with
@Returns 0 if the strings match
@Description Compares the string with _Ptr
*************************************************************************/
int compare(const char* _Ptr) const;
/*!***********************************************************************
@Function compare
@Input _Pos1 Position to start comparing from
@Input _Num1 Number of chars to compare
@Input _Ptr A string to compare with
@Returns 0 if the strings match
@Description Compares the string with _Ptr
*************************************************************************/
int compare(size_t _Pos1, size_t _Num1, const char* _Ptr) const;
/*!***********************************************************************
@Function compare
@Input _Pos1 Position to start comparing from
@Input _Num1 Number of chars to compare
@Input _Ptr A string to compare with
@Input _Count Number of chars to compare
@Returns 0 if the strings match
@Description Compares the string with _Str
*************************************************************************/
int compare(size_t _Pos1, size_t _Num1, const char* _Ptr, size_t _Count) const;
/*!***********************************************************************
@Function <
@Input _Str A string to compare with
@Returns True on success
@Description Less than operator
*************************************************************************/
bool operator<(const CPVRTString & _Str) const;
/*!***********************************************************************
@Function ==
@Input _Str A string to compare with
@Returns True if they match
@Description == Operator
*************************************************************************/
bool operator==(const CPVRTString& _Str) const;
/*!***********************************************************************
@Function ==
@Input _Ptr A string to compare with
@Returns True if they match
@Description == Operator
*************************************************************************/
bool operator==(const char* const _Ptr) const;
/*!***********************************************************************
@Function !=
@Input _Str A string to compare with
@Returns True if they don't match
@Description != Operator
*************************************************************************/
bool operator!=(const CPVRTString& _Str) const;
/*!***********************************************************************
@Function !=
@Input _Ptr A string to compare with
@Returns True if they don't match
@Description != Operator
*************************************************************************/
bool operator!=(const char* const _Ptr) const;
/*!***********************************************************************
@Function copy
@Modified _Ptr A string to copy to
@Input _Count Size of _Ptr
@Input _Off Position to start copying from
@Returns Number of bytes copied
@Description Copies the string to _Ptr
*************************************************************************/
size_t copy(char* _Ptr, size_t _Count, size_t _Off = 0) const;
/*!***********************************************************************
@Function data
@Returns A const char* version of the string
@Description Returns a const char* version of the string
*************************************************************************/
const char* data( ) const;
/*!***********************************************************************
@Function empty
@Returns True if the string is empty
@Description Returns true if the string is empty
*************************************************************************/
bool empty() const;
// const_iterator end() const;
// iterator end();
//iterator erase(iterator _First, iterator _Last);
//iterator erase(iterator _It);
/*!***********************************************************************
@Function erase
@Input _Pos The position to start erasing from
@Input _Count Number of chars to erase
@Returns An updated string
@Description Erases a portion of the string
*************************************************************************/
CPVRTString& erase(size_t _Pos = 0, size_t _Count = npos);
/*!***********************************************************************
@Function substitute
@Input _src Character to search
@Input _subDes Character to substitute for
@Input _all Substitute all
@Returns An updated string
@Description Erases a portion of the string
*************************************************************************/
CPVRTString& substitute(char _src,char _subDes, bool _all = true);
/*!***********************************************************************
@Function substitute
@Input _src Character to search
@Input _subDes Character to substitute for
@Input _all Substitute all
@Returns An updated string
@Description Erases a portion of the string
*************************************************************************/
CPVRTString& substitute(const char* _src, const char* _subDes, bool _all = true);
//size_t find(char _Ch, size_t _Off = 0) const;
//size_t find(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find
@Input _Ptr String to search.
@Input _Off Offset to search from.
@Input _Count Number of characters in this string.
@Returns Position of the first matched string.
@Description Finds a substring within this string.
*************************************************************************/
size_t find(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find
@Input _Str String to search.
@Input _Off Offset to search from.
@Returns Position of the first matched string.
@Description Finds a substring within this string.
*************************************************************************/
size_t find(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_first_not_of
@Input _Ch A char
@Input _Off Start position of the find
@Returns Position of the first char that is not _Ch
@Description Returns the position of the first char that is not _Ch
*************************************************************************/
size_t find_first_not_of(char _Ch, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_first_not_of
@Input _Ptr A string
@Input _Off Start position of the find
@Returns Position of the first char that is not in _Ptr
@Description Returns the position of the first char that is not in _Ptr
*************************************************************************/
size_t find_first_not_of(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_first_not_of
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Number of chars in _Ptr
@Returns Position of the first char that is not in _Ptr
@Description Returns the position of the first char that is not in _Ptr
*************************************************************************/
size_t find_first_not_of(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_first_not_of
@Input _Str A string
@Input _Off Start position of the find
@Returns Position of the first char that is not in _Str
@Description Returns the position of the first char that is not in _Str
*************************************************************************/
size_t find_first_not_of(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_first_of
@Input _Ch A char
@Input _Off Start position of the find
@Returns Position of the first char that is _Ch
@Description Returns the position of the first char that is _Ch
*************************************************************************/
size_t find_first_of(char _Ch, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_first_of
@Input _Ptr A string
@Input _Off Start position of the find
@Returns Position of the first char that matches a char in _Ptr
@Description Returns the position of the first char that matches a char in _Ptr
*************************************************************************/
size_t find_first_of(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_first_of
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Size of _Ptr
@Returns Position of the first char that matches a char in _Ptr
@Description Returns the position of the first char that matches a char in _Ptr
*************************************************************************/
size_t find_first_of(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_first_ofn
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Size of _Ptr
@Returns Position of the first char that matches a char in _Ptr
@Description Returns the position of the first char that matches all chars in _Ptr
*************************************************************************/
size_t find_first_ofn(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_first_of
@Input _Str A string
@Input _Off Start position of the find
@Returns Position of the first char that matches a char in _Str
@Description Returns the position of the first char that matches a char in _Str
*************************************************************************/
size_t find_first_of(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_last_not_of
@Input _Ch A char
@Input _Off Start position of the find
@Returns Position of the last char that is not _Ch
@Description Returns the position of the last char that is not _Ch
*************************************************************************/
size_t find_last_not_of(char _Ch, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_last_not_of
@Input _Ptr A string
@Input _Off Start position of the find
@Returns Position of the last char that is not in _Ptr
@Description Returns the position of the last char that is not in _Ptr
*************************************************************************/
size_t find_last_not_of(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_last_not_of
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Length of _Ptr
@Returns Position of the last char that is not in _Ptr
@Description Returns the position of the last char that is not in _Ptr
*************************************************************************/
size_t find_last_not_of(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_last_not_of
@Input _Str A string
@Input _Off Start position of the find
@Returns Position of the last char that is not in _Str
@Description Returns the position of the last char that is not in _Str
*************************************************************************/
size_t find_last_not_of(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_last_of
@Input _Ch A char
@Input _Off Start position of the find
@Returns Position of the last char that is _Ch
@Description Returns the position of the last char that is _Ch
*************************************************************************/
size_t find_last_of(char _Ch, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_last_of
@Input _Ptr A string
@Input _Off Start position of the find
@Returns Position of the last char that is in _Ptr
@Description Returns the position of the last char that is in _Ptr
*************************************************************************/
size_t find_last_of(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_last_of
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Length of _Ptr
@Returns Position of the last char that is in _Ptr
@Description Returns the position of the last char that is in _Ptr
*************************************************************************/
size_t find_last_of(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_last_of
@Input _Str A string
@Input _Off Start position of the find
@Returns Position of the last char that is in _Str
@Description Returns the position of the last char that is in _Str
*************************************************************************/
size_t find_last_of(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_number_of
@Input _Ch A char
@Input _Off Start position of the find
@Returns Number of occurances of _Ch in the parent string.
@Description Returns the number of occurances of _Ch in the parent string.
*************************************************************************/
size_t find_number_of(char _Ch, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_number_of
@Input _Ptr A string
@Input _Off Start position of the find
@Returns Number of occurances of _Ptr in the parent string.
@Description Returns the number of occurances of _Ptr in the parent string.
*************************************************************************/
size_t find_number_of(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_number_of
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Size of _Ptr
@Returns Number of occurances of _Ptr in the parent string.
@Description Returns the number of occurances of _Ptr in the parent string.
*************************************************************************/
size_t find_number_of(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_number_of
@Input _Str A string
@Input _Off Start position of the find
@Returns Number of occurances of _Str in the parent string.
@Description Returns the number of occurances of _Str in the parent string.
*************************************************************************/
size_t find_number_of(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_next_occurance_of
@Input _Ch A char
@Input _Off Start position of the find
@Returns Next occurance of _Ch in the parent string.
@Description Returns the next occurance of _Ch in the parent string
after or at _Off. If not found, returns the length of the string.
*************************************************************************/
int find_next_occurance_of(char _Ch, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_next_occurance_of
@Input _Ptr A string
@Input _Off Start position of the find
@Returns Next occurance of _Ptr in the parent string.
@Description Returns the next occurance of _Ptr in the parent string
after or at _Off. If not found, returns the length of the string.
*************************************************************************/
int find_next_occurance_of(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_next_occurance_of
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Size of _Ptr
@Returns Next occurance of _Ptr in the parent string.
@Description Returns the next occurance of _Ptr in the parent string
after or at _Off. If not found, returns the length of the string.
*************************************************************************/
int find_next_occurance_of(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_next_occurance_of
@Input _Str A string
@Input _Off Start position of the find
@Returns Next occurance of _Str in the parent string.
@Description Returns the next occurance of _Str in the parent string
after or at _Off. If not found, returns the length of the string.
*************************************************************************/
int find_next_occurance_of(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_previous_occurance_of
@Input _Ch A char
@Input _Off Start position of the find
@Returns Previous occurance of _Ch in the parent string.
@Description Returns the previous occurance of _Ch in the parent string
before _Off. If not found, returns -1.
*************************************************************************/
int find_previous_occurance_of(char _Ch, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_previous_occurance_of
@Input _Ptr A string
@Input _Off Start position of the find
@Returns Previous occurance of _Ptr in the parent string.
@Description Returns the previous occurance of _Ptr in the parent string
before _Off. If not found, returns -1.
*************************************************************************/
int find_previous_occurance_of(const char* _Ptr, size_t _Off = 0) const;
/*!***********************************************************************
@Function find_previous_occurance_of
@Input _Ptr A string
@Input _Off Start position of the find
@Input _Count Size of _Ptr
@Returns Previous occurance of _Ptr in the parent string.
@Description Returns the previous occurance of _Ptr in the parent string
before _Off. If not found, returns -1.
*************************************************************************/
int find_previous_occurance_of(const char* _Ptr, size_t _Off, size_t _Count) const;
/*!***********************************************************************
@Function find_previous_occurance_of
@Input _Str A string
@Input _Off Start position of the find
@Returns Previous occurance of _Str in the parent string.
@Description Returns the previous occurance of _Str in the parent string
before _Off. If not found, returns -1.
*************************************************************************/
int find_previous_occurance_of(const CPVRTString& _Str, size_t _Off = 0) const;
/*!***********************************************************************
@Function left
@Input iSize number of characters to return (excluding null character)
@Returns The leftmost 'iSize' characters of the string.
@Description Returns the leftmost characters of the string (excluding
the null character) in a new CPVRTString. If iSize is
larger than the string, a copy of the original string is returned.
*************************************************************************/
CPVRTString left(size_t iSize) const;
/*!***********************************************************************
@Function right
@Input iSize number of characters to return (excluding null character)
@Returns The rightmost 'iSize' characters of the string.
@Description Returns the rightmost characters of the string (excluding
the null character) in a new CPVRTString. If iSize is
larger than the string, a copy of the original string is returned.
*************************************************************************/
CPVRTString right(size_t iSize) const;
//allocator_type get_allocator( ) const;
//CPVRTString& insert(size_t _P0, const char* _Ptr);
//CPVRTString& insert(size_t _P0, const char* _Ptr, size_t _Count);
//CPVRTString& insert(size_t _P0, const CPVRTString& _Str);
//CPVRTString& insert(size_t _P0, const CPVRTString& _Str, size_t _Off, size_t _Count);
//CPVRTString& insert(size_t _P0, size_t _Count, char _Ch);
//iterator insert(iterator _It, char _Ch = char());
//template<class InputIterator> void insert(iterator _It, InputIterator _First, InputIterator _Last);
//void insert(iterator _It, size_t _Count, char _Ch);
/*!***********************************************************************
@Function length
@Returns Length of the string
@Description Returns the length of the string
*************************************************************************/
size_t length() const;
/*!***********************************************************************
@Function max_size
@Returns The maximum number of chars that the string can contain
@Description Returns the maximum number of chars that the string can contain
*************************************************************************/
size_t max_size() const;
/*!***********************************************************************
@Function push_back
@Input _Ch A char to append
@Description Appends _Ch to the string
*************************************************************************/
void push_back(char _Ch);
// const_reverse_iterator rbegin() const;
// reverse_iterator rbegin();
// const_reverse_iterator rend() const;
// reverse_iterator rend();
//CPVRTString& replace(size_t _Pos1, size_t _Num1, const char* _Ptr);
//CPVRTString& replace(size_t _Pos1, size_t _Num1, const CPVRTString& _Str);
//CPVRTString& replace(size_t _Pos1, size_t _Num1, const char* _Ptr, size_t _Num2);
//CPVRTString& replace(size_t _Pos1, size_t _Num1, const CPVRTString& _Str, size_t _Pos2, size_t _Num2);
//CPVRTString& replace(size_t _Pos1, size_t _Num1, size_t _Count, char _Ch);
//CPVRTString& replace(iterator _First0, iterator _Last0, const char* _Ptr);
//CPVRTString& replace(iterator _First0, iterator _Last0, const CPVRTString& _Str);
//CPVRTString& replace(iterator _First0, iterator _Last0, const char* _Ptr, size_t _Num2);
//CPVRTString& replace(iterator _First0, iterator _Last0, size_t _Num2, char _Ch);
//template<class InputIterator> CPVRTString& replace(iterator _First0, iterator _Last0, InputIterator _First, InputIterator _Last);
/*!***********************************************************************
@Function reserve
@Input _Count Size of string to reserve
@Description Reserves space for _Count number of chars
*************************************************************************/
void reserve(size_t _Count = 0);
/*!***********************************************************************
@Function resize
@Input _Count Size of string to resize to
@Input _Ch Character to use to fill any additional space
@Description Resizes the string to _Count in length
*************************************************************************/
void resize(size_t _Count, char _Ch = char());
//size_t rfind(char _Ch, size_t _Off = npos) const;
//size_t rfind(const char* _Ptr, size_t _Off = npos) const;
//size_t rfind(const char* _Ptr, size_t _Off = npos, size_t _Count) const;
//size_t rfind(const CPVRTString& _Str, size_t _Off = npos) const;
/*!***********************************************************************
@Function size
@Returns Size of the string
@Description Returns the size of the string
*************************************************************************/
size_t size() const;
/*!***********************************************************************
@Function substr
@Input _Off Start of the substring
@Input _Count Length of the substring
@Returns A substring of the string
@Description Returns the size of the string
*************************************************************************/
CPVRTString substr(size_t _Off = 0, size_t _Count = npos) const;
/*!***********************************************************************
@Function swap
@Input _Str A string to swap with
@Description Swaps the contents of the string with _Str
*************************************************************************/
void swap(CPVRTString& _Str);
/*!***********************************************************************
@Function toLower
@Returns An updated string
@Description Converts the string to lower case
*************************************************************************/
CPVRTString& toLower();
/*!***********************************************************************
@Function toUpper
@Returns An updated string
@Description Converts the string to upper case
*************************************************************************/
CPVRTString& toUpper();
/*!***********************************************************************
@Function format
@Input pFormat A string containing the formating
@Returns A formatted string
@Description return the formatted string
************************************************************************/
CPVRTString format(const char *pFormat, ...);
/*!***********************************************************************
@Function +=
@Input _Ch A char
@Returns An updated string
@Description += Operator
*************************************************************************/
CPVRTString& operator+=(char _Ch);
/*!***********************************************************************
@Function +=
@Input _Ptr A string
@Returns An updated string
@Description += Operator
*************************************************************************/
CPVRTString& operator+=(const char* _Ptr);
/*!***********************************************************************
@Function +=
@Input _Right A string
@Returns An updated string
@Description += Operator
*************************************************************************/
CPVRTString& operator+=(const CPVRTString& _Right);
/*!***********************************************************************
@Function =
@Input _Ch A char
@Returns An updated string
@Description = Operator
*************************************************************************/
CPVRTString& operator=(char _Ch);
/*!***********************************************************************
@Function =
@Input _Ptr A string
@Returns An updated string
@Description = Operator
*************************************************************************/
CPVRTString& operator=(const char* _Ptr);
/*!***********************************************************************
@Function =
@Input _Right A string
@Returns An updated string
@Description = Operator
*************************************************************************/
CPVRTString& operator=(const CPVRTString& _Right);
/*!***********************************************************************
@Function []
@Input _Off An index into the string
@Returns A character
@Description [] Operator
*************************************************************************/
const_reference operator[](size_t _Off) const;
/*!***********************************************************************
@Function []
@Input _Off An index into the string
@Returns A character
@Description [] Operator
*************************************************************************/
reference operator[](size_t _Off);
/*!***********************************************************************
@Function +
@Input _Left A string
@Input _Right A string
@Returns An updated string
@Description + Operator
*************************************************************************/
friend CPVRTString operator+ (const CPVRTString& _Left, const CPVRTString& _Right);
/*!***********************************************************************
@Function +
@Input _Left A string
@Input _Right A string
@Returns An updated string
@Description + Operator
*************************************************************************/
friend CPVRTString operator+ (const CPVRTString& _Left, const char* _Right);
/*!***********************************************************************
@Function +
@Input _Left A string
@Input _Right A string
@Returns An updated string
@Description + Operator
*************************************************************************/
friend CPVRTString operator+ (const CPVRTString& _Left, const char _Right);
/*!***********************************************************************
@Function +
@Input _Left A string
@Input _Right A string
@Returns An updated string
@Description + Operator
*************************************************************************/
friend CPVRTString operator+ (const char* _Left, const CPVRTString& _Right);
/*!***********************************************************************
@Function +
@Input _Left A string
@Input _Right A string
@Returns An updated string
@Description + Operator
*************************************************************************/
friend CPVRTString operator+ (const char _Left, const CPVRTString& _Right);
protected:
char* m_pString;
size_t m_Size;
size_t m_Capacity;
};
/*************************************************************************
* MISCELLANEOUS UTILITY FUNCTIONS
*************************************************************************/
/*!***********************************************************************
@Function PVRTStringGetFileExtension
@Input strFilePath A string
@Returns Extension
@Description Extracts the file extension from a file path.
Returns an empty CPVRTString if no extension is found.
************************************************************************/
CPVRTString PVRTStringGetFileExtension(const CPVRTString& strFilePath);
/*!***********************************************************************
@Function PVRTStringGetContainingDirectoryPath
@Input strFilePath A string
@Returns Directory
@Description Extracts the directory portion from a file path.
************************************************************************/
CPVRTString PVRTStringGetContainingDirectoryPath(const CPVRTString& strFilePath);
/*!***********************************************************************
@Function PVRTStringGetFileName
@Input strFilePath A string
@Returns FileName
@Description Extracts the name and extension portion from a file path.
************************************************************************/
CPVRTString PVRTStringGetFileName(const CPVRTString& strFilePath);
/*!***********************************************************************
@Function PVRTStringStripWhiteSpaceFromStartOf
@Input strLine A string
@Returns Result of the white space stripping
@Description strips white space characters from the beginning of a CPVRTString.
************************************************************************/
CPVRTString PVRTStringStripWhiteSpaceFromStartOf(const CPVRTString& strLine);
/*!***********************************************************************
@Function PVRTStringStripWhiteSpaceFromEndOf
@Input strLine A string
@Returns Result of the white space stripping
@Description strips white space characters from the end of a CPVRTString.
************************************************************************/
CPVRTString PVRTStringStripWhiteSpaceFromEndOf(const CPVRTString& strLine);
/*!***********************************************************************
@Function PVRTStringFromFormattedStr
@Input pFormat A string containing the formating
@Returns A formatted string
@Description Creates a formatted string
************************************************************************/
CPVRTString PVRTStringFromFormattedStr(const char *pFormat, ...);
#endif // _PVRTSTRING_H_
/*****************************************************************************
End of file (PVRTString.h)
*****************************************************************************/

@ -0,0 +1,703 @@
/******************************************************************************
@File PVRTTexture.h
@Title PVRTTexture
@Version @Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description Texture loading.
******************************************************************************/
#ifndef _PVRTTEXTURE_H_
#define _PVRTTEXTURE_H_
//ACS: PVRTGlobal.h was dragging in too much stuff (like windows.h & crtdbg.h)
// so I split the relevant stuff out into a new file, PVRTTypes.h
//#include "PVRTGlobal.h"
#include "PVRTTypes.h"
/*****************************************************************************
* Texture related constants and enumerations.
*****************************************************************************/
// V3 Header Identifiers.
const PVRTuint32 PVRTEX3_IDENT = 0x03525650; // 'P''V''R'3
const PVRTuint32 PVRTEX3_IDENT_REV = 0x50565203;
// If endianness is backwards then PVR3 will read as 3RVP, hence why it is written as an int.
//Current version texture identifiers
const PVRTuint32 PVRTEX_CURR_IDENT = PVRTEX3_IDENT;
const PVRTuint32 PVRTEX_CURR_IDENT_REV = PVRTEX3_IDENT_REV;
// PVR Header file flags. Condition if true. If false, opposite is true unless specified.
const PVRTuint32 PVRTEX3_FILE_COMPRESSED = (1<<0); // Texture has been file compressed using PVRTexLib (currently unused)
const PVRTuint32 PVRTEX3_PREMULTIPLIED = (1<<1); // Texture has been premultiplied by alpha value.
// Mip Map level specifier constants. Other levels are specified by 1,2...n
const PVRTint32 PVRTEX_TOPMIPLEVEL = 0;
const PVRTint32 PVRTEX_ALLMIPLEVELS = -1; //This is a special number used simply to return a total of all MIP levels when dealing with data sizes.
//values for each meta data type that we know about. Texture arrays hinge on each surface being identical in all but content, including meta data.
//If the meta data varies even slightly then a new texture should be used. It is possible to write your own extension to get around this however.
enum EPVRTMetaData
{
ePVRTMetaDataTextureAtlasCoords=0,
ePVRTMetaDataBumpData,
ePVRTMetaDataCubeMapOrder,
ePVRTMetaDataTextureOrientation,
ePVRTMetaDataBorderData,
ePVRTMetaDataPadding,
ePVRTMetaDataNumMetaDataTypes
};
enum EPVRTAxis
{
ePVRTAxisX = 0,
ePVRTAxisY = 1,
ePVRTAxisZ = 2
};
enum EPVRTOrientation
{
ePVRTOrientLeft = 1<<ePVRTAxisX,
ePVRTOrientRight= 0,
ePVRTOrientUp = 1<<ePVRTAxisY,
ePVRTOrientDown = 0,
ePVRTOrientOut = 1<<ePVRTAxisZ,
ePVRTOrientIn = 0
};
enum EPVRTColourSpace
{
ePVRTCSpacelRGB,
ePVRTCSpacesRGB,
ePVRTCSpaceNumSpaces
};
//Compressed pixel formats
enum EPVRTPixelFormat
{
ePVRTPF_PVRTCI_2bpp_RGB,
ePVRTPF_PVRTCI_2bpp_RGBA,
ePVRTPF_PVRTCI_4bpp_RGB,
ePVRTPF_PVRTCI_4bpp_RGBA,
ePVRTPF_PVRTCII_2bpp,
ePVRTPF_PVRTCII_4bpp,
ePVRTPF_ETC1,
ePVRTPF_DXT1,
ePVRTPF_DXT2,
ePVRTPF_DXT3,
ePVRTPF_DXT4,
ePVRTPF_DXT5,
//These formats are identical to some DXT formats.
ePVRTPF_BC1 = ePVRTPF_DXT1,
ePVRTPF_BC2 = ePVRTPF_DXT3,
ePVRTPF_BC3 = ePVRTPF_DXT5,
//These are currently unsupported:
ePVRTPF_BC4,
ePVRTPF_BC5,
ePVRTPF_BC6,
ePVRTPF_BC7,
//These are supported
ePVRTPF_UYVY,
ePVRTPF_YUY2,
ePVRTPF_BW1bpp,
ePVRTPF_SharedExponentR9G9B9E5,
ePVRTPF_RGBG8888,
ePVRTPF_GRGB8888,
ePVRTPF_ETC2_RGB,
ePVRTPF_ETC2_RGBA,
ePVRTPF_ETC2_RGB_A1,
ePVRTPF_EAC_R11,
ePVRTPF_EAC_RG11,
//Invalid value
ePVRTPF_NumCompressedPFs
};
//Variable Type Names
enum EPVRTVariableType
{
ePVRTVarTypeUnsignedByteNorm,
ePVRTVarTypeSignedByteNorm,
ePVRTVarTypeUnsignedByte,
ePVRTVarTypeSignedByte,
ePVRTVarTypeUnsignedShortNorm,
ePVRTVarTypeSignedShortNorm,
ePVRTVarTypeUnsignedShort,
ePVRTVarTypeSignedShort,
ePVRTVarTypeUnsignedIntegerNorm,
ePVRTVarTypeSignedIntegerNorm,
ePVRTVarTypeUnsignedInteger,
ePVRTVarTypeSignedInteger,
ePVRTVarTypeSignedFloat, ePVRTVarTypeFloat=ePVRTVarTypeSignedFloat, //the name ePVRTVarTypeFloat is now deprecated.
ePVRTVarTypeUnsignedFloat,
ePVRTVarTypeNumVarTypes
};
//A 64 bit pixel format ID & this will give you the high bits of a pixel format to check for a compressed format.
static const PVRTuint64 PVRTEX_PFHIGHMASK=0xffffffff00000000ull;
/*****************************************************************************
* Texture header structures.
*****************************************************************************/
struct MetaDataBlock
{
PVRTuint32 DevFOURCC; //A 4cc descriptor of the data type's creator. Values equating to values between 'P' 'V' 'R' 0 and 'P' 'V' 'R' 255 will be used by our headers.
PVRTuint32 u32Key; //A DWORD (enum value) identifying the data type, and thus how to read it.
PVRTuint32 u32DataSize; //Size of the Data member.
PVRTuint8* Data; //Data array, can be absolutely anything, the loader needs to know how to handle it based on DevFOURCC and Key. Use new operator to assign to it.
/*!***********************************************************************
@Function MetaDataBlock
@Description Meta Data Block Constructor
*************************************************************************/
MetaDataBlock() : DevFOURCC(0), u32Key(0), u32DataSize(0), Data(NULL)
{}
/*!***********************************************************************
@Function MetaDataBlock
@Description Meta Data Block Copy Constructor
*************************************************************************/
MetaDataBlock(const MetaDataBlock& rhs) : DevFOURCC(rhs.DevFOURCC), u32Key(rhs.u32Key), u32DataSize(rhs.u32DataSize)
{
//Copy the data across.
Data = new PVRTuint8[u32DataSize];
for (PVRTuint32 uiDataAmt=0; uiDataAmt<u32DataSize; ++uiDataAmt)
{
Data[uiDataAmt]=rhs.Data[uiDataAmt];
}
}
/*!***********************************************************************
@Function ~MetaDataBlock
@Description Meta Data Block Destructor
*************************************************************************/
~MetaDataBlock()
{
if (Data)
delete [] Data;
Data = NULL;
}
/*!***********************************************************************
@Function SizeOfBlock
@Return size_t Size (in a file) of the block.
@Description Returns the number of extra bytes this will add to any output files.
*************************************************************************/
size_t SizeOfBlock() const
{
return sizeof(DevFOURCC)+sizeof(u32Key)+sizeof(u32DataSize)+u32DataSize;
}
/*!***********************************************************************
@Function operator=
@Return MetaDataBlock This MetaDataBlock after the operation.
@Description Assigns one MetaDataBlock to the other.
*************************************************************************/
MetaDataBlock& operator=(const MetaDataBlock& rhs)
{
if (&rhs==this)
return *this;
//Remove pre-existing data.
if (Data)
delete [] Data;
Data=NULL;
//Copy the basic parameters
DevFOURCC=rhs.DevFOURCC;
u32Key=rhs.u32Key;
u32DataSize=rhs.u32DataSize;
//Copy the data across.
if (rhs.Data)
{
Data = new PVRTuint8[u32DataSize];
for (PVRTuint32 uiDataAmt=0; uiDataAmt<u32DataSize; ++uiDataAmt)
{
Data[uiDataAmt]=rhs.Data[uiDataAmt];
}
}
return *this;
}
/*!***************************************************************************
@Function ReadFromPtr
@Input pDataCursor The data to read
@Description Reads from a pointer of memory in to the meta data block.
*****************************************************************************/
bool ReadFromPtr(const unsigned char** pDataCursor);
};
//The idea behind this is that it stores EVERYTHING that you would ever need to read a texture accurately, and nothing more.
//Extraneous data is stored in meta data. Correct use of the texture may rely on meta data, but accurate data loading can be done through the
//Standard header alone.
#pragma pack(push,4)
struct PVRTextureHeaderV3{
PVRTuint32 u32Version; //Version of the file header, used to identify it.
PVRTuint32 u32Flags; //Various format flags.
PVRTuint64 u64PixelFormat; //The pixel format, 8cc value storing the 4 channel identifiers and their respective sizes.
PVRTuint32 u32ColourSpace; //The Colour Space of the texture, currently either linear RGB or sRGB.
PVRTuint32 u32ChannelType; //Variable type that the channel is stored in. Supports signed/unsigned int/short/byte or float for now.
PVRTuint32 u32Height; //Height of the texture.
PVRTuint32 u32Width; //Width of the texture.
PVRTuint32 u32Depth; //Depth of the texture. (Z-slices)
PVRTuint32 u32NumSurfaces; //Number of members in a Texture Array.
PVRTuint32 u32NumFaces; //Number of faces in a Cube Map. Maybe be a value other than 6.
PVRTuint32 u32MIPMapCount; //Number of MIP Maps in the texture - NB: Includes top level.
PVRTuint32 u32MetaDataSize; //Size of the accompanying meta data.
//Constructor for the header - used to make sure that the header is initialised usefully. The initial pixel format is an invalid one and must be set.
PVRTextureHeaderV3() :
u32Version(PVRTEX3_IDENT),u32Flags(0),
u64PixelFormat(ePVRTPF_NumCompressedPFs),
u32ColourSpace(0),u32ChannelType(0),
u32Height(1),u32Width(1),u32Depth(1),
u32NumSurfaces(1),u32NumFaces(1),
u32MIPMapCount(1),u32MetaDataSize(0)
{}
};
#pragma pack(pop)
#define PVRTEX3_HEADERSIZE 52
/*!***************************************************************************
Describes the Version 2 header of a PVR texture header.
*****************************************************************************/
struct PVR_Texture_Header
{
PVRTuint32 dwHeaderSize; /*!< size of the structure */
PVRTuint32 dwHeight; /*!< height of surface to be created */
PVRTuint32 dwWidth; /*!< width of input surface */
PVRTuint32 dwMipMapCount; /*!< number of mip-map levels requested */
PVRTuint32 dwpfFlags; /*!< pixel format flags */
PVRTuint32 dwTextureDataSize; /*!< Total size in bytes */
PVRTuint32 dwBitCount; /*!< number of bits per pixel */
PVRTuint32 dwRBitMask; /*!< mask for red bit */
PVRTuint32 dwGBitMask; /*!< mask for green bits */
PVRTuint32 dwBBitMask; /*!< mask for blue bits */
PVRTuint32 dwAlphaBitMask; /*!< mask for alpha channel */
PVRTuint32 dwPVR; /*!< magic number identifying pvr file */
PVRTuint32 dwNumSurfs; /*!< the number of surfaces present in the pvr */
} ;
/*****************************************************************************
* Legacy (V2 and V1) ENUMS
*****************************************************************************/
enum PVRTPixelType
{
MGLPT_ARGB_4444 = 0x00,
MGLPT_ARGB_1555,
MGLPT_RGB_565,
MGLPT_RGB_555,
MGLPT_RGB_888,
MGLPT_ARGB_8888,
MGLPT_ARGB_8332,
MGLPT_I_8,
MGLPT_AI_88,
MGLPT_1_BPP,
MGLPT_VY1UY0,
MGLPT_Y1VY0U,
MGLPT_PVRTC2,
MGLPT_PVRTC4,
// OpenGL version of pixel types
OGL_RGBA_4444= 0x10,
OGL_RGBA_5551,
OGL_RGBA_8888,
OGL_RGB_565,
OGL_RGB_555,
OGL_RGB_888,
OGL_I_8,
OGL_AI_88,
OGL_PVRTC2,
OGL_PVRTC4,
OGL_BGRA_8888,
OGL_A_8,
OGL_PVRTCII4, //Not in use
OGL_PVRTCII2, //Not in use
// S3TC Encoding
D3D_DXT1 = 0x20,
D3D_DXT2,
D3D_DXT3,
D3D_DXT4,
D3D_DXT5,
//RGB Formats
D3D_RGB_332,
D3D_AL_44,
D3D_LVU_655,
D3D_XLVU_8888,
D3D_QWVU_8888,
//10 bit integer - 2 bit alpha
D3D_ABGR_2101010,
D3D_ARGB_2101010,
D3D_AWVU_2101010,
//16 bit integers
D3D_GR_1616,
D3D_VU_1616,
D3D_ABGR_16161616,
//Float Formats
D3D_R16F,
D3D_GR_1616F,
D3D_ABGR_16161616F,
//32 bits per channel
D3D_R32F,
D3D_GR_3232F,
D3D_ABGR_32323232F,
// Ericsson
ETC_RGB_4BPP,
ETC_RGBA_EXPLICIT, // unimplemented
ETC_RGBA_INTERPOLATED, // unimplemented
D3D_A8 = 0x40,
D3D_V8U8,
D3D_L16,
D3D_L8,
D3D_AL_88,
//Y'UV Colourspace
D3D_UYVY,
D3D_YUY2,
// DX10
DX10_R32G32B32A32_FLOAT= 0x50,
DX10_R32G32B32A32_UINT ,
DX10_R32G32B32A32_SINT,
DX10_R32G32B32_FLOAT,
DX10_R32G32B32_UINT,
DX10_R32G32B32_SINT,
DX10_R16G16B16A16_FLOAT ,
DX10_R16G16B16A16_UNORM,
DX10_R16G16B16A16_UINT ,
DX10_R16G16B16A16_SNORM ,
DX10_R16G16B16A16_SINT ,
DX10_R32G32_FLOAT ,
DX10_R32G32_UINT ,
DX10_R32G32_SINT ,
DX10_R10G10B10A2_UNORM ,
DX10_R10G10B10A2_UINT ,
DX10_R11G11B10_FLOAT , // unimplemented
DX10_R8G8B8A8_UNORM ,
DX10_R8G8B8A8_UNORM_SRGB ,
DX10_R8G8B8A8_UINT ,
DX10_R8G8B8A8_SNORM ,
DX10_R8G8B8A8_SINT ,
DX10_R16G16_FLOAT ,
DX10_R16G16_UNORM ,
DX10_R16G16_UINT ,
DX10_R16G16_SNORM ,
DX10_R16G16_SINT ,
DX10_R32_FLOAT ,
DX10_R32_UINT ,
DX10_R32_SINT ,
DX10_R8G8_UNORM ,
DX10_R8G8_UINT ,
DX10_R8G8_SNORM ,
DX10_R8G8_SINT ,
DX10_R16_FLOAT ,
DX10_R16_UNORM ,
DX10_R16_UINT ,
DX10_R16_SNORM ,
DX10_R16_SINT ,
DX10_R8_UNORM,
DX10_R8_UINT,
DX10_R8_SNORM,
DX10_R8_SINT,
DX10_A8_UNORM,
DX10_R1_UNORM,
DX10_R9G9B9E5_SHAREDEXP, // unimplemented
DX10_R8G8_B8G8_UNORM, // unimplemented
DX10_G8R8_G8B8_UNORM, // unimplemented
DX10_BC1_UNORM,
DX10_BC1_UNORM_SRGB,
DX10_BC2_UNORM,
DX10_BC2_UNORM_SRGB,
DX10_BC3_UNORM,
DX10_BC3_UNORM_SRGB,
DX10_BC4_UNORM, // unimplemented
DX10_BC4_SNORM, // unimplemented
DX10_BC5_UNORM, // unimplemented
DX10_BC5_SNORM, // unimplemented
// OpenVG
/* RGB{A,X} channel ordering */
ePT_VG_sRGBX_8888 = 0x90,
ePT_VG_sRGBA_8888,
ePT_VG_sRGBA_8888_PRE,
ePT_VG_sRGB_565,
ePT_VG_sRGBA_5551,
ePT_VG_sRGBA_4444,
ePT_VG_sL_8,
ePT_VG_lRGBX_8888,
ePT_VG_lRGBA_8888,
ePT_VG_lRGBA_8888_PRE,
ePT_VG_lL_8,
ePT_VG_A_8,
ePT_VG_BW_1,
/* {A,X}RGB channel ordering */
ePT_VG_sXRGB_8888,
ePT_VG_sARGB_8888,
ePT_VG_sARGB_8888_PRE,
ePT_VG_sARGB_1555,
ePT_VG_sARGB_4444,
ePT_VG_lXRGB_8888,
ePT_VG_lARGB_8888,
ePT_VG_lARGB_8888_PRE,
/* BGR{A,X} channel ordering */
ePT_VG_sBGRX_8888,
ePT_VG_sBGRA_8888,
ePT_VG_sBGRA_8888_PRE,
ePT_VG_sBGR_565,
ePT_VG_sBGRA_5551,
ePT_VG_sBGRA_4444,
ePT_VG_lBGRX_8888,
ePT_VG_lBGRA_8888,
ePT_VG_lBGRA_8888_PRE,
/* {A,X}BGR channel ordering */
ePT_VG_sXBGR_8888,
ePT_VG_sABGR_8888 ,
ePT_VG_sABGR_8888_PRE,
ePT_VG_sABGR_1555,
ePT_VG_sABGR_4444,
ePT_VG_lXBGR_8888,
ePT_VG_lABGR_8888,
ePT_VG_lABGR_8888_PRE,
// max cap for iterating
END_OF_PIXEL_TYPES,
MGLPT_NOTYPE = 0xffffffff
};
/*****************************************************************************
* Legacy constants (V1/V2)
*****************************************************************************/
const PVRTuint32 PVRTEX_MIPMAP = (1<<8); // has mip map levels
const PVRTuint32 PVRTEX_TWIDDLE = (1<<9); // is twiddled
const PVRTuint32 PVRTEX_BUMPMAP = (1<<10); // has normals encoded for a bump map
const PVRTuint32 PVRTEX_TILING = (1<<11); // is bordered for tiled pvr
const PVRTuint32 PVRTEX_CUBEMAP = (1<<12); // is a cubemap/skybox
const PVRTuint32 PVRTEX_FALSEMIPCOL = (1<<13); // are there false coloured MIP levels
const PVRTuint32 PVRTEX_VOLUME = (1<<14); // is this a volume texture
const PVRTuint32 PVRTEX_ALPHA = (1<<15); // v2.1 is there transparency info in the texture
const PVRTuint32 PVRTEX_VERTICAL_FLIP = (1<<16); // v2.1 is the texture vertically flipped
const PVRTuint32 PVRTEX_PIXELTYPE = 0xff; // pixel type is always in the last 16bits of the flags
const PVRTuint32 PVRTEX_IDENTIFIER = 0x21525650; // the pvr identifier is the characters 'P','V','R'
const PVRTuint32 PVRTEX_V1_HEADER_SIZE = 44; // old header size was 44 for identification purposes
const PVRTuint32 PVRTC2_MIN_TEXWIDTH = 16;
const PVRTuint32 PVRTC2_MIN_TEXHEIGHT = 8;
const PVRTuint32 PVRTC4_MIN_TEXWIDTH = 8;
const PVRTuint32 PVRTC4_MIN_TEXHEIGHT = 8;
const PVRTuint32 ETC_MIN_TEXWIDTH = 4;
const PVRTuint32 ETC_MIN_TEXHEIGHT = 4;
const PVRTuint32 DXT_MIN_TEXWIDTH = 4;
const PVRTuint32 DXT_MIN_TEXHEIGHT = 4;
/****************************************************************************
** Functions
****************************************************************************/
/*!***************************************************************************
@Function PVRTTextureCreate
@Input w Size of the texture
@Input h Size of the texture
@Input wMin Minimum size of a texture level
@Input hMin Minimum size of a texture level
@Input nBPP Bits per pixel of the format
@Input bMIPMap Create memory for MIP-map levels also?
@Return Allocated texture memory (must be free()d)
@Description Creates a PVRTextureHeaderV3 structure, including room for
the specified texture, in memory.
*****************************************************************************/
PVRTextureHeaderV3 *PVRTTextureCreate(
unsigned int w,
unsigned int h,
const unsigned int wMin,
const unsigned int hMin,
const unsigned int nBPP,
const bool bMIPMap);
/*!***************************************************************************
@Function PVRTTextureTile
@Modified pOut The tiled texture in system memory
@Input pIn The source texture
@Input nRepeatCnt Number of times to repeat the source texture
@Description Allocates and fills, in system memory, a texture large enough
to repeat the source texture specified number of times.
*****************************************************************************/
void PVRTTextureTile(
PVRTextureHeaderV3 **pOut,
const PVRTextureHeaderV3 * const pIn,
const int nRepeatCnt);
/****************************************************************************
** Internal Functions
****************************************************************************/
//Preprocessor definitions to generate a pixelID for use when consts are needed. For example - switch statements. These should be evaluated by the compiler rather than at run time - assuming that arguments are all constant.
//Generate a 4 channel PixelID.
#define PVRTGENPIXELID4(C1Name, C2Name, C3Name, C4Name, C1Bits, C2Bits, C3Bits, C4Bits) ( ( (PVRTuint64)C1Name) + ( (PVRTuint64)C2Name<<8) + ( (PVRTuint64)C3Name<<16) + ( (PVRTuint64)C4Name<<24) + ( (PVRTuint64)C1Bits<<32) + ( (PVRTuint64)C2Bits<<40) + ( (PVRTuint64)C3Bits<<48) + ( (PVRTuint64)C4Bits<<56) )
//Generate a 1 channel PixelID.
#define PVRTGENPIXELID3(C1Name, C2Name, C3Name, C1Bits, C2Bits, C3Bits)( PVRTGENPIXELID4(C1Name, C2Name, C3Name, 0, C1Bits, C2Bits, C3Bits, 0) )
//Generate a 2 channel PixelID.
#define PVRTGENPIXELID2(C1Name, C2Name, C1Bits, C2Bits) ( PVRTGENPIXELID4(C1Name, C2Name, 0, 0, C1Bits, C2Bits, 0, 0) )
//Generate a 3 channel PixelID.
#define PVRTGENPIXELID1(C1Name, C1Bits) ( PVRTGENPIXELID4(C1Name, 0, 0, 0, C1Bits, 0, 0, 0))
//Forward declaration of CPVRTMap.
template <typename KeyType, typename DataType>
class CPVRTMap;
/*!***********************************************************************
@Function PVRTGetBitsPerPixel
@Input u64PixelFormat A PVR Pixel Format ID.
@Return const PVRTuint32 Number of bits per pixel.
@Description Returns the number of bits per pixel in a PVR Pixel Format
identifier.
*************************************************************************/
PVRTuint32 PVRTGetBitsPerPixel(PVRTuint64 u64PixelFormat);
/*!***********************************************************************
@Function PVRTGetFormatMinDims
@Input u64PixelFormat A PVR Pixel Format ID.
@Modified minX Returns the minimum width.
@Modified minY Returns the minimum height.
@Modified minZ Returns the minimum depth.
@Description Gets the minimum dimensions (x,y,z) for a given pixel format.
*************************************************************************/
void PVRTGetFormatMinDims(PVRTuint64 u64PixelFormat, PVRTuint32 &minX, PVRTuint32 &minY, PVRTuint32 &minZ);
/*!***********************************************************************
@Function PVRTConvertOldTextureHeaderToV3
@Input LegacyHeader Legacy header for conversion.
@Modified NewHeader New header to output into.
@Modified pMetaData MetaData Map to output into.
@Description Converts a legacy texture header (V1 or V2) to a current
generation header (V3)
*************************************************************************/
void PVRTConvertOldTextureHeaderToV3(const PVR_Texture_Header* LegacyHeader, PVRTextureHeaderV3& NewHeader, CPVRTMap<PVRTuint32, CPVRTMap<PVRTuint32,MetaDataBlock> >* pMetaData);
/*!***********************************************************************
@Function PVRTMapLegacyTextureEnumToNewFormat
@Input OldFormat Legacy Enumeration Value
@Modified newType New PixelType identifier.
@Modified newCSpace New ColourSpace
@Modified newChanType New Channel Type
@Modified isPreMult Whether format is pre-multiplied
@Description Maps a legacy enumeration value to the new PVR3 style format.
*************************************************************************/
void PVRTMapLegacyTextureEnumToNewFormat(PVRTPixelType OldFormat, PVRTuint64& newType, EPVRTColourSpace& newCSpace, EPVRTVariableType& newChanType, bool& isPreMult);
/*!***************************************************************************
@Function PVRTTextureLoadTiled
@Modified pDst Texture to place the tiled data
@Input nWidthDst Width of destination texture
@Input nHeightDst Height of destination texture
@Input pSrc Texture to tile
@Input nWidthSrc Width of source texture
@Input nHeightSrc Height of source texture
@Input nElementSize Bytes per pixel
@Input bTwiddled True if the data is twiddled
@Description Needed by PVRTTextureTile() in the various PVRTTextureAPIs
*****************************************************************************/
void PVRTTextureLoadTiled(
PVRTuint8 * const pDst,
const unsigned int nWidthDst,
const unsigned int nHeightDst,
const PVRTuint8 * const pSrc,
const unsigned int nWidthSrc,
const unsigned int nHeightSrc,
const unsigned int nElementSize,
const bool bTwiddled);
/*!***************************************************************************
@Function PVRTTextureTwiddle
@Output a Twiddled value
@Input u Coordinate axis 0
@Input v Coordinate axis 1
@Description Combine a 2D coordinate into a twiddled value
*****************************************************************************/
void PVRTTextureTwiddle(unsigned int &a, const unsigned int u, const unsigned int v);
/*!***************************************************************************
@Function PVRTTextureDeTwiddle
@Output u Coordinate axis 0
@Output v Coordinate axis 1
@Input a Twiddled value
@Description Extract 2D coordinates from a twiddled value.
*****************************************************************************/
void PVRTTextureDeTwiddle(unsigned int &u, unsigned int &v, const unsigned int a);
/*!***********************************************************************
@Function PVRTGetTextureDataSize
@Input sTextureHeader Specifies the texture header.
@Input iMipLevel Specifies a mip level to check, 'PVRTEX_ALLMIPLEVELS'
can be passed to get the size of all MIP levels.
@Input bAllSurfaces Size of all surfaces is calculated if true,
only a single surface if false.
@Input bAllFaces Size of all faces is calculated if true,
only a single face if false.
@Return PVRTuint32 Size in BYTES of the specified texture area.
@Description Gets the size in BYTES of the texture, given various input
parameters. User can retrieve the size of either all
surfaces or a single surface, all faces or a single face and
all MIP-Maps or a single specified MIP level.
*************************************************************************/
PVRTuint32 PVRTGetTextureDataSize(PVRTextureHeaderV3 sTextureHeader, PVRTint32 iMipLevel=PVRTEX_ALLMIPLEVELS, bool bAllSurfaces = true, bool bAllFaces = true);
#endif /* _PVRTTEXTURE_H_ */
/*****************************************************************************
End of file (PVRTTexture.h)
*****************************************************************************/

@ -0,0 +1,120 @@
/******************************************************************************
@File PVRTTypes.h
@Title PVRTTypes
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI compatible
@Description Global enums and typedefs for PVRTools
******************************************************************************/
//ACS: I split this out of PVRTGlobal.h
#ifndef _PVRTTYPES_H_
#define _PVRTTYPES_H_
/*!***************************************************************************
Macros
*****************************************************************************/
//#include <stdio.h>
// This macro is used to check at compile time that types are of a certain size
// If the size does not equal the expected size, this typedefs an array of size 0
// which causes a compile error
#define PVRTSIZEASSERT(T, size) typedef int (sizeof_##T)[sizeof(T) == (size)]
#define PVRTCOMPILEASSERT(T, expr) typedef int (assert_##T)[expr]
/****************************************************************************
** Integer types
****************************************************************************/
typedef char PVRTchar8;
typedef signed char PVRTint8;
typedef signed short PVRTint16;
typedef signed int PVRTint32;
typedef unsigned char PVRTuint8;
typedef unsigned short PVRTuint16;
typedef unsigned int PVRTuint32;
typedef float PVRTfloat32;
#if (defined(__int64) || defined(_WIN32))
typedef signed __int64 PVRTint64;
typedef unsigned __int64 PVRTuint64;
#elif defined(TInt64)
typedef TInt64 PVRTint64;
typedef TUInt64 PVRTuint64;
#else
typedef signed long long PVRTint64;
typedef unsigned long long PVRTuint64;
#endif
#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000
#define PVRTSIZEOFWCHAR 4
#else
#define PVRTSIZEOFWCHAR 2
#endif
PVRTSIZEASSERT(PVRTchar8, 1);
PVRTSIZEASSERT(PVRTint8, 1);
PVRTSIZEASSERT(PVRTuint8, 1);
PVRTSIZEASSERT(PVRTint16, 2);
PVRTSIZEASSERT(PVRTuint16, 2);
PVRTSIZEASSERT(PVRTint32, 4);
PVRTSIZEASSERT(PVRTuint32, 4);
PVRTSIZEASSERT(PVRTint64, 8);
PVRTSIZEASSERT(PVRTuint64, 8);
PVRTSIZEASSERT(PVRTfloat32, 4);
/*!**************************************************************************
@Enum ETextureFilter
@Brief Enum values for defining texture filtering
****************************************************************************/
enum ETextureFilter
{
eFilter_Nearest,
eFilter_Linear,
eFilter_None,
eFilter_Size,
eFilter_Default = eFilter_Nearest,
eFilter_MipDefault = eFilter_None
};
/*!**************************************************************************
@Enum ETextureWrap
@Brief Enum values for defining texture wrapping
****************************************************************************/
enum ETextureWrap
{
eWrap_Clamp,
eWrap_Repeat,
eWrap_Size,
eWrap_Default = eWrap_Repeat
};
/*****************************************************************************
ACS: Handle missing assert macros.
Maybe you needed to include PVRTGlobal.h after all?
*****************************************************************************/
#ifndef _ASSERT
# define _ASSERT(X)
#endif
#ifndef _ASSERTE
# define _ASSERTE(X)
#endif
#endif // _PVRTTYPES_H_
/*****************************************************************************
End of file
*****************************************************************************/

@ -0,0 +1,225 @@
/******************************************************************************
@File PVRTexture.h
@Title
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform
@Description
******************************************************************************/
#ifndef _PVRTEXTURE_H
#define _PVRTEXTURE_H
#include "PVRTextureDefines.h"
#include "PVRTextureHeader.h"
//ACS: removed unneccesary includes:
//#include "PVRTString.h"
namespace pvrtexture
{
class PVR_DLL CPVRTexture : public CPVRTextureHeader
{
public:
/*******************************************************************************
* Construction methods for a texture.
*******************************************************************************/
/*!***********************************************************************
@Function CPVRTexture
@Return CPVRTexture A new texture.
@Description Creates a new empty texture
*************************************************************************/
CPVRTexture();
/*!***********************************************************************
@Function CPVRTexture
@Input sHeader
@Input pData
@Return CPVRTexture A new texture.
@Description Creates a new texture based on a texture header,
pre-allocating the correct amount of memory. If data is
supplied, it will be copied into memory.
*************************************************************************/
CPVRTexture(const CPVRTextureHeader& sHeader, const void* pData=NULL);
/*!***********************************************************************
@Function CPVRTexture
@Input szFilePath
@Return CPVRTexture A new texture.
@Description Creates a new texture from a filepath.
*************************************************************************/
CPVRTexture(const char* szFilePath);
/*!***********************************************************************
@Function CPVRTexture
@Input pTexture
@Return CPVRTexture A new texture.
@Description Creates a new texture from a pointer that includes a header
structure, meta data and texture data as laid out in a file.
This functionality is primarily for user defined file loading.
Header may be any version of pvr.
*************************************************************************/
CPVRTexture( const void* pTexture );
/*!***********************************************************************
@Function CPVRTexture
@Input texture
@Return CPVRTexture A new texture
@Description Creates a new texture as a copy of another.
*************************************************************************/
CPVRTexture(const CPVRTexture& texture);
/*!***********************************************************************
@Function ~CPVRTexture
@Description Deconstructor for CPVRTextures.
*************************************************************************/
~CPVRTexture();
/*!***********************************************************************
@Function operator=
@Input rhs
@Return CPVRTexture& This texture.
@Description Will copy the contents and information of another texture into this one.
*************************************************************************/
CPVRTexture& operator=(const CPVRTexture& rhs);
/*******************************************************************************
* Texture accessor functions - others are inherited from CPVRTextureHeader.
*******************************************************************************/
/*!***********************************************************************
@Function getDataPtr
@Input uiMIPLevel
@Input uiArrayMember
@Input uiFaceNumber
@Return void* Pointer to a location in the texture.
@Description Returns a pointer into the texture's data.
It is possible to specify an offset to specific array members,
faces and MIP Map levels.
*************************************************************************/
void* getDataPtr(uint32 uiMIPLevel = 0, uint32 uiArrayMember = 0, uint32 uiFaceNumber = 0) const;
/*!***********************************************************************
@Function getHeader
@Return const CPVRTextureHeader& Returns the header only for this texture.
@Description Gets the header for this texture, allowing you to create a new
texture based on this one with some changes. Useful for passing
information about a texture without passing all of its data.
*************************************************************************/
const CPVRTextureHeader& getHeader() const;
/*******************************************************************************
* File io.
*******************************************************************************/
/*!***********************************************************************
@Function setPaddedMetaData
@Input uiPadding
@Description When writing the texture out to a PVR file, it is often
desirable to pad the meta data so that the start of the
texture data aligns to a given boundary.
This function pads to a boundary value equal to "uiPadding".
For example setting uiPadding=8 will align the start of the
texture data to an 8 byte boundary.
Note - this should be called immediately before saving as
the value is worked out based on the current meta data size.
*************************************************************************/
void addPaddingMetaData( uint32 uiPadding );
/*!***********************************************************************
@Function saveFile
@Input filepath
@Return bool Whether the method succeeds or not.
@Description Writes out to a file, given a filename and path.
File type will be determined by the extension present in the string.
If no extension is present, PVR format will be selected.
Unsupported formats will result in failure.
*************************************************************************/
bool saveFile(const CPVRTString& filepath) const;
/*!***********************************************************************
@Function saveFileLegacyPVR
@Input filepath
@Input eApi
@Return bool Whether the method succeeds or not.
@Description Writes out to a file, stripping any extensions specified
and appending .pvr. This function is for legacy support only
and saves out to PVR Version 2 file. The target api must be
specified in order to save to this format.
*************************************************************************/
bool saveFileLegacyPVR(const CPVRTString& filepath, ELegacyApi eApi) const;
private:
size_t m_stDataSize; // Size of the texture data.
uint8* m_pTextureData; // Pointer to texture data.
/*******************************************************************************
* Private IO functions
*******************************************************************************/
/*!***********************************************************************
@Function loadPVRFile
@Input pTextureFile
@Description Loads a PVR file.
*************************************************************************/
bool privateLoadPVRFile(FILE* pTextureFile);
/*!***********************************************************************
@Function privateSavePVRFile
@Input pTextureFile
@Description Saves a PVR File.
*************************************************************************/
bool privateSavePVRFile(FILE* pTextureFile) const;
/*!***********************************************************************
@Function loadKTXFile
@Input pTextureFile
@Description Loads a KTX file.
*************************************************************************/
bool privateLoadKTXFile(FILE* pTextureFile);
/*!***********************************************************************
@Function privateSaveKTXFile
@Input pTextureFile
@Description Saves a KTX File.
*************************************************************************/
bool privateSaveKTXFile(FILE* pTextureFile) const;
/*!***********************************************************************
@Function loadDDSFile
@Input pTextureFile
@Description Loads a DDS file.
*************************************************************************/
bool privateLoadDDSFile(FILE* pTextureFile);
bool privateLoadDDS10File(FILE* pTextureFile);
/*!***********************************************************************
@Function privateSaveDDSFile
@Input pTextureFile
@Description Saves a DDS File.
*************************************************************************/
bool privateSaveDDSFile(FILE* pTextureFile) const;
//Legacy IO
/*!***********************************************************************
@Function privateSavePVRFile
@Input pTextureFile
@Input filename
@Description Saves a .h File.
*************************************************************************/
bool privateSaveCHeaderFile(FILE* pTextureFile, CPVRTString filename) const;
/*!***********************************************************************
@Function privateSaveLegacyPVRFile
@Input pTextureFile
@Input eApi
@Description Saves a legacy PVR File - Uses version 2 file format.
*************************************************************************/
bool privateSaveLegacyPVRFile(FILE* pTextureFile, ELegacyApi eApi) const;
};
};
#endif //_PVRTEXTURE_H

@ -0,0 +1,109 @@
/******************************************************************************
@File PVRTextureDefines.h
@Title
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform
@Description
******************************************************************************/
#ifndef _PVRTEXTURE_DEFINES_H
#define _PVRTEXTURE_DEFINES_H
//To use the PVRTexLib .dll on Windows, you need to define _WINDLL_IMPORT
#ifndef PVR_DLL
#if defined(_WINDLL_EXPORT)
#define PVR_DLL __declspec(dllexport)
//Forward declaration of PVRTexture Header and CPVRTMap. This exports their interfaces for DLLs.
struct PVR_DLL PVRTextureHeaderV3;
template <typename KeyType, typename DataType>
class PVR_DLL CPVRTMap;
template<typename T>
class PVR_DLL CPVRTArray;
#elif defined(_WINDLL_IMPORT)
#define PVR_DLL __declspec(dllimport)
//Forward declaration of PVRTexture Header and CPVRTMap. This imports their interfaces for DLLs.
struct PVR_DLL PVRTextureHeaderV3;
template <typename KeyType, typename DataType>
class PVR_DLL CPVRTMap;
template<typename T>
class PVR_DLL CPVRTArray;
#else
#define PVR_DLL
#endif
#endif
#include "PVRTTexture.h"
namespace pvrtexture
{
/*****************************************************************************
* Type defines for standard variable sizes.
*****************************************************************************/
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef signed long long int64;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long uint64;
/*****************************************************************************
* Texture related constants and enumerations.
*****************************************************************************/
enum ECompressorQuality
{
ePVRTCFast=0,
ePVRTCNormal,
ePVRTCHigh,
ePVRTCBest,
eNumPVRTCModes,
eETCFast=0,
eETCFastPerceptual,
eETCSlow,
eETCSlowPerceptual,
eNumETCModes
};
enum EResizeMode
{
eResizeNearest,
eResizeLinear,
eResizeCubic,
eNumResizeModes
};
// Legacy - API enums.
enum ELegacyApi
{
eOGLES=1,
eOGLES2,
eD3DM,
eOGL,
eDX9,
eDX10,
eOVG,
eMGL,
};
/*****************************************************************************
* Useful macros.
*****************************************************************************/
#define TEXOFFSET2D(x,y,width) ( ((x)+(y)*(width)) )
#define TEXOFFSET3D(x,y,z,width,height) ( ((x)+(y)*(width)+(z)*(width)*(height)) )
/*****************************************************************************
* Useful typedef for Meta Data Maps
*****************************************************************************/
typedef CPVRTMap<uint32, CPVRTMap<uint32,MetaDataBlock> > MetaDataMap;
};
#endif //_PVRTEXTURE_DEFINES_H

@ -0,0 +1,90 @@
/******************************************************************************
@File PVRTextureFormat.h
@Title
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform
@Description
******************************************************************************/
#ifndef _PVRT_PIXEL_FORMAT_H
#define _PVRT_PIXEL_FORMAT_H
#include "PVRTextureDefines.h"
//ACS: removed unneccesary includes:
//#include "PVRTString.h"
namespace pvrtexture
{
//Channel Names
enum EChannelName
{
eNoChannel,
eRed,
eGreen,
eBlue,
eAlpha,
eLuminance,
eIntensity,
eUnspecified,
eNumChannels
};
//PixelType union
union PVR_DLL PixelType
{
/*!***********************************************************************
@Function PixelType
@Return A new PixelType
@Description Creates an empty pixeltype.
*************************************************************************/
PixelType();
/*!***********************************************************************
@Function PixelType
@Input Type
@Return A new PixelType
@Description Initialises a new pixel type from a 64 bit integer value.
*************************************************************************/
PixelType(uint64 Type);
/*!***********************************************************************
@Function PixelType
@Input C1Name
@Input C2Name
@Input C3Name
@Input C4Name
@Input C1Bits
@Input C2Bits
@Input C3Bits
@Input C4Bits
@Return A new PixelType
@Description Takes up to 4 characters (CnName) and 4 values (CnBits)
to create a new PixelType. Any unused channels should be set to 0.
For example: PixelType('r','g','b',0,8,8,8,0);
*************************************************************************/
PixelType(uint8 C1Name, uint8 C2Name, uint8 C3Name, uint8 C4Name, uint8 C1Bits, uint8 C2Bits, uint8 C3Bits, uint8 C4Bits);
struct PVR_DLL LowHigh
{
uint32 Low;
uint32 High;
} Part;
uint64 PixelTypeID;
uint8 PixelTypeChar[8];
};
static const PixelType PVRStandard8PixelType = PixelType('r','g','b','a',8,8,8,8);
static const PixelType PVRStandard16PixelType = PixelType('r','g','b','a',16,16,16,16);
static const PixelType PVRStandard32PixelType = PixelType('r','g','b','a',32,32,32,32);
}
#endif

@ -0,0 +1,603 @@
/******************************************************************************
@File PVRTextureHeader.h
@Title
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform
@Description
******************************************************************************/
#ifndef _PVRTEXTURE_HEADER_H
#define _PVRTEXTURE_HEADER_H
#include "PVRTextureDefines.h"
#include "PVRTextureFormat.h"
#include "PVRTMap.h"
#include "PVRTString.h"
namespace pvrtexture
{
//Wrapper class for PVRTextureHeaderV3, adds 'smart' accessor functions.
class PVR_DLL CPVRTextureHeader
{
protected:
PVRTextureHeaderV3 m_sHeader; //Texture header as laid out in a file.
mutable CPVRTMap<uint32, CPVRTMap<uint32,MetaDataBlock> > m_MetaData; //Map of all the meta data stored for a texture.
public:
/*******************************************************************************
* Construction methods for a texture header.
*******************************************************************************/
/*!***********************************************************************
@Function CPVRTextureHeader
@Return CPVRTextureHeader A new texture header.
@Description Default constructor for a CPVRTextureHeader. Returns an empty header.
*************************************************************************/
CPVRTextureHeader();
/*!***********************************************************************
@Function CPVRTextureHeader
@Input fileHeader
@Input metaDataCount
@Input metaData
@Return CPVRTextureHeader A new texture header.
@Description Creates a new texture header from a PVRTextureHeaderV3,
and appends Meta data if any is supplied.
*************************************************************************/
CPVRTextureHeader( PVRTextureHeaderV3 fileHeader,
uint32 metaDataCount=0,
MetaDataBlock* metaData=NULL);
/*!***********************************************************************
@Function CPVRTextureHeader
@Input u64PixelFormat
@Input u32Height
@Input u32Width
@Input u32Depth
@Input u32NumMipMaps
@Input u32NumArrayMembers
@Input u32NumFaces
@Input eColourSpace
@Input eChannelType
@Input bPreMultiplied
@Return CPVRTextureHeader A new texture header.
@Description Creates a new texture header based on individual header
variables.
*************************************************************************/
CPVRTextureHeader( uint64 u64PixelFormat,
uint32 u32Height=1,
uint32 u32Width=1,
uint32 u32Depth=1,
uint32 u32NumMipMaps=1,
uint32 u32NumArrayMembers=1,
uint32 u32NumFaces=1,
EPVRTColourSpace eColourSpace=ePVRTCSpacelRGB,
EPVRTVariableType eChannelType=ePVRTVarTypeUnsignedByteNorm,
bool bPreMultiplied=false);
/*!***********************************************************************
@Function operator=
@Input rhs
@Return CPVRTextureHeader& This header.
@Description Will copy the contents and information of another header into this one.
*************************************************************************/
CPVRTextureHeader& operator=(const CPVRTextureHeader& rhs);
/*******************************************************************************
* Accessor Methods for a texture's properties - getters.
*******************************************************************************/
/*!***********************************************************************
@Function getFileHeader
@Return PVRTextureHeaderV3 The file header.
@Description Gets the file header structure.
*************************************************************************/
const PVRTextureHeaderV3 getFileHeader() const;
/*!***********************************************************************
@Function getPixelType
@Return PixelType 64-bit pixel type ID.
@Description Gets the 64-bit pixel type ID of the texture.
*************************************************************************/
const PixelType getPixelType() const;
/*!***********************************************************************
@Function getBitsPerPixel
@Return uint32 Number of bits per pixel
@Description Gets the bits per pixel of the texture format.
*************************************************************************/
const uint32 getBitsPerPixel() const;
/*!***********************************************************************
@Function getColourSpace
@Return EPVRTColourSpace enum representing colour space.
@Description Returns the colour space of the texture.
*************************************************************************/
const EPVRTColourSpace getColourSpace() const;
/*!***********************************************************************
@Function getChannelType
@Return EPVRTVariableType enum representing the type of the texture.
@Description Returns the variable type that the texture's data is stored in.
*************************************************************************/
const EPVRTVariableType getChannelType() const;
/*!***********************************************************************
@Function getWidth
@Input uiMipLevel MIP level that user is interested in.
@Return uint32 Width of the specified MIP-Map level.
@Description Gets the width of the user specified MIP-Map
level for the texture
*************************************************************************/
const uint32 getWidth(uint32 uiMipLevel=PVRTEX_TOPMIPLEVEL) const;
/*!***********************************************************************
@Function getHeight
@Input uiMipLevel MIP level that user is interested in.
@Return uint32 Height of the specified MIP-Map level.
@Description Gets the height of the user specified MIP-Map
level for the texture
*************************************************************************/
const uint32 getHeight(uint32 uiMipLevel=PVRTEX_TOPMIPLEVEL) const;
/*!***********************************************************************
@Function getDepth
@Input uiMipLevel MIP level that user is interested in.
@Return Depth of the specified MIP-Map level.
@Description Gets the depth of the user specified MIP-Map
level for the texture
*************************************************************************/
const uint32 getDepth(uint32 uiMipLevel=PVRTEX_TOPMIPLEVEL) const;
/*!***********************************************************************
@Function getTextureSize
@Input iMipLevel Specifies a MIP level to check,
'PVRTEX_ALLMIPLEVELS' can be passed to get
the size of all MIP levels.
@Input bAllSurfaces Size of all surfaces is calculated if true,
only a single surface if false.
@Input bAllFaces Size of all faces is calculated if true,
only a single face if false.
@Return uint32 Size in PIXELS of the specified texture area.
@Description Gets the size in PIXELS of the texture, given various input
parameters. User can retrieve the total size of either all
surfaces or a single surface, all faces or a single face and
all MIP-Maps or a single specified MIP level. All of these
*************************************************************************/
const uint32 getTextureSize(int32 iMipLevel=PVRTEX_ALLMIPLEVELS, bool bAllSurfaces = true, bool bAllFaces = true) const;
/*!***********************************************************************
@Function getDataSize
@Input iMipLevel Specifies a mip level to check,
'PVRTEX_ALLMIPLEVELS' can be passed to get
the size of all MIP levels.
@Input bAllSurfaces Size of all surfaces is calculated if true,
only a single surface if false.
@Input bAllFaces Size of all faces is calculated if true,
only a single face if false.
@Return uint32 Size in BYTES of the specified texture area.
@Description Gets the size in BYTES of the texture, given various input
parameters. User can retrieve the size of either all
surfaces or a single surface, all faces or a single face
and all MIP-Maps or a single specified MIP level.
*************************************************************************/
const uint32 getDataSize(int32 iMipLevel=PVRTEX_ALLMIPLEVELS, bool bAllSurfaces = true, bool bAllFaces = true) const;
/*!***********************************************************************
@Function getNumArrayMembers
@Return uint32 Number of array members in this texture.
@Description Gets the number of array members stored in this texture.
*************************************************************************/
const uint32 getNumArrayMembers() const;
/*!***********************************************************************
@Function getNumMIPLevels
@Return uint32 Number of MIP-Map levels in this texture.
@Description Gets the number of MIP-Map levels stored in this texture.
*************************************************************************/
const uint32 getNumMIPLevels() const;
/*!***********************************************************************
@Function getNumFaces
@Return uint32 Number of faces in this texture.
@Description Gets the number of faces stored in this texture.
*************************************************************************/
const uint32 getNumFaces() const;
/*!***********************************************************************
@Function getOrientation
@Input axis EPVRTAxis type specifying the axis to examine.
@Return EPVRTOrientation Enum orientation of the axis.
@Description Gets the data orientation for this texture.
*************************************************************************/
const EPVRTOrientation getOrientation(EPVRTAxis axis) const;
/*!***********************************************************************
@Function isFileCompressed
@Return bool True if it is file compressed.
@Description Returns whether or not the texture is compressed using
PVRTexLib's FILE compression - this is independent of
any texture compression.
*************************************************************************/
const bool isFileCompressed() const;
/*!***********************************************************************
@Function isPreMultiplied
@Return bool True if texture is premultiplied.
@Description Returns whether or not the texture's colour has been
pre-multiplied by the alpha values.
*************************************************************************/
const bool isPreMultiplied() const;
/*!***********************************************************************
@Function getMetaDataSize
@Return const uint32 Size, in bytes, of the meta data stored in the header.
@Description Returns the total size of the meta data stored in the header.
This includes the size of all information stored in all MetaDataBlocks.
*************************************************************************/
const uint32 getMetaDataSize() const;
/*!***********************************************************************
@Function getOGLFormat
@Modified internalformat
@Modified format
@Modified type
@Description Gets the OpenGL equivalent values of internal format, format
and type for this texture. This will return any supported
OpenGL texture values, it is up to the user to decide if
these are valid for their current platform.
*************************************************************************/
const void getOGLFormat(uint32& internalformat, uint32& format, uint32& type) const;
/*!***********************************************************************
@Function getOGLESFormat
@Modified internalformat
@Modified format
@Modified type
@Description Gets the OpenGLES equivalent values of internal format,
format and type for this texture. This will return any
supported OpenGLES texture values, it is up to the user
to decide if these are valid for their current platform.
*************************************************************************/
const void getOGLESFormat(uint32& internalformat, uint32& format, uint32& type) const;
/*!***********************************************************************
@Function getD3DFormat
@Return const uint32
@Description Gets the D3DFormat (up to DirectX 9 and Direct 3D Mobile)
equivalent values for this texture. This will return any
supported D3D texture formats, it is up to the user to
decide if this is valid for their current platform.
*************************************************************************/
const uint32 getD3DFormat() const;
/*!***********************************************************************
@Function getDXGIFormat
@Return const uint32
@Description Gets the DXGIFormat (DirectX 10 onward) equivalent values
for this texture. This will return any supported DX texture
formats, it is up to the user to decide if this is valid
for their current platform.
*************************************************************************/
const uint32 getDXGIFormat() const;
/*!***********************************************************************
* Accessor Methods for a texture's properties - setters.
*************************************************************************/
/*!***********************************************************************
@Function setPixelFormat
@Input uPixelFormat The format of the pixel.
@Description Sets the pixel format for this texture.
*************************************************************************/
void setPixelFormat(PixelType uPixelFormat);
/*!***********************************************************************
@Function setColourSpace
@Input eColourSpace A colour space enum.
@Description Sets the colour space for this texture. Default is lRGB.
*************************************************************************/
void setColourSpace(EPVRTColourSpace eColourSpace);
/*!***********************************************************************
@Function setChannelType
@Input eVarType A variable type enum.
@Description Sets the variable type for the channels in this texture.
*************************************************************************/
void setChannelType(EPVRTVariableType eVarType);
/*!***********************************************************************
@Function setOGLFormat
@Input internalformat
@Input format
@Input type
@Return bool Whether the format is valid or not.
@Description Sets the format of the texture to PVRTexLib's internal
representation of the OGL format.
*************************************************************************/
bool setOGLFormat(const uint32& internalformat, const uint32& format, const uint32& type);
/*!***********************************************************************
@Function setOGLESFormat
@Input internalformat
@Input format
@Input type
@Return bool Whether the format is valid or not.
@Description Sets the format of the texture to PVRTexLib's internal
representation of the OGLES format.
*************************************************************************/
bool setOGLESFormat(const uint32& internalformat, const uint32& format, const uint32& type);
/*!***********************************************************************
@Function setD3DFormat
@Return bool Whether the format is valid or not.
@Description Sets the format of the texture to PVRTexLib's internal
representation of the D3D format.
*************************************************************************/
bool setD3DFormat(const uint32& DWORD_D3D_FORMAT);
/*!***********************************************************************
@Function setDXGIFormat
@Return bool Whether the format is valid or not.
@Description Sets the format of the texture to PVRTexLib's internal
representation of the DXGI format.
*************************************************************************/
bool setDXGIFormat(const uint32& DWORD_DXGI_FORMAT);
/*!***********************************************************************
@Function setWidth
@Input newWidth The new width.
@Description Sets the width.
*************************************************************************/
void setWidth(uint32 newWidth);
/*!***********************************************************************
@Function setHeight
@Input newHeight The new height.
@Description Sets the height.
*************************************************************************/
void setHeight(uint32 newHeight);
/*!***********************************************************************
@Function setDepth
@Input newDepth The new depth.
@Description Sets the depth.
*************************************************************************/
void setDepth(uint32 newDepth);
/*!***********************************************************************
@Function setNumArrayMembers
@Input newNumMembers The new number of members in this array.
@Description Sets the depth.
*************************************************************************/
void setNumArrayMembers(uint32 newNumMembers);
/*!***********************************************************************
@Function setNumMIPLevels
@Input newNumMIPLevels New number of MIP-Map levels.
@Description Sets the number of MIP-Map levels in this texture.
*************************************************************************/
void setNumMIPLevels(uint32 newNumMIPLevels);
/*!***********************************************************************
@Function setNumFaces
@Input newNumFaces New number of faces for this texture.
@Description Sets the number of faces stored in this texture.
*************************************************************************/
void setNumFaces(uint32 newNumFaces);
/*!***********************************************************************
@Function setOrientation
@Input eAxisOrientation Enum specifying axis and orientation.
@Description Sets the data orientation for a given axis in this texture.
*************************************************************************/
void setOrientation(EPVRTOrientation eAxisOrientation);
/*!***********************************************************************
@Function setIsFileCompressed
@Input isFileCompressed Sets file compression to true/false.
@Description Sets whether or not the texture is compressed using
PVRTexLib's FILE compression - this is independent of
any texture compression. Currently unsupported.
*************************************************************************/
void setIsFileCompressed(bool isFileCompressed);
/*!***********************************************************************
@Function isPreMultiplied
@Return isPreMultiplied Sets if texture is premultiplied.
@Description Sets whether or not the texture's colour has been
pre-multiplied by the alpha values.
*************************************************************************/
void setIsPreMultiplied(bool isPreMultiplied);
/*!***********************************************************************
Meta Data functions - Getters.
*************************************************************************/
/*!***********************************************************************
@Function isBumpMap
@Return bool True if it is a bump map.
@Description Returns whether the texture is a bump map or not.
*************************************************************************/
const bool isBumpMap() const;
/*!***********************************************************************
@Function getBumpMapScale
@Return float Returns the bump map scale.
@Description Gets the bump map scaling value for this texture. If the
texture is not a bump map, 0.0f is returned. If the
texture is a bump map but no meta data is stored to
specify its scale, then 1.0f is returned.
*************************************************************************/
const float getBumpMapScale() const;
/*!***********************************************************************
@Function getBumpMapOrder
@Return CPVRTString Returns bump map order relative to rgba.
@Description Gets the bump map channel order relative to rgba. For
example, an RGB texture with bumps mapped to XYZ returns
'xyz'. A BGR texture with bumps in the order ZYX will also
return 'xyz' as the mapping is the same: R=X, G=Y, B=Z.
If the letter 'h' is present in the string, it means that
the height map has been stored here.
Other characters are possible if the bump map was created
manually, but PVRTexLib will ignore these characters. They
are returned simply for completeness.
*************************************************************************/
const CPVRTString getBumpMapOrder() const;
/*!***********************************************************************
@Function getNumTextureAtlasMembers
@Return int Returns number of sub textures defined by meta data.
@Description Works out the number of possible texture atlas members in
the texture based on the w/h/d and the data size.
TODO: Is this the right way to do things? Should I return number of floats? Or just data size? Hmm. Also need to make it TWO floats per dimension, and also possibly a rotated value. Not sure.
*************************************************************************/
const int getNumTextureAtlasMembers() const;
/*!***********************************************************************
@Function getTextureAtlasData
@Return float* Returns a pointer directly to the texture atlas data.
@Description Returns a pointer to the texture atlas data.
TODO: Maybe I should return a copy rather than the original.
*************************************************************************/
const float* getTextureAtlasData() const;
/*!***********************************************************************
@Function getCubeMapOrder
@Return CPVRTString Returns cube map order.
@Description Gets the cube map face order. Returned string will be in
the form "ZzXxYy" with capitals representing positive and
small letters representing negative. I.e. Z=Z-Positive,
z=Z-Negative.
*************************************************************************/
const CPVRTString getCubeMapOrder() const;
/*!***********************************************************************
@Function getBorder
@Input uiBorderWidth
@Input uiBorderHeight
@Input uiBorderDepth
@Description Obtains the border size in each dimension for this texture.
*************************************************************************/
void getBorder(uint32& uiBorderWidth, uint32& uiBorderHeight, uint32& uiBorderDepth) const;
/*!***********************************************************************
@Function getMetaData
@Input DevFOURCC
@Input u32Key
@Return pvrtexture::MetaDataBlock A copy of the meta data from the texture.
@Description Returns a block of meta data from the texture. If the meta data doesn't exist, a block with data size 0 will be returned.
*************************************************************************/
MetaDataBlock getMetaData(uint32 DevFOURCC, uint32 u32Key) const;
/*!***********************************************************************
@Function hasMetaData
@Input DevFOURCC
@Input u32Key
@Return bool Whether or not the meta data bock specified exists
@Description Returns whether or not the specified meta data exists as
part of this texture header.
*************************************************************************/
bool hasMetaData(uint32 DevFOURCC, uint32 u32Key) const;
/*!***********************************************************************
@Function getMetaDataMap
@Return MetaDataMap* A direct pointer to the MetaData map.
@Description A pointer directly to the Meta Data Map, to allow users to read out data.
*************************************************************************/
const MetaDataMap* const getMetaDataMap() const;
/*!***********************************************************************
Meta Data functions - Setters.
*************************************************************************/
/*!***********************************************************************
@Function setBumpMap
@Input bumpScale Floating point "height" value to scale the bump map.
@Input bumpOrder Up to 4 character string, with values x,y,z,h in
some combination. Not all values need to be present.
Denotes channel order; x,y,z refer to the
corresponding axes, h indicates presence of the
original height map. It is possible to have only some
of these values rather than all. For example if 'h'
is present alone it will be considered a height map.
The values should be presented in RGBA order, regardless
of the texture format, so a zyxh order in a bgra texture
should still be passed as 'xyzh'. Capitals are allowed.
Any character stored here that is not one of x,y,z,h
or a NULL character will be ignored when PVRTexLib
reads the data, but will be preserved. This is useful
if you wish to define a custom data channel for instance.
In these instances PVRTexLib will assume it is simply
colour data.
@Description Sets a texture's bump map data.
*************************************************************************/
void setBumpMap(float bumpScale, CPVRTString bumpOrder="xyz");
/*!***********************************************************************
@Function setTextureAtlas
@Input pAtlasData Pointer to an array of atlas data.
@Input dataSize Number of floats that the data pointer contains.
@Description Sets the texture atlas coordinate meta data for later display.
It is up to the user to make sure that this texture atlas
data actually makes sense in the context of the header. It is
suggested that the "generateTextureAtlas" method in the tools
is used to create a texture atlas, manually setting one up is
possible but should be done with care.
*************************************************************************/
void setTextureAtlas(float* pAtlasData, uint32 dataSize);
/*!***********************************************************************
@Function setCubeMapOrder
@Input cubeMapOrder Up to 6 character string, with values
x,X,y,Y,z,Z in some combination. Not all
values need to be present. Denotes face
order; Capitals refer to positive axis
positions and small letters refer to
negative axis positions. E.g. x=X-Negative,
X=X-Positive. It is possible to have only
some of these values rather than all, as
long as they are NULL terminated.
NB: Values past the 6th character are not read.
@Description Sets a texture's bump map data.
*************************************************************************/
void setCubeMapOrder(CPVRTString cubeMapOrder="XxYyZz");
/*!***********************************************************************
@Function setBorder
@Input uiBorderWidth
@Input uiBorderHeight
@Input uiBorderDepth
@Return void
@Description Sets a texture's border size data. This value is subtracted
from the current texture height/width/depth to get the valid
texture data.
*************************************************************************/
void setBorder(uint32 uiBorderWidth, uint32 uiBorderHeight, uint32 uiBorderDepth);
/*!***********************************************************************
@Function addMetaData
@Input MetaBlock Meta data block to be added.
@Description Adds an arbitrary piece of meta data.
*************************************************************************/
void addMetaData(const MetaDataBlock& MetaBlock);
/*!***********************************************************************
@Function removeMetaData
@Input DevFourCC
@Input u32Key
@Return void
@Description Removes a specified piece of meta data, if it exists.
*************************************************************************/
void removeMetaData(const uint32& DevFourCC, const uint32& u32Key);
};
};
#endif

@ -0,0 +1,171 @@
/******************************************************************************
@File PVRTextureUtilities.h
@Title
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform
@Description
******************************************************************************/
#ifndef _PVRTEXTURE_UTILITIES_H
#define _PVRTEXTURE_UTILITIES_H
#include "PVRTextureFormat.h"
#include "PVRTexture.h"
namespace pvrtexture
{
/*!***********************************************************************
@Function Resize
@Input sTexture
@Input u32NewWidth
@Input u32NewHeight
@Input u32NewDepth
@Input eResizeMode
@Return bool Whether the method succeeds or not.
@Description Resizes the texture to new specified dimensions. Filtering
mode is specified with "eResizeMode".
*************************************************************************/
bool PVR_DLL Resize(CPVRTexture& sTexture, const uint32& u32NewWidth, const uint32& u32NewHeight, const uint32& u32NewDepth, const EResizeMode eResizeMode);
/*!***********************************************************************
@Function Rotate90
@Input sTexture
@Input eRotationAxis
@Input bForward
@Return bool Whether the method succeeds or not.
@Description Rotates a texture by 90 degrees around the given axis. bForward controls direction of rotation.
*************************************************************************/
bool PVR_DLL Rotate90(CPVRTexture& sTexture, const EPVRTAxis eRotationAxis, const bool bForward);
/*!***********************************************************************
@Function Flip
@Input sTexture
@Input eFlipDirection
@Return bool Whether the method succeeds or not.
@Description Flips a texture in a given direction.
*************************************************************************/
bool PVR_DLL Flip(CPVRTexture& sTexture, const EPVRTAxis eFlipDirection);
/*!***********************************************************************
@Function Border
@Input sTexture
@Input uiBorderX
@Input uiBorderY
@Input uiBorderZ
@Return bool Whether the method succeeds or not.
@Description Adds a user specified border to the texture.
*************************************************************************/
bool PVR_DLL Border(CPVRTexture& sTexture, uint32 uiBorderX, uint32 uiBorderY, uint32 uiBorderZ);
/*!***********************************************************************
@Function PreMultiplyAlpha
@Input sTexture
@Return bool Whether the method succeeds or not.
@Description Pre-multiplies a texture's colours by its alpha values.
*************************************************************************/
bool PVR_DLL PreMultiplyAlpha(CPVRTexture& sTexture);
/*!***********************************************************************
@Function Bleed
@Input sTexture
@Return bool Whether the method succeeds or not.
@Description Allows a texture's colours to run into any fully transparent areas.
*************************************************************************/
bool PVR_DLL Bleed(CPVRTexture& sTexture);
/*!***********************************************************************
@Function SetChannels
@Input sTexture
@Input uiNumChannelSets
@Input eChannels
@Input pValues
@Return bool Whether the method succeeds or not.
@Description Sets the specified number of channels to values specified in pValues.
*************************************************************************/
bool PVR_DLL SetChannels(CPVRTexture& sTexture, uint32 uiNumChannelSets, EChannelName *eChannels, uint32 *pValues);
bool PVR_DLL SetChannelsFloat(CPVRTexture& sTexture, uint32 uiNumChannelSets, EChannelName *eChannels, float *pValues);
/*!***********************************************************************
@Function CopyChannels
@Input sTexture
@Input sTextureSource
@Input uiNumChannelCopies
@Input eChannels
@Input eChannelsSource
@Return bool Whether the method succeeds or not.
@Description Copies the specified channels from sTextureSource into sTexture.
sTextureSource is not modified so it is possible to use the
same texture as both input and output. When using the same
texture as source and destination, channels are preserved
between swaps (e.g. copying Red to Green and then Green to Red
will result in the two channels trading places correctly).
Channels in eChannels are set to the value of the channels
in eChannelSource.
*************************************************************************/
bool PVR_DLL CopyChannels(CPVRTexture& sTexture, const CPVRTexture& sTextureSource, uint32 uiNumChannelCopies, EChannelName *eChannels, EChannelName *eChannelsSource);
/*!***********************************************************************
@Function GenerateNormalMap
@Input sTexture
@Input fScale
@Input sChannelOrder
@Return bool Whether the method succeeds or not.
@Description Generates a Normal Map from a given height map.
Assumes the red channel has the height values.
By default outputs to red/green/blue = x/y/z,
this can be overridden by specifying a channel
order in sChannelOrder. The channels specified
will output to red/green/blue/alpha in that order.
So "xyzh" maps x to red, y to green, z to blue
and h to alpha. 'h' is used to specify that the
original height map data should be preserved in
the given channel.
*************************************************************************/
bool PVR_DLL GenerateNormalMap(CPVRTexture& sTexture, const float fScale, CPVRTString sChannelOrder);
/*!***********************************************************************
@Function GenerateMIPMaps
@Input sTexture
@Input eFilterMode
@Input uiMIPMapsToDo
@Return bool Whether the method succeeds or not.
@Description Generates MIPMaps for a source texture. Default is to
create a complete MIPMap chain, however this can be
overridden with uiMIPMapsToDo.
*************************************************************************/
bool PVR_DLL GenerateMIPMaps(CPVRTexture& sTexture, const EResizeMode eFilterMode, const uint32 uiMIPMapsToDo=PVRTEX_ALLMIPLEVELS);
/*!***********************************************************************
@Function ColourMIPMaps
@Input sTexture
@Return bool Whether the method succeeds or not.
@Description Colours a texture's MIPMap levels with artificial colours
for debugging. MIP levels are coloured in the order:
Red, Green, Blue, Cyan, Magenta and Yellow
in a repeating pattern.
*************************************************************************/
bool PVR_DLL ColourMIPMaps(CPVRTexture& sTexture);
/*!***********************************************************************
@Function Transcode
@Input sTexture
@Input ptFormat
@Input eChannelType
@Input eColourspace
@Input eQuality
@Input bDoDither
@Return bool Whether the method succeeds or not.
@Description Transcodes a texture from its original format into a newly specified format.
Will either quantise or dither to lower precisions based on bDoDither.
uiQuality specifies the quality for PVRTC and ETC compression.
*************************************************************************/
bool PVR_DLL Transcode(CPVRTexture& sTexture, const PixelType ptFormat, const EPVRTVariableType eChannelType, const EPVRTColourSpace eColourspace, const ECompressorQuality eQuality=ePVRTCNormal, const bool bDoDither=false);
};
#endif //_PVRTEXTURE_UTILTIES_H

@ -0,0 +1,23 @@
/******************************************************************************
@File PVRTextureVersion.h
@Title
@Version
@Copyright Copyright (c) Imagination Technologies Limited. All Rights Reserved. Strictly Confidential.
@Platform ANSI
@Description Texture processing routines.
******************************************************************************/
#ifndef PVRTEXLIBVERSION_H
#define PVRTEXLIBVERSION_H
#define PVRTLMAJORVERSION 4
#define PVRTLMINORVERSION 2
#define PVRTLSTRINGVERSION "4.2"
#define PVRTLVERSIONDESCRIPTOR "" //"BETA" //"ALPHA" //"ENGINEERING DROP"
#endif

Binary file not shown.

@ -0,0 +1,7 @@
SET(RGETC_SRCS
rg_etc1.cpp
rg_etc1.h)
ADD_LIBRARY(rg_etc1 STATIC ${RGETC_SRCS})

File diff suppressed because it is too large Load Diff

@ -0,0 +1,76 @@
// File: rg_etc1.h - Fast, high quality ETC1 block packer/unpacker - Rich Geldreich <richgel99@gmail.com>
// Please see ZLIB license at the end of this file.
#pragma once
namespace rg_etc1
{
// Unpacks an 8-byte ETC1 compressed block to a block of 4x4 32bpp RGBA pixels.
// Returns false if the block is invalid. Invalid blocks will still be unpacked with clamping.
// This function is thread safe, and does not dynamically allocate any memory.
// If preserve_alpha is true, the alpha channel of the destination pixels will not be overwritten. Otherwise, alpha will be set to 255.
bool unpack_etc1_block(const void *pETC1_block, unsigned int* pDst_pixels_rgba, bool preserve_alpha = false);
// Quality setting = the higher the quality, the slower.
// To pack large textures, it is highly recommended to call pack_etc1_block() in parallel, on different blocks, from multiple threads (particularly when using cHighQuality).
enum etc1_quality
{
cLowQuality,
cMediumQuality,
cHighQuality,
};
struct etc1_pack_params
{
etc1_quality m_quality;
bool m_dithering;
inline etc1_pack_params()
{
clear();
}
void clear()
{
m_quality = cHighQuality;
m_dithering = false;
}
};
// Important: pack_etc1_block_init() must be called before calling pack_etc1_block().
void pack_etc1_block_init();
// Packs a 4x4 block of 32bpp RGBA pixels to an 8-byte ETC1 block.
// 32-bit RGBA pixels must always be arranged as (R,G,B,A) (R first, A last) in memory, independent of platform endianness. A should always be 255.
// Returns squared error of result.
// This function is thread safe, and does not dynamically allocate any memory.
// pack_etc1_block() does not currently support "perceptual" colorspace metrics - it primarily optimizes for RGB RMSE.
unsigned int pack_etc1_block(void* pETC1_block, const unsigned int* pSrc_pixels_rgba, etc1_pack_params& pack_params);
} // namespace rg_etc1
//------------------------------------------------------------------------------
//
// rg_etc1 uses the ZLIB license:
// http://opensource.org/licenses/Zlib
//
// Copyright (c) 2012 Rich Geldreich
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
//------------------------------------------------------------------------------
Loading…
Cancel
Save