Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding some palette classes #70

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
66 changes: 56 additions & 10 deletions Porytiles-2.x/include/porytiles/Color/Bgr15.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@

#include <cstdint>
#include <iostream>
#include <string>

#include "porytiles/Color/Rgba32.h"
#include <porytiles/Color/Rgba32.h>

namespace porytiles::color {

/**
* @brief Value object representing a color in 15-bit BGR format.
*
* @details
* TODO 2.x : fill in explanation about BGR format, 5 bits per color, top bit unused, etc.
* The 15-bit BGR format represents a color with three 5-bit channels: one channel for blue, green,
* and red respectively. Internally, a Bgr15 is representing using a 16-bit integer, with the top
* bit left unused. Bgr15 is the preferred color format for the Game Boy Advance's palette RAM. The
* BGR format has no concept of transparency, so Bgr15's @link Bgr15::computeAlphaComponent
* computeAlphaComponent @endlink implementation simply returns @link ALPHA_OPAQUE @endlink.
*/
class Bgr15 : public Color {
class Bgr15 {
std::uint16_t bgr;

public:
Expand Down Expand Up @@ -62,7 +67,7 @@ class Bgr15 : public Color {
*
* @return The 8-bit red component derived from the 15-bit BGR value.
*/
[[nodiscard]] std::uint8_t computeRedComponent() const override;
[[nodiscard]] std::uint8_t computeRedComponent() const;

/**
* @brief Computes the green component from the 15-bit BGR color value.
Expand All @@ -73,7 +78,7 @@ class Bgr15 : public Color {
*
* @return The 8-bit green component derived from the 15-bit BGR value.
*/
[[nodiscard]] std::uint8_t computeGreenComponent() const override;
[[nodiscard]] std::uint8_t computeGreenComponent() const;

/**
* @brief Computes the blue component from the 15-bit BGR color value.
Expand All @@ -84,7 +89,7 @@ class Bgr15 : public Color {
*
* @return The 8-bit blue component derived from the 15-bit BGR value.
*/
[[nodiscard]] std::uint8_t computeBlueComponent() const override;
[[nodiscard]] std::uint8_t computeBlueComponent() const;

/**
* @brief Computes the alpha component, which will always be opaque.
Expand All @@ -95,17 +100,58 @@ class Bgr15 : public Color {
*
* @return The opaque alpha component.
*/
[[nodiscard]] std::uint8_t computeAlphaComponent() const override
[[nodiscard]] std::uint8_t computeAlphaComponent() const
{
return Rgba32::ALPHA_OPAQUE;
return ALPHA_OPAQUE;
}

/**
* @brief Converts the Color to a JASC-PAL formatted string.
*
* @details
* This method converts the red, green, and blue components of the Color object into a
* space-separated string format commonly used in JASC-PAL color palette files. JASC-PAL files
* typically do not include an alpha channel value, so that value is omitted from the string
* returned here.
*
* @return A string representation of the color in JASC-PAL format.
*/
[[nodiscard]] std::string toJascString() const
{
return std::to_string(computeRedComponent()) + " " +
std::to_string(computeGreenComponent()) + " " +
std::to_string(computeBlueComponent());
}

/**
* @brief Equality operator for Bgr15 objects.
*
* @details
* Compares two Bgr15 objects to determine whether their 15-bit BGR values are equal. The
* comparison uses the raw value but shifts off the top bit, since this bit is unused in BGR15
* format. Garbage bit values here should not affect logical equality.
*
* @param lhs The left-hand side Bgr15 object to compare.
* @param rhs The right-hand side Bgr15 object to compare.
* @return True if the 15-bit BGR values of both Bgr15 objects are equal, false otherwise.
*/
friend bool operator==(const Bgr15 &lhs, const Bgr15 &rhs)
{
// TODO 2.x : make this ignore the top bit of the raw value, since that bit is unused
return lhs.getRawValue() == rhs.getRawValue();
return lhs.getRawValue() << 1 == rhs.getRawValue() << 1;
}

/**
* @brief Inequality operator for Bgr15 objects.
*
* @details
* Compares two Bgr15 objects to determine whether their 15-bit BGR values are not equal.
* Currently, it compares the raw 16-bit values, but it should be updated to ignore the top
* unused bit.
*
* @param lhs The left-hand side Bgr15 object to compare.
* @param rhs The right-hand side Bgr15 object to compare.
* @return True if the 15-bit BGR values of both Bgr15 objects are not equal, false otherwise.
*/
friend bool operator!=(const Bgr15 &lhs, const Bgr15 &rhs)
{
return !(lhs == rhs);
Expand Down
27 changes: 11 additions & 16 deletions Porytiles-2.x/include/porytiles/Color/Color.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define PORYTILES_COLOR_COLOR_H

#include <cstdint>
#include <iostream>
#include <string>

namespace porytiles::color {

Expand All @@ -18,6 +18,16 @@ namespace porytiles::color {
*/
class Color {
public:
/**
* @brief Completely transparent alpha channel value.
*/
static constexpr std::uint8_t ALPHA_TRANSPARENT = 0;

/**
* @brief Completely opaque alpha channel value.
*/
static constexpr std::uint8_t ALPHA_OPAQUE = 0xff;

virtual ~Color() = default;

/**
Expand Down Expand Up @@ -48,21 +58,6 @@ class Color {
*/
[[nodiscard]] virtual std::uint8_t computeAlphaComponent() const = 0;

/**
* @brief Converts the Color to a JASC-PAL formatted string.
*
* @details
* This method converts the red, green, and blue components of the Color object into a
* space-separated string format commonly used in JASC-PAL color palette files.
*
* @return A string representation of the color in JASC-PAL format.
*/
[[nodiscard]] virtual std::string toJascString() const
{
return std::to_string(computeRedComponent()) + " " +
std::to_string(computeGreenComponent()) + " " +
std::to_string(computeBlueComponent());
}

/**
* @brief Compares two Color objects for equality.
Expand Down
21 changes: 21 additions & 0 deletions Porytiles-2.x/include/porytiles/Color/ColorConverter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef PORYTILES_COLOR_COLOR_CONVERTER_H
#define PORYTILES_COLOR_COLOR_CONVERTER_H

#include <porytiles/Color/RGBLike.h>

namespace porytiles::color {

/**
* @brief Service interface for a converter service that transforms one Color implementation into a
* different Color implementation.
*/
template<RGBLike T, RGBLike U>
class ColorConverter {
public:
virtual ~ColorConverter() = default;
[[nodiscard]] virtual U convert(const T&) const = 0;
};

} // namespace porytiles::color

#endif // PORYTILES_COLOR_COLOR_CONVERTER_H
27 changes: 0 additions & 27 deletions Porytiles-2.x/include/porytiles/Color/ColorConverters.h

This file was deleted.

10 changes: 0 additions & 10 deletions Porytiles-2.x/include/porytiles/Color/NamespaceDoc.h

This file was deleted.

48 changes: 48 additions & 0 deletions Porytiles-2.x/include/porytiles/Color/Palette.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef PORYTILES_COLOR_PALETTE_H
#define PORYTILES_COLOR_PALETTE_H

#include <vector>

#include <porytiles/Color/ColorConverter.h>
#include <porytiles/Color/RGBLike.h>

namespace porytiles::color {

template<RGBLike T>
class Palette {
std::vector<T> colors;

public:
explicit Palette(std::size_t capacity) {
colors.reserve(capacity);
}

[[nodiscard]] std::size_t getCapacity() const {
return colors.capacity();
}

[[nodiscard]] std::size_t getSize() const {
return colors.size();
}

const T& at(std::size_t index) const {
return colors.at(index);
}

void pushColor(const T& color) {
if (getSize() >= getCapacity()) {
throw std::out_of_range("porytiles::color::Palette::pushColor");
}
colors.push_back(color);
}

template<RGBLike U>
void foo(const ColorConverter<U, T>& converter, U color) {
auto myColor = converter.convert(color);
std::cout << ":" << myColor.toJascString() << std::endl;
}
};

} // namespace porytiles::color

#endif // PORYTILES_COLOR_PALETTE_H
51 changes: 51 additions & 0 deletions Porytiles-2.x/include/porytiles/Color/RGBLike.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef PORYTILES_COLOR_RGBLIKE_H
#define PORYTILES_COLOR_RGBLIKE_H

#include <concepts>
#include <cstdint>
#include <string>

namespace porytiles::color {

/**
* @brief An RGBLike should match any type which can behave like an RGBA format color.
*
* @details
* The Porytiles library is color implementation agnostic. That is, it only needs a color to conform
* to this simple concept. The underlying color implementation is irrelevant, as most color
* representations can be converted into red, green, and blue channels via a simple formula.
* Porytiles provides a few RGBLike compliant implementations that may be useful, but users of the
* Porytiles library may also implement their own if they have a specific use-case.
*/
template <typename T>
concept RGBLike = requires(T t) {
{
t.computeRedComponent()
} -> std::same_as<std::uint8_t>;
{
t.computeGreenComponent()
} -> std::same_as<std::uint8_t>;
{
t.computeBlueComponent()
} -> std::same_as<std::uint8_t>;
{
t.computeAlphaComponent()
} -> std::same_as<std::uint8_t>;
{
t.toJascString()
} -> std::same_as<std::string>;
};

/**
* @brief Completely transparent alpha channel value.
*/
constexpr std::uint8_t ALPHA_TRANSPARENT = 0;

/**
* @brief Completely opaque alpha channel value.
*/
constexpr std::uint8_t ALPHA_OPAQUE = 0xff;

} // namespace porytiles::color

#endif // PORYTILES_COLOR_RGBLIKE_H
Loading
Loading