coloradapter.h

Back to Color adapters

pastel/gfx/color/

// Description: Some adapters for colors

#ifndef PASTELGFX_COLORADAPTER_H
#define PASTELGFX_COLORADAPTER_H

#include "pastel/gfx/color/color.h"

#include "pastel/sys/mytypes.h"
#include "pastel/sys/bit/extract_bits.h"

namespace Pastel
{

    template <typename Adapter>
    class ReverseAdapter
    {
    public:
        using Logical = typename Adapter::Physical;
        using Physical = typename Adapter::Logical;

        ReverseAdapter()
            : adapter_()
        {
        }

        explicit ReverseAdapter(
            const Adapter& adapter)
            : adapter_(adapter)
        {
        }

        Logical convert(const Physical& physical) const
        {
            return adapter_.revert(physical);
        }

        Physical revert(const Logical& logical) const
        {
            return adapter_.convert(logical);
        }

    private:
        Adapter adapter_;
    };

    template <typename Type>
    class IdentityAdapter
    {
    public:
        using Logical = Type;
        using Physical = Type;

        const Logical& convert(const Physical& physical) const
        {
            return physical;
        }

        const Physical& revert(const Logical& logical) const
        {
            return logical;
        }
    };

    class Color_To_Component
    {
    public:
        using Logical = real32;
        using Physical = Color;

        Color_To_Component()
            : component_(0)
        {
        }

        explicit Color_To_Component(
            integer component)
            : component_(component)
        {
            ENSURE1(component >= 0 && component < 3, component);
        }

        Logical convert(const Physical& physical) const
        {
            return physical[component_];
        }

        Physical revert(const Logical& logical) const
        {
            return Physical(logical);
        }

    private:
        integer component_;
    };

    template <typename Real, typename Integer>
    class Integer_To_Real
    {
    public:
        using Logical = Real;
        using Physical = Integer;

        explicit Integer_To_Real(
            integer numbers,
            Real maxValue = 1)
            : numbers_(numbers)
            , maxValue_(maxValue)
        {
        }

        Logical convert(const Physical& physical) const
        {
            return dequantizeUnsigned(physical, numbers_) * maxValue_;
        }

        Physical revert(const Logical& logical) const
        {
            return quantizeUnsigned(logical / maxValue_, numbers_);
        }

    private:
        integer numbers_;
        Real maxValue_;
    };

    template <typename Integer>
    class Integer_To_Bool
    {
    public:
        using Logical = bool;
        using Physical = Integer;

        static Logical convert(const Physical& physical)
        {
            return (physical != 0);
        }

        static Physical revert(const Logical& logical)
        {
            return logical ? 1 : 0;
        }
    };

    class ByteColor_To_Color
    {
    public:
        using Logical = Color;
        using Physical = ByteColor;

        static Logical convert(const Physical& physical)
        {
            return Color(
                dequantizeUnsigned(physical[0], 256),
                dequantizeUnsigned(physical[1], 256),
                dequantizeUnsigned(physical[2], 256));
        }

        static Physical revert(const Logical& logical)
        {
            return ByteColor(
                quantizeUnsigned(logical[0], 256),
                quantizeUnsigned(logical[1], 256),
                quantizeUnsigned(logical[2], 256));
        }
    };

    using ByteColor_Color_Adapter = ReverseAdapter<ByteColor_To_Color>;

    template <typename Integer,
        int RedBits, integer GreenBits, integer BlueBits,
        int RedFrom = 0,
        int GreenFrom = RedFrom + RedBits,
        int BlueFrom = GreenFrom + GreenBits>
    class Integer_To_ByteColor
    {
    public:
        using Logical = ByteColor;
        using Physical = Integer;

        ~Integer_To_ByteColor()
        {
            PASTEL_STATIC_ASSERT(RedFrom >= 0);
            PASTEL_STATIC_ASSERT(GreenFrom >= 0);
            PASTEL_STATIC_ASSERT(BlueFrom >= 0);
            PASTEL_STATIC_ASSERT(RedBits > 0);
            PASTEL_STATIC_ASSERT(GreenBits > 0);
            PASTEL_STATIC_ASSERT(BlueBits > 0);
        }

