Compare commits

...

3 Commits

Author SHA1 Message Date
a3cc69db64 Split up blocks file 2021-02-14 19:01:41 -08:00
36bd624273 Fix some small integer type issues 2021-02-14 18:19:14 -08:00
eb4fa20d2f Fix segfault 2021-02-14 17:52:13 -08:00
20 changed files with 228 additions and 126 deletions

View File

@ -36,7 +36,7 @@ set_project_warnings(test_rgbcx)
if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fsanitize=undefined")
set(PROJECT_WARNINGS ${CLANG_WARNINGS})
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set_property(TARGET python_rgbcx test_rgbcx PROPERTY OSX_ARCHITECTURES_RELEASE x86_64 arm64) #Mach-O fat binary for arm and x86

85
src/BC1/BC1Block.h Normal file
View File

@ -0,0 +1,85 @@
/* Python-rgbcx Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <array>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include "../Color.h"
#include "../util.h"
namespace rgbcx {
#pragma pack(push, 1)
class BC1Block {
public:
using UnpackedSelectors = std::array<std::array<uint8_t, 4>, 4>;
uint16_t GetLowColor() const { return static_cast<uint16_t>(_low_color[0] | (_low_color[1] << 8U)); }
uint16_t GetHighColor() const { return static_cast<uint16_t>(_high_color[0] | (_high_color[1] << 8U)); }
Color GetLowColor32() const { return Color::Unpack565(GetLowColor()); }
Color GetHighColor32() const { return Color::Unpack565(GetHighColor()); }
bool Is3Color() const { return GetLowColor() <= GetHighColor(); }
void SetLowColor(uint16_t c) {
_low_color[0] = c & 0xFF;
_low_color[1] = (c >> 8) & 0xFF;
}
void SetHighColor(uint16_t c) {
_high_color[0] = c & 0xFF;
_high_color[1] = (c >> 8) & 0xFF;
}
uint32_t GetSelector(uint32_t x, uint32_t y) const {
assert((x < 4U) && (y < 4U));
return (selectors[y] >> (x * SelectorBits)) & SelectorMask;
}
void SetSelector(uint32_t x, uint32_t y, uint32_t val) {
assert((x < 4U) && (y < 4U) && (val < 4U));
selectors[y] &= (~(SelectorMask << (x * SelectorBits)));
selectors[y] |= (val << (x * SelectorBits));
}
UnpackedSelectors UnpackSelectors() const {
UnpackedSelectors unpacked;
for (unsigned i = 0; i < 4; i++) { unpacked[i] = Unpack<uint8_t, uint8_t, 2, 4>(selectors[i]); }
return unpacked;
}
void PackSelectors(const UnpackedSelectors& unpacked) {
for (unsigned i = 0; i < 4; i++) { selectors[i] = Pack<uint8_t, uint8_t, 2, 4>(unpacked[i]); }
}
constexpr static inline size_t EndpointSize = 2;
constexpr static inline size_t SelectorSize = 4;
constexpr static inline uint8_t SelectorBits = 2;
constexpr static inline uint8_t SelectorValues = 1 << SelectorBits;
constexpr static inline uint8_t SelectorMask = SelectorValues - 1;
private:
std::array<uint8_t, EndpointSize> _low_color;
std::array<uint8_t, EndpointSize> _high_color;
public:
std::array<uint8_t, 4> selectors;
};
#pragma pack(pop)
} // namespace rgbcx

View File

@ -21,19 +21,21 @@
#include <assert.h>
#include <stdint.h>
#include <array>
#include "../ColorBlock.h"
#include "../blocks.h"
#include "../Color.h"
#include "../ColorBlock.h"
#include "../interpolator.h"
#include "../ndebug.h"
#include "BC1Block.h"
namespace rgbcx {
void BC1Decoder::DecodeBlock(Color4x4 dest, BC1Block *const block) const noexcept(ndebug) {
const auto l = block->GetLowColor();
const auto h = block->GetHighColor();
const auto selectors = block->UnpackSelectors();
const auto colors = _interpolator.InterpolateBC1(l, h);
const auto colors = _interpolator->InterpolateBC1(l, h);
for (unsigned y = 0; y < 4; y++) {
for (unsigned x = 0; x < 4; x++) {

View File

@ -19,24 +19,28 @@
#pragma once
#include <memory>
#include "../BlockDecoder.h"
#include "../blocks.h"
#include "../ColorBlock.h"
#include "../interpolator.h"
#include "../ndebug.h"
#include "../ColorBlock.h"
#include "BC1Block.h"
namespace rgbcx {
class BC1Decoder final : public BlockDecoder<BC1Block, 4, 4> {
public:
BC1Decoder(const Interpolator &interpolator = Interpolator(), bool write_alpha = false) : _interpolator(interpolator), _write_alpha(write_alpha) {}
using InterpolatorPtr = std::shared_ptr<Interpolator>;
BC1Decoder(const InterpolatorPtr interpolator = std::make_shared<Interpolator>(), bool write_alpha = false)
: _interpolator(interpolator), _write_alpha(write_alpha) {}
void DecodeBlock(Color4x4 dest, BC1Block *const block) const noexcept(ndebug) override;
constexpr const Interpolator &GetInterpolator() const { return _interpolator; }
InterpolatorPtr GetInterpolator() const { return _interpolator; }
constexpr bool WritesAlpha() const { return _write_alpha; }
private:
const Interpolator &_interpolator;
const InterpolatorPtr _interpolator;
const bool _write_alpha;
};
} // namespace rgbcx

34
src/BC3/BC3Block.h Normal file
View File

@ -0,0 +1,34 @@
/* Python-rgbcx Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "../BC1/BC1Block.h"
#include "../BC4/BC4Block.h"
namespace rgbcx {
#pragma pack(push, 1)
class BC3Block {
public:
BC4Block alpha_block;
BC1Block color_block;
};
#pragma pack(pop)
} // namespace rgbcx

View File

@ -22,13 +22,12 @@
#include "../BC1/BC1Decoder.h"
#include "../BC4/BC4Decoder.h"
#include "../ColorBlock.h"
#include "../blocks.h"
#include "../ndebug.h"
namespace rgbcx {
void BC3Decoder::DecodeBlock(Color4x4 dest, BC3Block *const block) const noexcept(ndebug) {
_bc1_decoder.DecodeBlock(dest, &(block->color_block));
_bc4_decoder.DecodeBlock(dest, &(block->alpha_block), 3);
_bc1_decoder->DecodeBlock(dest, &(block->color_block));
_bc4_decoder->DecodeBlock(dest, &(block->alpha_block), 3);
}
} // namespace rgbcx

View File

@ -19,24 +19,30 @@
#pragma once
#include <memory>
#include "../BC1/BC1Decoder.h"
#include "../BC4/BC4Decoder.h"
#include "../BlockDecoder.h"
#include "../ColorBlock.h"
#include "../blocks.h"
#include "../interpolator.h"
#include "../ndebug.h"
#include "BC3Block.h"
namespace rgbcx {
class BC3Decoder : public BlockDecoder<BC3Block, 4, 4> {
public:
BC3Decoder(const Interpolator &interpolator = Interpolator()) : BC3Decoder(BC1Decoder(interpolator, false)) {}
BC3Decoder(const BC1Decoder &bc1_decoder, const BC4Decoder &bc4_decoder = BC4Decoder()) : _bc1_decoder(bc1_decoder), _bc4_decoder(bc4_decoder) {}
using InterpolatorPtr = std::shared_ptr<Interpolator>;
using BC1DecoderPtr = std::shared_ptr<BC1Decoder>;
using BC4DecoderPtr = std::shared_ptr<BC4Decoder>;
BC3Decoder(InterpolatorPtr interpolator = std::make_shared<Interpolator>()) : BC3Decoder(std::make_shared<BC1Decoder>(interpolator)) {}
BC3Decoder(BC1DecoderPtr bc1_decoder, BC4DecoderPtr bc4_decoder = std::make_shared<BC4Decoder>()) : _bc1_decoder(bc1_decoder), _bc4_decoder(bc4_decoder) {}
void DecodeBlock(Color4x4 dest, BC3Block *const block) const noexcept(ndebug) override;
private:
const BC1Decoder &_bc1_decoder;
const BC4Decoder &_bc4_decoder;
const BC1DecoderPtr _bc1_decoder;
const BC4DecoderPtr _bc4_decoder;
};
} // namespace rgbcx

View File

@ -1,6 +1,6 @@
/* Python-rgbcx Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
This program is free software: you can redistribute it and/or modify
@ -24,62 +24,13 @@
#include <cstdint>
#include <cstdlib>
#include "Color.h"
#include "util.h"
#include "../BC1/BC1Block.h"
#include "../Color.h"
#include "../util.h"
namespace rgbcx {
#pragma pack(push, 1)
class BC1Block {
public:
using UnpackedSelectors = std::array<std::array<uint8_t, 4>, 4>;
uint16_t GetLowColor() const { return static_cast<uint16_t>(_low_color[0] | (_low_color[1] << 8U)); }
uint16_t GetHighColor() const { return static_cast<uint16_t>(_high_color[0] | (_high_color[1] << 8U)); }
Color GetLowColor32() const { return Color::Unpack565(GetLowColor()); }
Color GetHighColor32() const { return Color::Unpack565(GetHighColor()); }
bool Is3Color() const { return GetLowColor() <= GetHighColor(); }
void SetLowColor(uint16_t c) {
_low_color[0] = c & 0xFF;
_low_color[1] = (c >> 8) & 0xFF;
}
void SetHighColor(uint16_t c) {
_high_color[0] = c & 0xFF;
_high_color[1] = (c >> 8) & 0xFF;
}
uint32_t GetSelector(uint32_t x, uint32_t y) const {
assert((x < 4U) && (y < 4U));
return (selectors[y] >> (x * SelectorBits)) & SelectorMask;
}
void SetSelector(uint32_t x, uint32_t y, uint32_t val) {
assert((x < 4U) && (y < 4U) && (val < 4U));
selectors[y] &= (~(SelectorMask << (x * SelectorBits)));
selectors[y] |= (val << (x * SelectorBits));
}
UnpackedSelectors UnpackSelectors() const {
UnpackedSelectors unpacked;
for (unsigned i = 0; i < 4; i++) { unpacked[i] = Unpack<uint8_t, uint8_t, 2, 4>(selectors[i]); }
return unpacked;
}
void PackSelectors(const UnpackedSelectors& unpacked) {
for (unsigned i = 0; i < 4; i++) { selectors[i] = Pack<uint8_t, uint8_t, 2, 4>(unpacked[i]); }
}
constexpr static inline size_t EndpointSize = 2;
constexpr static inline size_t SelectorSize = 4;
constexpr static inline uint8_t SelectorBits = 2;
constexpr static inline uint8_t SelectorValues = 1 << SelectorBits;
constexpr static inline uint8_t SelectorMask = SelectorValues - 1;
private:
std::array<uint8_t, EndpointSize> _low_color;
std::array<uint8_t, EndpointSize> _high_color;
public:
std::array<uint8_t, 4> selectors;
};
class BC4Block {
public:
using UnpackedSelectors = std::array<std::array<uint8_t, 4>, 4>;
@ -156,22 +107,11 @@ class BC4Block {
constexpr static inline uint8_t SelectorBits = 3;
constexpr static inline uint8_t SelectorValues = 1 << SelectorBits;
constexpr static inline uint8_t SelectorMask = SelectorValues - 1;
constexpr static inline uint64_t SelectorBitsMax = (1UL << (8U * SelectorSize)) - 1U;
constexpr static inline uint64_t SelectorBitsMax = (1ULL << (8U * SelectorSize)) - 1U;
uint8_t low_alpha;
uint8_t high_alpha;
std::array<uint8_t, SelectorSize> selectors;
};
class BC3Block {
public:
BC4Block alpha_block;
BC1Block color_block;
};
class BC5Block {
public:
BC4Block chan0_block;
BC4Block chan1_block;
};
#pragma pack(pop)
#pragma pack(pop)
} // namespace rgbcx

View File

@ -25,8 +25,8 @@
#include "../Color.h" // for Color
#include "../ColorBlock.h" // for ColorBlock
#include "../blocks.h" // for BC4Block
#include "../ndebug.h" // for ndebug
#include "BC4Block.h"
void rgbcx::BC4Decoder::DecodeBlock(Color4x4 dest, BC4Block *const block, size_t channel) const noexcept(ndebug) {
auto l = block->GetLowAlpha();

View File

@ -23,8 +23,8 @@
#include "../BlockDecoder.h"
#include "../ColorBlock.h"
#include "../blocks.h"
#include "../ndebug.h"
#include "BC4Block.h"
namespace rgbcx {
class BC4Decoder : public BlockDecoder<BC4Block, 4, 4> {

33
src/BC5/BC5Block.h Normal file
View File

@ -0,0 +1,33 @@
/* Python-rgbcx Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "../BC4/BC4Block.h"
namespace rgbcx {
#pragma pack(push, 1)
class BC5Block {
public:
BC4Block chan0_block;
BC4Block chan1_block;
};
#pragma pack(pop)
} // namespace rgbcx

View File

@ -21,13 +21,12 @@
#include "../BC4/BC4Decoder.h"
#include "../ColorBlock.h"
#include "../blocks.h"
#include "../ndebug.h"
namespace rgbcx {
void BC5Decoder::DecodeBlock(Color4x4 dest, BC5Block *const block) const noexcept(ndebug) {
_bc4_decoder.DecodeBlock(dest, &block->chan0_block, _chan0);
_bc4_decoder.DecodeBlock(dest, &block->chan1_block, _chan1);
_bc4_decoder->DecodeBlock(dest, &block->chan0_block, _chan0);
_bc4_decoder->DecodeBlock(dest, &block->chan1_block, _chan1);
}
} // namespace rgbcx

View File

@ -20,18 +20,21 @@
#pragma once
#include <stddef.h>
#include <memory>
#include "../BC4/BC4Decoder.h"
#include "../BlockDecoder.h"
#include "../ColorBlock.h"
#include "../ndebug.h"
#include "../blocks.h"
#include "BC5Block.h"
namespace rgbcx {
class BC5Decoder : public BlockDecoder<BC5Block, 4, 4> {
public:
BC5Decoder(size_t chan0 = 0, size_t chan1 = 1) : BC5Decoder(BC4Decoder(), chan0, chan1) {}
BC5Decoder(const BC4Decoder &bc4_decoder, size_t chan0 = 0, size_t chan1 = 1) : _bc4_decoder(bc4_decoder), _chan0(chan0), _chan1(chan1) {}
using BC4DecoderPtr = std::shared_ptr<BC4Decoder>;
BC5Decoder(size_t chan0 = 0, size_t chan1 = 1) : BC5Decoder(std::make_shared<BC4Decoder>(), chan0, chan1) {}
BC5Decoder(BC4DecoderPtr bc4_decoder, size_t chan0 = 0, size_t chan1 = 1) : _bc4_decoder(bc4_decoder), _chan0(chan0), _chan1(chan1) {}
void DecodeBlock(Color4x4 dest, BC5Block *const block) const noexcept(ndebug) override;
@ -39,7 +42,7 @@ class BC5Decoder : public BlockDecoder<BC5Block, 4, 4> {
constexpr size_t GetChannel1() const { return _chan1; }
private:
const BC4Decoder &_bc4_decoder;
const BC4DecoderPtr _bc4_decoder;
const size_t _chan0;
const size_t _chan1;
};

View File

@ -56,7 +56,7 @@ class Color {
void SetRGBA(const Color &other) { SetRGBA(other.r, other.g, other.b, other.a); }
void SetRGB(uint8_t vr, uint8_t vg, uint8_t vb);
void SetRGB(const Color &other) { SetRGB(other.r, other.g, other.a); }
void SetRGB(const Color &other) { SetRGB(other.r, other.g, other.b); }
uint16_t pack565();
uint16_t pack565Unscaled();
@ -67,6 +67,6 @@ class Color {
static Color min(const Color &A, const Color &B);
static Color max(const Color &A, const Color &B);
unsigned get_luma() const { return (13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U; } // REC709 weightings
int get_luma() const { return (13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U; } // REC709 weightings
};
#pragma pack(pop)

View File

@ -25,7 +25,7 @@
#include <cstdio>
#include <vector>
#include "blocks.h"
#include "Color.h"
template <size_t N> class ColorRow {
public:

View File

@ -127,22 +127,16 @@ std::array<Color, 4> Interpolator::InterpolateBC1(uint16_t low, uint16_t high) c
return colors;
}
uint8_t Interpolator::Interpolate8(uint8_t v0, uint8_t v1) const {
return (v0 * 2 + v1) / 3;
}
uint8_t Interpolator::Interpolate8(uint8_t v0, uint8_t v1) const { return (v0 * 2 + v1) / 3; }
uint8_t Interpolator::InterpolateHalf8(uint8_t v0, uint8_t v1) const {
return (v0 + v1) / 2;
}
uint8_t Interpolator::InterpolateHalf8(uint8_t v0, uint8_t v1) const { return (v0 + v1) / 2; }
// endregion
// region InterpolatorRound implementation
uint8_t InterpolatorRound::Interpolate5(uint8_t v0, uint8_t v1) const { return Interpolate8(scale5To8(v0), scale5To8(v1)); }
uint8_t InterpolatorRound::Interpolate6(uint8_t v0, uint8_t v1) const { return Interpolate8(scale6To8(v0), scale6To8(v1)); }
uint8_t InterpolatorRound::Interpolate8(uint8_t v0, uint8_t v1) const {
return (v0 * 2 + v1 + 1) / 3;
}
uint8_t InterpolatorRound::Interpolate8(uint8_t v0, uint8_t v1) const { return (v0 * 2 + v1 + 1) / 3; }
// endregion
// region InterpolatorNvidia implementation
@ -153,7 +147,7 @@ uint8_t InterpolatorNvidia::Interpolate5(uint8_t v0, uint8_t v1) const {
uint8_t InterpolatorNvidia::Interpolate6(uint8_t v0, uint8_t v1) const {
assert(v0 < 64 && v1 < 64);
const int gdiff = v1 - v0;
const int gdiff = (int) v1 - v0;
return static_cast<uint8_t>((256 * v0 + (gdiff / 4) + 128 + gdiff * 80) >> 8);
}
@ -164,13 +158,13 @@ uint8_t InterpolatorNvidia::InterpolateHalf5(uint8_t v0, uint8_t v1) const {
uint8_t InterpolatorNvidia::InterpolateHalf6(uint8_t v0, uint8_t v1) const {
assert(v0 < 64 && v1 < 64);
const int gdiff = v1 - v0;
const int gdiff = (int) v1 - v0;
return static_cast<uint8_t>((256 * v0 + gdiff / 4 + 128 + gdiff * 128) >> 8);
}
std::array<Color, 4> InterpolatorNvidia::InterpolateBC1(uint16_t low, uint16_t high) const {
// Nvidia is special and interpolation cant be done with 8-bit values, so we need to override the default behavior
auto colors = std::array<Color, 4>();
std::array<Color, 4> colors;
auto low565 = Color::Unpack565Unscaled(low);
auto high565 = Color::Unpack565Unscaled(high);
colors[0] = low565.ScaleFrom565();
@ -196,12 +190,8 @@ uint8_t InterpolatorAMD::Interpolate6(uint8_t v0, uint8_t v1) const { return Int
uint8_t InterpolatorAMD::InterpolateHalf5(uint8_t v0, uint8_t v1) const { return InterpolateHalf8(scale5To8(v0), scale5To8(v1)); }
uint8_t InterpolatorAMD::InterpolateHalf6(uint8_t v0, uint8_t v1) const { return InterpolateHalf8(scale6To8(v0), scale6To8(v1)); }
uint8_t InterpolatorAMD::Interpolate8(uint8_t v0, uint8_t v1) const {
return (v0 * 43 + v1 * 21 + 32) >> 6;
}
uint8_t InterpolatorAMD::Interpolate8(uint8_t v0, uint8_t v1) const { return (v0 * 43 + v1 * 21 + 32) >> 6; }
uint8_t InterpolatorAMD::InterpolateHalf8(uint8_t v0, uint8_t v1) const {
return (v0 + v1 + 1) >> 1;
}
uint8_t InterpolatorAMD::InterpolateHalf8(uint8_t v0, uint8_t v1) const { return (v0 + v1 + 1) >> 1; }
// endregion
} // namespace rgbcx

View File

@ -12,8 +12,8 @@
#include <cstring>
#include <type_traits>
#include "BC1/BC1Block.h"
#include "Color.h"
#include "blocks.h"
#include "tables.h"
#include "util.h"

View File

@ -55,7 +55,10 @@
#include <cstdint>
#include "blocks.h"
#include "BC1/BC1Block.h"
#include "BC3/BC3Block.h"
#include "BC4/BC4Block.h"
#include "BC5/BC5Block.h"
#include "interpolator.h"
// By default, the table used to accelerate cluster fit on 4 color blocks uses a 969x128 entry table.

View File

@ -17,7 +17,6 @@
#include <type_traits>
#include <vector>
#include "../blocks.h"
#include "../rgbcx.h"
#include "../rgbcxDecoders.h"
#include "../util.h"
@ -26,6 +25,8 @@
#include "dds_defs.h"
#include "lodepng.h"
using namespace rgbcx;
const int MAX_UBER_LEVEL = 5;
static int print_usage() {
@ -264,9 +265,11 @@ class image_metrics {
const color_quad_u8 &ca = a(x, y);
const color_quad_u8 &cb = b(x, y);
if (!num_channels)
hist[iabs(ca.get_luma() - cb.get_luma())]++;
else {
if (!num_channels) {
// int luma_diff = ;
unsigned index = iabs(ca.get_luma() - cb.get_luma());
hist[index]++;
} else {
for (uint32_t c = 0; c < num_channels; c++) hist[iabs(ca[first_channel + c] - cb[first_channel + c])]++;
}
}

View File

@ -38,6 +38,7 @@ template <typename S> constexpr void Assert6Bit(S x) {
}
template <typename S> constexpr auto iabs(S i) {
static_assert(!std::is_unsigned<S>::value);
using O = typename std::make_unsigned<S>::type;
return (i < 0) ? static_cast<O>(-i) : static_cast<O>(i);
}
@ -103,12 +104,12 @@ template <size_t Size, int Op(int)> constexpr std::array<uint8_t, Size> ExpandAr
}
template <typename S> constexpr S scale8To5(S v) {
v = v * 31 + 128;
return static_cast<S>((v + (v >> 8)) >> 8);
auto v2 = v * 31 + 128;
return static_cast<S>((v2 + (v2 >> 8)) >> 8);
}
template <typename S> constexpr S scale8To6(S v) {
v = v * 63 + 128;
return static_cast<S>((v + (v >> 8)) >> 8);
auto v2 = v * 63 + 128;
return static_cast<S>((v2 + (v2 >> 8)) >> 8);
}
template <typename S> constexpr S scale5To8(S v) {