Skip to content

Commit

Permalink
Refactoring: make anything static as possible
Browse files Browse the repository at this point in the history
  • Loading branch information
ledyba-z committed Apr 20, 2022
1 parent 6209c8a commit e88a61d
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 165 deletions.
64 changes: 31 additions & 33 deletions src/avif/img/Conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,45 +31,43 @@ struct ChromaSampler {

namespace detail {

template <typename ConverterFactory, size_t rgbBits, size_t yuvBits, bool isMonoYUV, bool isFullRange>
template <typename Converter, size_t rgbBits, size_t yuvBits, bool isMonoYUV, bool isFullRange>
constexpr void calcYUV(uint16_t const ir, uint16_t const ig, uint16_t const ib, typename avif::img::color::YUV<yuvBits>::Type* dstY, typename avif::img::color::YUV<yuvBits>::Type* dstU, typename avif::img::color::YUV<yuvBits>::Type* dstV) {
using Quantizer = typename avif::img::color::Quantizer<rgbBits, yuvBits, isFullRange>;
using RGBSpec = typename avif::img::color::RGB<rgbBits>;
auto converter = ConverterFactory::create();
float const r = static_cast<float>(ir) / RGBSpec::max;
float const g = static_cast<float>(ig) / RGBSpec::max;
float const b = static_cast<float>(ib) / RGBSpec::max;

if (isMonoYUV) {
float y = 0;
converter.calcYUV(r,g,b, &y, nullptr, nullptr);
Converter::calcYUV(r,g,b, &y, nullptr, nullptr);
*dstY = Quantizer::quantizeLuma(y);
} else {
float y = {};
float u = {};
float v = {};
converter.calcYUV(r,g,b, &y, &u, &v);
Converter::calcYUV(r,g,b, &y, &u, &v);
*dstY = Quantizer::quantizeLuma(y);
*dstU = Quantizer::quantizeChroma(u);
*dstV = Quantizer::quantizeChroma(v);
}
}

template <typename ConverterFactory, size_t rgbBits, size_t yuvBits, bool isMonoYUV, bool isFullRange>
template <typename Converter, size_t rgbBits, size_t yuvBits, bool isMonoYUV, bool isFullRange>
constexpr std::tuple<typename avif::img::color::RGB<rgbBits>::Type, typename avif::img::color::RGB<rgbBits>::Type, typename avif::img::color::RGB<rgbBits>::Type> calcRGB(typename avif::img::color::YUV<yuvBits>::Type const* srcY, typename avif::img::color::YUV<yuvBits>::Type const* srcU, typename avif::img::color::YUV<yuvBits>::Type const* srcV) {
using avif::img::color::clamp;
using Quantizer = typename avif::img::color::Quantizer<rgbBits, yuvBits, isFullRange>;
using RGBSpec = typename avif::img::color::RGB<rgbBits>;
using YUVSpec = typename avif::img::color::YUV<yuvBits>;
auto converter = ConverterFactory::create();

using RGBType = typename RGBSpec::Type;

auto const y = Quantizer::dequantizeLuma(*srcY);
auto const u = isMonoYUV ? 0.0f : Quantizer::dequantizeChroma(*srcU);
auto const v = isMonoYUV ? 0.0f : Quantizer::dequantizeChroma(*srcV);

auto const [r, g, b] = converter.calcRGB(y, u, v);
auto const [r, g, b] = Converter::calcRGB(y, u, v);

auto const ir = static_cast<RGBType>(clamp<int>(static_cast<int>(std::round(r * RGBSpec::max)), 0, RGBSpec::max));
auto const ig = static_cast<RGBType>(clamp<int>(static_cast<int>(std::round(g * RGBSpec::max)), 0, RGBSpec::max));
Expand All @@ -78,7 +76,7 @@ constexpr std::tuple<typename avif::img::color::RGB<rgbBits>::Type, typename avi
}

// MonochromeYUV version
template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool fromMonoRGB, bool isFullRange>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool fromMonoRGB, bool isFullRange>
void constexpr convertFromRGB(size_t width, size_t height, uint8_t bytesPerPixel, uint8_t const* src, size_t const stride, uint8_t* const dstY, size_t const strideY) {
using avif::img::color::clamp;
using RGBSpec = typename avif::img::color::RGB<rgbBits>;
Expand All @@ -95,12 +93,12 @@ void constexpr convertFromRGB(size_t width, size_t height, uint8_t bytesPerPixel
for (size_t x = 0; x < width; ++x) {
if(fromMonoRGB) {
uint16_t const mono = reinterpret_cast<RGBType const *>(ptr)[0];
calcYUV<ConverterFactory, rgbBits, yuvBits, true, isFullRange>(mono, mono, mono, &ptrY[x], nullptr, nullptr);
calcYUV<Converter, rgbBits, yuvBits, true, isFullRange>(mono, mono, mono, &ptrY[x], nullptr, nullptr);
} else {
uint16_t const r = reinterpret_cast<RGBType const *>(ptr)[0];
uint16_t const g = reinterpret_cast<RGBType const *>(ptr)[1];
uint16_t const b = reinterpret_cast<RGBType const *>(ptr)[2];
calcYUV<ConverterFactory, rgbBits, yuvBits, true, isFullRange>(r, g, b, &ptrY[x], nullptr, nullptr);
calcYUV<Converter, rgbBits, yuvBits, true, isFullRange>(r, g, b, &ptrY[x], nullptr, nullptr);
}
ptr += bytesPerPixel;
}
Expand All @@ -109,7 +107,7 @@ void constexpr convertFromRGB(size_t width, size_t height, uint8_t bytesPerPixel
}
}

template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool fromMonoRGB, bool isFullRange, bool subX, bool subY>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool fromMonoRGB, bool isFullRange, bool subX, bool subY>
void constexpr convertFromRGB(size_t width, size_t height, uint8_t bytesPerPixel, uint8_t const* src, size_t const stride, uint8_t* const dstY, size_t const strideY, uint8_t* const dstU, size_t const strideU, uint8_t* const dstV, size_t const strideV) {
using avif::img::color::clamp;
using RGBSpec = typename avif::img::color::RGB<rgbBits>;
Expand All @@ -133,12 +131,12 @@ void constexpr convertFromRGB(size_t width, size_t height, uint8_t bytesPerPixel
for (size_t x = 0; x < width; ++x) {
if(fromMonoRGB) {
uint16_t const mono = reinterpret_cast<RGBType const *>(ptr)[0];
calcYUV<ConverterFactory, rgbBits, yuvBits, false, isFullRange>(mono, mono, mono, &ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
calcYUV<Converter, rgbBits, yuvBits, false, isFullRange>(mono, mono, mono, &ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
} else {
uint16_t const r = reinterpret_cast<RGBType const *>(ptr)[0];
uint16_t const g = reinterpret_cast<RGBType const *>(ptr)[1];
uint16_t const b = reinterpret_cast<RGBType const *>(ptr)[2];
calcYUV<ConverterFactory, rgbBits, yuvBits, false, isFullRange>(r, g, b, &ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
calcYUV<Converter, rgbBits, yuvBits, false, isFullRange>(r, g, b, &ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
}
ptr += bytesPerPixel;
}
Expand All @@ -150,7 +148,7 @@ void constexpr convertFromRGB(size_t width, size_t height, uint8_t bytesPerPixel
}

// MonochromeYUV version
template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange>
void constexpr convertFromYUV(size_t width, size_t height, uint8_t bytesPerPixel, uint8_t* dst, size_t stride, uint8_t const* srcY, size_t strideY) {
using RGBSpec = typename avif::img::color::RGB<rgbBits>;
using YUVSpec = typename avif::img::color::YUV<yuvBits>;
Expand All @@ -166,12 +164,12 @@ void constexpr convertFromYUV(size_t width, size_t height, uint8_t bytesPerPixel
for (size_t x = 0; x < width; ++x) {
if(toMonoRGB) {
RGBType& mono = reinterpret_cast<RGBType*>(ptr)[0];
std::tie(mono, mono, mono) = calcRGB<ConverterFactory, rgbBits, yuvBits, true, isFullRange>(&ptrY[x], nullptr, nullptr);
std::tie(mono, mono, mono) = calcRGB<Converter, rgbBits, yuvBits, true, isFullRange>(&ptrY[x], nullptr, nullptr);
} else {
RGBType& r = reinterpret_cast<RGBType*>(ptr)[0];
RGBType& g = reinterpret_cast<RGBType*>(ptr)[1];
RGBType& b = reinterpret_cast<RGBType*>(ptr)[2];
std::tie(r,g,b) = calcRGB<ConverterFactory, rgbBits, yuvBits, true, isFullRange>(&ptrY[x], nullptr, nullptr);
std::tie(r,g,b) = calcRGB<Converter, rgbBits, yuvBits, true, isFullRange>(&ptrY[x], nullptr, nullptr);
}
ptr += bytesPerPixel;
}
Expand All @@ -180,7 +178,7 @@ void constexpr convertFromYUV(size_t width, size_t height, uint8_t bytesPerPixel
}
}

template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange, bool subX, bool subY>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange, bool subX, bool subY>
void constexpr convertFromYUV(size_t width, size_t height, uint8_t bytesPerPixel, uint8_t* dst, size_t stride, uint8_t const* srcY, size_t strideY, uint8_t const* srcU, size_t strideU, uint8_t const* srcV, size_t strideV) {
using RGBSpec = typename avif::img::color::RGB<rgbBits>;
using YUVSpec = typename avif::img::color::YUV<yuvBits>;
Expand All @@ -202,12 +200,12 @@ void constexpr convertFromYUV(size_t width, size_t height, uint8_t bytesPerPixel
for (size_t x = 0; x < width; ++x) {
if(toMonoRGB) {
RGBType& mono = reinterpret_cast<RGBType*>(ptr)[0];
std::tie(mono, mono, mono) = calcRGB<ConverterFactory, rgbBits, yuvBits, false, isFullRange>(&ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
std::tie(mono, mono, mono) = calcRGB<Converter, rgbBits, yuvBits, false, isFullRange>(&ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
} else {
RGBType& r = reinterpret_cast<RGBType*>(ptr)[0];
RGBType& g = reinterpret_cast<RGBType*>(ptr)[1];
RGBType& b = reinterpret_cast<RGBType*>(ptr)[2];
std::tie(r,g,b) = calcRGB<ConverterFactory, rgbBits, yuvBits, false, isFullRange>(&ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
std::tie(r,g,b) = calcRGB<Converter, rgbBits, yuvBits, false, isFullRange>(&ptrY[x], sampler.pixelInLine(ptrU, x), sampler.pixelInLine(ptrV, x));
}
ptr += bytesPerPixel;
}
Expand All @@ -220,29 +218,29 @@ void constexpr convertFromYUV(size_t width, size_t height, uint8_t bytesPerPixel

}

template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange>
struct FromRGB final {
static void toI400(Image<rgbBits>& src, uint8_t* dstY, size_t strideY) {
detail::convertFromRGB<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY);
detail::convertFromRGB<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY);
}
static void toI444(Image<rgbBits> const& src, uint8_t* dstY, size_t strideY, uint8_t* dstU, size_t strideU, uint8_t* dstV, size_t strideV) {
detail::convertFromRGB<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange, false, false>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY, dstU, strideU, dstV, strideV);
detail::convertFromRGB<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange, false, false>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY, dstU, strideU, dstV, strideV);
}
static void toI422(Image<rgbBits> const& src, uint8_t* dstY, size_t strideY, uint8_t* dstU, size_t strideU, uint8_t* dstV, size_t strideV){
detail::convertFromRGB<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange, true, false>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY, dstU, strideU, dstV, strideV);
detail::convertFromRGB<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange, true, false>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY, dstU, strideU, dstV, strideV);
}
static void toI420(Image<rgbBits> const& src, uint8_t* dstY, size_t strideY, uint8_t* dstU, size_t strideU, uint8_t* dstV, size_t strideV){
detail::convertFromRGB<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange, true, true>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY, dstU, strideU, dstV, strideV);
detail::convertFromRGB<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange, true, true>(src.width(), src.height(), src.bytesPerPixel(), src.data(), src.stride(), dstY, strideY, dstU, strideU, dstV, strideV);
}
};

template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool isFullRange>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool isFullRange>
struct FromAlpha final {
static void toI400(Image<rgbBits>& src, uint8_t* dstY, size_t strideY) {
switch(src.pixelOrder()) {
case avif::img::PixelOrder::MonoA:
case avif::img::PixelOrder::RGBA:
detail::convertFromRGB<ConverterFactory, rgbBits, yuvBits, true, isFullRange>(src.width(), src.height(), src.bytesPerPixel(), src.data() + (src.numComponents() - 1) * src.bytesPerComponent(), src.stride(), dstY, strideY);
detail::convertFromRGB<Converter, rgbBits, yuvBits, true, isFullRange>(src.width(), src.height(), src.bytesPerPixel(), src.data() + (src.numComponents() - 1) * src.bytesPerComponent(), src.stride(), dstY, strideY);
break;
case avif::img::PixelOrder::Mono:
throw std::domain_error("Cannot separate Alpha from Mono image.");
Expand All @@ -252,28 +250,28 @@ struct FromAlpha final {
}
};

template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool toMonoRGB, bool isFullRange>
struct ToRGB final {
static void fromI400(Image<rgbBits>& dst, uint8_t* srcY, size_t strideY) {
detail::convertFromYUV<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY);
detail::convertFromYUV<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY);
}
static void fromI444(Image<rgbBits>& dst, uint8_t* srcY, size_t strideY, uint8_t* srcU, size_t strideU, uint8_t* srcV, size_t strideV) {
detail::convertFromYUV<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange, false, false>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY, srcU, strideU, srcV, strideV);
detail::convertFromYUV<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange, false, false>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY, srcU, strideU, srcV, strideV);
}
static void fromI422(Image<rgbBits>& dst, uint8_t* srcY, size_t strideY, uint8_t* srcU, size_t strideU, uint8_t* srcV, size_t strideV){
detail::convertFromYUV<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange, true, false>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY, srcU, strideU, srcV, strideV);
detail::convertFromYUV<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange, true, false>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY, srcU, strideU, srcV, strideV);
}
static void fromI420(Image<rgbBits>& dst, uint8_t* srcY, size_t strideY, uint8_t* srcU, size_t strideU, uint8_t* srcV, size_t strideV){
detail::convertFromYUV<ConverterFactory, rgbBits, yuvBits, toMonoRGB, isFullRange, true, true>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY, srcU, strideU, srcV, strideV);
detail::convertFromYUV<Converter, rgbBits, yuvBits, toMonoRGB, isFullRange, true, true>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data(), dst.stride(), srcY, strideY, srcU, strideU, srcV, strideV);
}
};
template <typename ConverterFactory, uint8_t rgbBits, uint8_t yuvBits, bool isFullRange>
template <typename Converter, uint8_t rgbBits, uint8_t yuvBits, bool isFullRange>
struct ToAlpha final {
static void fromI400(Image<rgbBits>& dst, uint8_t* srcY, size_t strideY) {
switch(dst.pixelOrder()) {
case avif::img::PixelOrder::MonoA:
case avif::img::PixelOrder::RGBA:
detail::convertFromYUV<ConverterFactory, rgbBits, yuvBits, true, isFullRange>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data() + (dst.numComponents() - 1) * dst.bytesPerComponent(), dst.stride(), srcY, strideY);
detail::convertFromYUV<Converter, rgbBits, yuvBits, true, isFullRange>(dst.width(), dst.height(), dst.bytesPerPixel(), dst.data() + (dst.numComponents() - 1) * dst.bytesPerComponent(), dst.stride(), srcY, strideY);
break;
case avif::img::PixelOrder::Mono:
throw std::domain_error("Cannot store Alpha to Mono image.");
Expand Down
Loading

0 comments on commit e88a61d

Please sign in to comment.