        static Logical convert(const Physical& physical)
        {
            uint8 red = (uint8)scaleInteger<RedBits, 8>(
                extractBits<RedFrom, RedBits>(physical));
            uint8 green = (uint8)scaleInteger<GreenBits, 8>(
                extractBits<GreenFrom, GreenBits>(physical));
            uint8 blue = (uint8)scaleInteger<BlueBits, 8>(
                extractBits<BlueFrom, BlueBits>(physical));

            return Logical(red, green, blue);
        }

        static Physical revert(const Logical& logical)
        {
            Integer red = scaleInteger<8, RedBits, uint32>(logical[0]);
            Integer green = scaleInteger<8, GreenBits, uint32>(logical[1]);
            Integer blue = scaleInteger<8, BlueBits, uint32>(logical[2]);

            return (red << RedFrom) + (green << GreenFrom) + (blue << BlueFrom);
        }
    };

    template <typename Integer,
        int RedBits, integer GreenBits, integer BlueBits,
        int RedFrom = 0,
        int GreenFrom = RedFrom + RedBits,
        int BlueFrom = GreenFrom + GreenBits>
    class Integer_To_Color
    {
    private:
        static constexpr int RedNumbers = 1 << RedBits;
        static constexpr int GreenNumbers = 1 << GreenBits;
        static constexpr int BlueNumbers = 1 << BlueBits;

    public:
        using Logical = Color;
        using Physical = Integer;

        Integer_To_Color()
        {
        }

        ~Integer_To_Color()
        {
            PASTEL_STATIC_ASSERT(RedFrom >= 0);
            PASTEL_STATIC_ASSERT(GreenFrom >= 0);
            PASTEL_STATIC_ASSERT(BlueFrom >= 0);
            PASTEL_STATIC_ASSERT(RedBits > 0);
            PASTEL_STATIC_ASSERT(GreenBits > 0);
            PASTEL_STATIC_ASSERT(BlueBits > 0);
            PASTEL_STATIC_ASSERT(RedFrom + RedBits <= 32);
            PASTEL_STATIC_ASSERT(GreenFrom + GreenBits <= 32);
            PASTEL_STATIC_ASSERT(BlueFrom + BlueBits <= 32);
        }

        static Logical convert(const Physical& physical)
        {
            return Color(
                dequantizeUnsigned(extractBits<RedFrom, RedBits>(physical), RedNumbers),
                dequantizeUnsigned(extractBits<GreenFrom, GreenBits>(physical), GreenNumbers),
                dequantizeUnsigned(extractBits<BlueFrom, BlueBits>(physical), BlueNumbers));
        }

        static Physical revert(const Logical& logical)
        {
            Integer red = quantizeUnsigned(logical[0], RedNumbers);
            Integer green = quantizeUnsigned(logical[1], GreenNumbers);
            Integer blue = quantizeUnsigned(logical[2], BlueNumbers);

            return (red << RedFrom) + (green << GreenFrom) + (blue << BlueFrom);
        }
    };

    template <typename Integer>
    Color integerToColor(
        const NoDeduction<Integer>& packedColor,
        integer redBits, integer greenBits, integer blueBits,
        integer redFrom, integer greenFrom, integer blueFrom);

    template <typename Integer>
    Color integerToColor(
        const NoDeduction<Integer>& packedColor,
        integer redBits, integer greenBits, integer blueBits);

    template <typename Integer>
    Integer colorToInteger(const Color& color,
        integer redBits, integer greenBits, integer blueBits,
        integer redFrom, integer greenFrom, integer blueFrom);

    template <typename Integer>
    Integer colorToInteger(const Color& color,
        integer redBits, integer greenBits, integer blueBits);

}

#include "pastel/gfx/color/coloradapter.hpp"

#endif