mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-24 10:35:44 +01:00
Actually adhere to the wrap mode passed to the compressor
This commit is contained in:
parent
b7b9357964
commit
049ea129eb
@ -62,7 +62,11 @@
|
|||||||
#include "FasTC/Pixel.h"
|
#include "FasTC/Pixel.h"
|
||||||
#include "FasTC/Color.h"
|
#include "FasTC/Color.h"
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
# include "PVRTCImage.h"
|
||||||
|
#endif
|
||||||
#include "Block.h"
|
#include "Block.h"
|
||||||
|
#include "Indexer.h"
|
||||||
|
|
||||||
#define USE_CONSTANT_LUTS
|
#define USE_CONSTANT_LUTS
|
||||||
|
|
||||||
@ -231,18 +235,26 @@ namespace PVRTCC {
|
|||||||
#define AssertPOT(x) (void)(0)
|
#define AssertPOT(x) (void)(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint8 LookupIntensityByte(CompressionLabel *labels,
|
||||||
|
const uint32 *pixels,
|
||||||
|
uint32 index) {
|
||||||
|
float i = 255.0f * LookupIntensity(labels, pixels, index);
|
||||||
|
return static_cast<uint8>(i + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
static EExtremaResult ComputeLocalExtrema(
|
static EExtremaResult ComputeLocalExtrema(
|
||||||
CompressionLabel *labels, const uint8 *inBuf,
|
CompressionLabel *labels, const uint8 *inBuf,
|
||||||
const uint32 x, const uint32 y, const uint32 width, const uint32 height) {
|
const uint32 x, const uint32 y, const Indexer &idxr) {
|
||||||
|
|
||||||
|
uint32 width = idxr.GetWidth();
|
||||||
|
uint32 height = idxr.GetHeight();
|
||||||
|
|
||||||
AssertPOT(width);
|
AssertPOT(width);
|
||||||
AssertPOT(height);
|
AssertPOT(height);
|
||||||
|
|
||||||
assert(x < width);
|
|
||||||
assert(y < height);
|
|
||||||
|
|
||||||
const uint32 *pixels = reinterpret_cast<const uint32 *>(inBuf);
|
const uint32 *pixels = reinterpret_cast<const uint32 *>(inBuf);
|
||||||
uint8 i0 = static_cast<uint8>(255.0f * LookupIntensity(labels, pixels, y*width + x) + 0.5f);
|
uint32 idx0 = idxr(x, y);
|
||||||
|
uint8 i0 = LookupIntensityByte(labels, pixels, idx0);
|
||||||
|
|
||||||
int32 ng = 0;
|
int32 ng = 0;
|
||||||
int32 nl = 0;
|
int32 nl = 0;
|
||||||
@ -254,14 +266,10 @@ namespace PVRTCC {
|
|||||||
|
|
||||||
if(i == 0 && j == 0) continue;
|
if(i == 0 && j == 0) continue;
|
||||||
|
|
||||||
int32 xx = (i + static_cast<int32>(x + width)) & (width - 1);
|
int32 xx = i + static_cast<int32>(x);
|
||||||
int32 yy = (j + static_cast<int32>(y + height)) & (height - 1);
|
int32 yy = j + static_cast<int32>(y);
|
||||||
|
uint8 ix = LookupIntensityByte(labels, pixels, idxr(xx, yy));
|
||||||
|
|
||||||
assert(xx >= 0 && xx < static_cast<int32>(width));
|
|
||||||
assert(yy >= 0 && yy < static_cast<int32>(height));
|
|
||||||
|
|
||||||
uint32 idx = static_cast<uint32>(xx) + width * static_cast<uint32>(yy);
|
|
||||||
uint8 ix = static_cast<uint8>(255.0f * LookupIntensity(labels, pixels, idx) + 0.5f);
|
|
||||||
if(ix >= i0) {
|
if(ix >= i0) {
|
||||||
ng++;
|
ng++;
|
||||||
}
|
}
|
||||||
@ -276,15 +284,15 @@ namespace PVRTCC {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompressionLabel &l = labels[y*width + x];
|
CompressionLabel &l = labels[idx0];
|
||||||
const int32 kThreshold = kKernelSz * kKernelSz - 1;
|
const int32 kThreshold = kKernelSz * kKernelSz - 1;
|
||||||
if(ng >= kThreshold) {
|
if(ng >= kThreshold) {
|
||||||
l.lowLabel.distance = 1;
|
l.lowLabel.distance = 1;
|
||||||
l.lowLabel.AddIdx(y*width+x);
|
l.lowLabel.AddIdx(idx0);
|
||||||
result = eExtremaResult_LocalMin;
|
result = eExtremaResult_LocalMin;
|
||||||
} else if(nl >= kThreshold) {
|
} else if(nl >= kThreshold) {
|
||||||
l.highLabel.distance = 1;
|
l.highLabel.distance = 1;
|
||||||
l.highLabel.AddIdx(y*width+x);
|
l.highLabel.AddIdx(idx0);
|
||||||
result = eExtremaResult_LocalMax;
|
result = eExtremaResult_LocalMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,23 +359,25 @@ namespace PVRTCC {
|
|||||||
|
|
||||||
static void LabelImageForward(CompressionLabel *labels,
|
static void LabelImageForward(CompressionLabel *labels,
|
||||||
const uint8 *inBuf,
|
const uint8 *inBuf,
|
||||||
const uint32 w, const uint32 h) {
|
const Indexer &idxr) {
|
||||||
|
uint32 w = idxr.GetWidth();
|
||||||
|
uint32 h = idxr.GetHeight();
|
||||||
|
|
||||||
AssertPOT(w);
|
AssertPOT(w);
|
||||||
AssertPOT(h);
|
AssertPOT(h);
|
||||||
|
|
||||||
for(uint32 j = 0; j < h+3; j++) {
|
for(uint32 j = 0; j < h+3; j++) {
|
||||||
for(uint32 i = 0; i < w; i++) {
|
for(uint32 i = 0; i < w; i++) {
|
||||||
EExtremaResult result = ComputeLocalExtrema(labels, inBuf, i, j & (h - 1), w, h);
|
EExtremaResult result = ComputeLocalExtrema(labels, inBuf, i, j, idxr);
|
||||||
bool dilateMax = result != eExtremaResult_LocalMax;
|
bool dilateMax = result != eExtremaResult_LocalMax;
|
||||||
bool dilateMin = result != eExtremaResult_LocalMin;
|
bool dilateMin = result != eExtremaResult_LocalMin;
|
||||||
|
|
||||||
if(dilateMax || dilateMin) {
|
if(dilateMax || dilateMin) {
|
||||||
// Look up and to the left to determine the distance...
|
// Look up and to the left to determine the distance...
|
||||||
uint32 upIdx = ((j+h-1) & (h - 1)) * w + i;
|
uint32 upIdx = idxr(i, j - 1);
|
||||||
uint32 leftIdx = (j & (h - 1)) * w + ((i+w-1) & (w - 1));
|
uint32 leftIdx = idxr(i - 1, j);
|
||||||
|
|
||||||
CompressionLabel &l = labels[(j & (h - 1))*w + i];
|
CompressionLabel &l = labels[idxr(i, j)];
|
||||||
CompressionLabel &up = labels[upIdx];
|
CompressionLabel &up = labels[upIdx];
|
||||||
CompressionLabel &left = labels[leftIdx];
|
CompressionLabel &left = labels[leftIdx];
|
||||||
|
|
||||||
@ -431,8 +441,10 @@ namespace PVRTCC {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LabelImageBackward(CompressionLabel *labels,
|
static void LabelImageBackward(CompressionLabel *labels, const Indexer &idxr) {
|
||||||
const uint32 w, const uint32 h) {
|
|
||||||
|
uint32 w = idxr.GetWidth();
|
||||||
|
uint32 h = idxr.GetHeight();
|
||||||
|
|
||||||
AssertPOT(w);
|
AssertPOT(w);
|
||||||
AssertPOT(h);
|
AssertPOT(h);
|
||||||
@ -441,22 +453,22 @@ namespace PVRTCC {
|
|||||||
for(int32 j = static_cast<int32>(h)+2; j >= 0; j--) {
|
for(int32 j = static_cast<int32>(h)+2; j >= 0; j--) {
|
||||||
for(int32 i = static_cast<int32>(w)-1; i >= 0; i--) {
|
for(int32 i = static_cast<int32>(w)-1; i >= 0; i--) {
|
||||||
|
|
||||||
CompressionLabel &l = labels[(j & (h - 1)) * w + i];
|
CompressionLabel &l = labels[idxr(i, j)];
|
||||||
|
|
||||||
// Add top right corner
|
// Add top right corner
|
||||||
neighbors[0] = &(labels[((j + h - 1) & (h - 1)) * w + ((i + 1) & (w - 1))]);
|
neighbors[0] = &(labels[idxr(i+1, j-1)]);
|
||||||
|
|
||||||
// Add right label
|
// Add right label
|
||||||
neighbors[1] = &(labels[(j & (h - 1)) * w + ((i + 1) & (w - 1))]);
|
neighbors[1] = &(labels[idxr(i+1, j)]);
|
||||||
|
|
||||||
// Add bottom right label
|
// Add bottom right label
|
||||||
neighbors[2] = &(labels[((j + 1) & (h - 1)) * w + ((i + 1) & (w - 1))]);
|
neighbors[2] = &(labels[idxr(i+1, j+1)]);
|
||||||
|
|
||||||
// Add bottom label
|
// Add bottom label
|
||||||
neighbors[3] = &(labels[((j + 1) & (h - 1)) * w + i]);
|
neighbors[3] = &(labels[idxr(i, j+1)]);
|
||||||
|
|
||||||
// Add bottom left label
|
// Add bottom left label
|
||||||
neighbors[4] = &(labels[((j + 1) & (h - 1)) * w + ((i + w - 1) & (w - 1))]);
|
neighbors[4] = &(labels[idxr(i-1, j+1)]);
|
||||||
|
|
||||||
DilateLabelBackward(l.highLabel, neighbors, true);
|
DilateLabelBackward(l.highLabel, neighbors, true);
|
||||||
DilateLabelBackward(l.lowLabel, neighbors, false);
|
DilateLabelBackward(l.lowLabel, neighbors, false);
|
||||||
@ -464,60 +476,6 @@ namespace PVRTCC {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void DilateImage(CompressionLabel *labels, const uint8 *inBuf, uint32 w, uint32 h) {
|
|
||||||
for(uint32 j = 0; j < h; j++)
|
|
||||||
for(uint32 i = 0; i < w; i++) {
|
|
||||||
ComputeLocalExtrema(labels, inBuf, i, j, w, h);
|
|
||||||
|
|
||||||
uint32 idx = j*w + i;
|
|
||||||
|
|
||||||
uint32 minLowDist = labels[idx].lowLabel.distance == 0? 5 : labels[idx].lowLabel.distance - 1;
|
|
||||||
uint32 minHighDist = labels[idx].highLabel.distance == 0? 5 : labels[idx].highLabel.distance - 1;
|
|
||||||
|
|
||||||
for(int32 y = 0; y < 3; y++)
|
|
||||||
for(int32 x = 0; x < 3; x++) {
|
|
||||||
uint32 cidx = ((j + y + h-1) & (h-1))*w + ((i+x+w-1) & (w-1));
|
|
||||||
|
|
||||||
if(labels[cidx].lowLabel.distance > 0)
|
|
||||||
minLowDist = ::std::min<uint32>(minLowDist, labels[cidx].lowLabel.distance);
|
|
||||||
|
|
||||||
if(labels[cidx].highLabel.distance > 0)
|
|
||||||
minHighDist = ::std::min<uint32>(minHighDist, labels[cidx].highLabel.distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(static_cast<int32>(minLowDist) != labels[idx].lowLabel.distance - 1) {
|
|
||||||
labels[idx].lowLabel.nLabels = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(static_cast<int32>(minHighDist) != labels[idx].highLabel.distance - 1) {
|
|
||||||
labels[idx].highLabel.nLabels = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int32 y = 0; y < 3; y++)
|
|
||||||
for(int32 x = 0; x < 3; x++) {
|
|
||||||
uint32 cidx = ((j + y + h-1) & (h-1))*w + ((i+x+w-1) & (w-1));
|
|
||||||
|
|
||||||
if(minLowDist > 0 && labels[cidx].lowLabel.distance == minLowDist) {
|
|
||||||
labels[idx].lowLabel.Combine(labels[cidx].lowLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minHighDist > 0 && labels[cidx].highLabel.distance == minHighDist) {
|
|
||||||
labels[idx].highLabel.Combine(labels[cidx].highLabel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minLowDist > 0 && minLowDist < 5) {
|
|
||||||
labels[idx].lowLabel.distance = minLowDist + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minHighDist > 0 && minHighDist < 5) {
|
|
||||||
labels[idx].highLabel.distance = minHighDist + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static FasTC::Color CollectLabel(const uint32 *pixels, const Label &label) {
|
static FasTC::Color CollectLabel(const uint32 *pixels, const Label &label) {
|
||||||
FasTC::Color ret;
|
FasTC::Color ret;
|
||||||
uint32 nPs = 0;
|
uint32 nPs = 0;
|
||||||
@ -536,7 +494,10 @@ namespace PVRTCC {
|
|||||||
|
|
||||||
static void GenerateLowHighImages(CompressionLabel *labels,
|
static void GenerateLowHighImages(CompressionLabel *labels,
|
||||||
const uint8 *inBuf, uint8 *outBuf,
|
const uint8 *inBuf, uint8 *outBuf,
|
||||||
const uint32 w, const uint32 h) {
|
const Indexer &idxr) {
|
||||||
|
uint32 w = idxr.GetWidth();
|
||||||
|
uint32 h = idxr.GetHeight();
|
||||||
|
|
||||||
assert((w % 4) == 0);
|
assert((w % 4) == 0);
|
||||||
assert((h % 4) == 0);
|
assert((h % 4) == 0);
|
||||||
AssertPOT(w);
|
AssertPOT(w);
|
||||||
@ -556,7 +517,7 @@ namespace PVRTCC {
|
|||||||
for(uint32 y = j*4; y <= (j+1)*4; y++)
|
for(uint32 y = j*4; y <= (j+1)*4; y++)
|
||||||
for(uint32 x = i*4; x <= (i+1)*4; x++) {
|
for(uint32 x = i*4; x <= (i+1)*4; x++) {
|
||||||
|
|
||||||
uint32 idx = (y & (h-1))*w + (x & (w-1));
|
uint32 idx = idxr(x, y);
|
||||||
float intensity = labels[idx].intensity;
|
float intensity = labels[idx].intensity;
|
||||||
if(intensity < minIntensity) {
|
if(intensity < minIntensity) {
|
||||||
minIntensity = intensity;
|
minIntensity = intensity;
|
||||||
@ -616,9 +577,10 @@ namespace PVRTCC {
|
|||||||
#endif
|
#endif
|
||||||
// Average all of the values together now...
|
// Average all of the values together now...
|
||||||
FasTC::Color high, low;
|
FasTC::Color high, low;
|
||||||
for(uint32 y = 0; y < 4; y++)
|
Indexer localIdxr(4, 4);
|
||||||
for(uint32 x = 0; x < 4; x++) {
|
for(uint32 y = 0; y < localIdxr.GetHeight(); y++)
|
||||||
uint32 idx = y * 4 + x;
|
for(uint32 x = 0; x < localIdxr.GetWidth(); x++) {
|
||||||
|
uint32 idx = localIdxr(x, y);
|
||||||
FasTC::Color c = blockColors[0][idx];
|
FasTC::Color c = blockColors[0][idx];
|
||||||
if(c.A() < 0.0f) {
|
if(c.A() < 0.0f) {
|
||||||
c.Unpack(pixels[maxIntensityIdx]);
|
c.Unpack(pixels[maxIntensityIdx]);
|
||||||
@ -699,7 +661,10 @@ namespace PVRTCC {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GenerateModulationValues(uint8 *outBuf, const uint8 *inBuf, uint32 w, uint32 h) {
|
static void GenerateModulationValues(uint8 *outBuf, const uint8 *inBuf,
|
||||||
|
const Indexer &idxr) {
|
||||||
|
uint32 w = idxr.GetWidth();
|
||||||
|
uint32 h = idxr.GetHeight();
|
||||||
|
|
||||||
AssertPOT(w);
|
AssertPOT(w);
|
||||||
AssertPOT(h);
|
AssertPOT(h);
|
||||||
@ -715,13 +680,14 @@ namespace PVRTCC {
|
|||||||
// every iteration of the loop. Once we finish with a block, topLeft becomes topRight and
|
// every iteration of the loop. Once we finish with a block, topLeft becomes topRight and
|
||||||
// bottomLeft becomes bottomRight. Also, when we go to the next row, bottomRight becomes
|
// bottomLeft becomes bottomRight. Also, when we go to the next row, bottomRight becomes
|
||||||
// topLeft.
|
// topLeft.
|
||||||
|
Indexer blkIdxr(blocksW, blocksH, idxr.GetWrapMode());
|
||||||
for(uint32 j = 0; j < blocksH; j++) {
|
for(uint32 j = 0; j < blocksH; j++) {
|
||||||
for(uint32 i = 0; i < blocksW; i++) {
|
for(uint32 i = 0; i < blocksW; i++) {
|
||||||
|
|
||||||
const int32 lowXIdx = i;
|
const int32 lowXIdx = i;
|
||||||
const int32 highXIdx = (i + 1) & (blocksW - 1);
|
const int32 highXIdx = blkIdxr.ResolveX(i + 1);
|
||||||
const int32 lowYIdx = j;
|
const int32 lowYIdx = j;
|
||||||
const int32 highYIdx = (j + 1) & (blocksH - 1);
|
const int32 highYIdx = blkIdxr.ResolveY(j + 1);
|
||||||
|
|
||||||
const uint32 topLeftBlockIdx = GetBlockIndex(lowXIdx, lowYIdx);
|
const uint32 topLeftBlockIdx = GetBlockIndex(lowXIdx, lowYIdx);
|
||||||
const uint32 topRightBlockIdx = GetBlockIndex(highXIdx, lowYIdx);
|
const uint32 topRightBlockIdx = GetBlockIndex(highXIdx, lowYIdx);
|
||||||
@ -759,8 +725,8 @@ namespace PVRTCC {
|
|||||||
|
|
||||||
for(uint32 y = 0; y < 4; y++) {
|
for(uint32 y = 0; y < 4; y++) {
|
||||||
for(uint32 x = 0; x < 4; x++) {
|
for(uint32 x = 0; x < 4; x++) {
|
||||||
uint32 pixelX = (i*4 + 2 + x) & (w - 1);
|
uint32 pixelX = idxr.ResolveX(i*4 + 2 + x);
|
||||||
uint32 pixelY = (j*4 + 2 + y) & (h - 1);
|
uint32 pixelY = idxr.ResolveY(j*4 + 2 + y);
|
||||||
FasTC::Pixel colorA = BilerpPixels(x, y, topLeftA, topRightA, bottomLeftA, bottomRightA);
|
FasTC::Pixel colorA = BilerpPixels(x, y, topLeftA, topRightA, bottomLeftA, bottomRightA);
|
||||||
FasTC::Pixel colorB = BilerpPixels(x, y, topLeftB, topRightB, bottomLeftB, bottomRightB);
|
FasTC::Pixel colorB = BilerpPixels(x, y, topLeftB, topRightB, bottomLeftB, bottomRightB);
|
||||||
FasTC::Pixel original(pixels[pixelY * w + pixelX]);
|
FasTC::Pixel original(pixels[pixelY * w + pixelX]);
|
||||||
@ -938,8 +904,10 @@ namespace PVRTCC {
|
|||||||
CompressionLabel *labels =
|
CompressionLabel *labels =
|
||||||
(CompressionLabel *)calloc(width * height, sizeof(CompressionLabel));
|
(CompressionLabel *)calloc(width * height, sizeof(CompressionLabel));
|
||||||
|
|
||||||
|
Indexer idxr(width, height, wrapMode);
|
||||||
|
|
||||||
// First traverse forward...
|
// First traverse forward...
|
||||||
LabelImageForward(labels, cj.InBuf(), width, height);
|
LabelImageForward(labels, cj.InBuf(), idxr);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
gDbgPixels = reinterpret_cast<const uint32 *>(cj.InBuf());
|
gDbgPixels = reinterpret_cast<const uint32 *>(cj.InBuf());
|
||||||
@ -961,7 +929,7 @@ namespace PVRTCC {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Then traverse backward...
|
// Then traverse backward...
|
||||||
LabelImageBackward(labels, width, height);
|
LabelImageBackward(labels, idxr);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
DebugOutputLabels("Backward-", labels, width, height);
|
DebugOutputLabels("Backward-", labels, width, height);
|
||||||
@ -992,10 +960,10 @@ namespace PVRTCC {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Then combine everything...
|
// Then combine everything...
|
||||||
GenerateLowHighImages(labels, cj.InBuf(), cj.OutBuf(), width, height);
|
GenerateLowHighImages(labels, cj.InBuf(), cj.OutBuf(), idxr);
|
||||||
|
|
||||||
// Then compute modulation values
|
// Then compute modulation values
|
||||||
GenerateModulationValues(cj.OutBuf(), cj.InBuf(), width, height);
|
GenerateModulationValues(cj.OutBuf(), cj.InBuf(), idxr);
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
free(labels);
|
free(labels);
|
||||||
|
118
PVRTCEncoder/src/Indexer.h
Normal file
118
PVRTCEncoder/src/Indexer.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* FasTC
|
||||||
|
* Copyright (c) 2013 University of North Carolina at Chapel Hill.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software and its
|
||||||
|
* documentation for educational, research, and non-profit purposes, without
|
||||||
|
* fee, and without a written agreement is hereby granted, provided that the
|
||||||
|
* above copyright notice, this paragraph, and the following four paragraphs
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* Permission to incorporate this software into commercial products may be
|
||||||
|
* obtained by contacting the authors or the Office of Technology Development
|
||||||
|
* at the University of North Carolina at Chapel Hill <otd@unc.edu>.
|
||||||
|
*
|
||||||
|
* This software program and documentation are copyrighted by the University of
|
||||||
|
* North Carolina at Chapel Hill. The software program and documentation are
|
||||||
|
* supplied "as is," without any accompanying services from the University of
|
||||||
|
* North Carolina at Chapel Hill or the authors. The University of North
|
||||||
|
* Carolina at Chapel Hill and the authors do not warrant that the operation of
|
||||||
|
* the program will be uninterrupted or error-free. The end-user understands
|
||||||
|
* that the program was developed for research purposes and is advised not to
|
||||||
|
* rely exclusively on the program for any reason.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
|
||||||
|
* AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA
|
||||||
|
* AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY
|
||||||
|
* DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
|
||||||
|
* STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON
|
||||||
|
* AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND
|
||||||
|
* THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||||
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Please send all BUG REPORTS to <pavel@cs.unc.edu>.
|
||||||
|
*
|
||||||
|
* The authors may be contacted via:
|
||||||
|
*
|
||||||
|
* Pavel Krajcevski
|
||||||
|
* Dept of Computer Science
|
||||||
|
* 201 S Columbia St
|
||||||
|
* Frederick P. Brooks, Jr. Computer Science Bldg
|
||||||
|
* Chapel Hill, NC 27599-3175
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* <http://gamma.cs.unc.edu/FasTC/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PVRTCENCODER_SRC_INDEXER_H_
|
||||||
|
#define PVRTCENCODER_SRC_INDEXER_H_
|
||||||
|
|
||||||
|
#include "FasTC/PVRTCCompressor.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace PVRTCC {
|
||||||
|
|
||||||
|
class Indexer {
|
||||||
|
private:
|
||||||
|
const EWrapMode m_WrapMode;
|
||||||
|
const uint32 m_Width;
|
||||||
|
const uint32 m_Height;
|
||||||
|
|
||||||
|
uint32 Resolve(int32 i, uint32 limit) const {
|
||||||
|
int32 r;
|
||||||
|
switch(m_WrapMode) {
|
||||||
|
case eWrapMode_Clamp:
|
||||||
|
r = static_cast<uint32>(std::max(0, std::min<int32>(i, limit)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eWrapMode_Wrap:
|
||||||
|
{
|
||||||
|
r = i;
|
||||||
|
int32 l = static_cast<int32>(limit);
|
||||||
|
while (r >= l) { r -= l; }
|
||||||
|
while (r < 0) { r += l; }
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (r >= 0);
|
||||||
|
assert (r < limit);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Indexer(uint32 width, uint32 height, EWrapMode wrapMode = eWrapMode_Wrap)
|
||||||
|
: m_WrapMode(wrapMode)
|
||||||
|
, m_Width(width)
|
||||||
|
, m_Height(height)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint32 GetWidth() const { return this->m_Width; }
|
||||||
|
uint32 GetHeight() const { return this->m_Height; }
|
||||||
|
EWrapMode GetWrapMode() const { return this->m_WrapMode; }
|
||||||
|
|
||||||
|
uint32 ResolveX(int32 i) const { return Resolve(i, this->m_Width); }
|
||||||
|
uint32 ResolveY(int32 i) const { return Resolve(i, this->m_Height); }
|
||||||
|
|
||||||
|
uint32 operator()(int32 i, int32 j) const {
|
||||||
|
uint32 _i = this->ResolveX(i);
|
||||||
|
uint32 _j = this->ResolveY(j);
|
||||||
|
|
||||||
|
uint32 index = _j * this->m_Width + _i;
|
||||||
|
assert (index < this->m_Width * this->m_Height);
|
||||||
|
assert (index >= 0);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace PVRTCC
|
||||||
|
|
||||||
|
#endif // PVRTCENCODER_SRC_INDEXER_H_
|
Loading…
Reference in New Issue
Block a user