Repository: SerenityOS/serenity
File: Userland/Libraries/LibGfx/ImageFormats/BilevelImage.h (C/C++)

Code before:

enum class DitheringAlgorithm {
    None,

    Bayer2x2,
    Bayer4x4,
    Bayer8x8,

    FloydSteinberg,

    // FIXME: Add Atkinson, BlueNoise, Hilbert / Peano space-filling, ...
    // https://surma.dev/things/ditherpunk/
    // https://tannerhelland.com/2012/12/28/dithering-eleven-algorithms-source-code.html
};

class BilevelImage {
public:
    static ErrorOr<NonnullOwnPtr<BilevelImage>> create(size_t width, size_t height);
    static ErrorOr<NonnullOwnPtr<BilevelImage>> create_from_byte_buffer(ByteBuffer bitmap, size_t width, size_t height);
    static ErrorOr<NonnullOwnPtr<BilevelImage>> create_from_bitmap(Gfx::Bitmap const& bitmap, DitheringAlgorithm dithering_algorithm);

    bool get_bit(size_t x, size_t y) const;
    void set_bit(size_t x, size_t y, bool b);
    void fill(bool b);

    // This is binary compatible with JBIG2::CombinationOperator.
    enum class BlendType : u8 {
        Or = 0,
        And = 1,
        Xor = 2,
        XNor = 3,
        Replace = 4,
    };

    void blend_into(BilevelImage& out, IntPoint position, BlendType) const;

    ErrorOr<NonnullOwnPtr<BilevelImage>> subbitmap(Gfx::IntRect const& rect) const;

    ErrorOr<NonnullRefPtr<Gfx::Bitmap>> to_gfx_bitmap() const;
    ErrorOr<ByteBuffer> to_byte_buffer() const;

    size_t width() const { return m_width; }
    size_t height() const { return m_height; }

    Bytes bytes() { return m_bits.bytes(); }

private:
    BilevelImage(ByteBuffer, size_t width, size_t height, size_t pitch);

    ByteBuffer m_bits;
    size_t m_width { 0 };

Review comment (suggestion):
nit: i'd add a `blend_type_from_combination_operator(op) { switch(op) { case CO::Or: return BT::Or; …]` in the jbig2 code instead of static_casting and requiring matching enum values

Code after:

enum class DitheringAlgorithm {
    None,

    Bayer2x2,
    Bayer4x4,
    Bayer8x8,

    FloydSteinberg,

    // FIXME: Add Atkinson, BlueNoise, Hilbert / Peano space-filling, ...
    // https://surma.dev/things/ditherpunk/
    // https://tannerhelland.com/2012/12/28/dithering-eleven-algorithms-source-code.html
};

class BilevelImage {
public:
    static ErrorOr<NonnullOwnPtr<BilevelImage>> create(size_t width, size_t height);
    static ErrorOr<NonnullOwnPtr<BilevelImage>> create_from_byte_buffer(ByteBuffer bitmap, size_t width, size_t height);
    static ErrorOr<NonnullOwnPtr<BilevelImage>> create_from_bitmap(Gfx::Bitmap const& bitmap, DitheringAlgorithm dithering_algorithm);

    bool get_bit(size_t x, size_t y) const;
    void set_bit(size_t x, size_t y, bool b);
    void fill(bool b);

    enum class CompositionType : u8 {
        Or = 0,
        And = 1,
        Xor = 2,
        XNor = 3,
        Replace = 4,
    };

    void composite_onto(BilevelImage& out, IntPoint position, CompositionType) const;

    ErrorOr<NonnullOwnPtr<BilevelImage>> subbitmap(Gfx::IntRect const& rect) const;

    ErrorOr<NonnullRefPtr<Gfx::Bitmap>> to_gfx_bitmap() const;
    ErrorOr<ByteBuffer> to_byte_buffer() const;

    size_t width() const { return m_width; }
    size_t height() const { return m_height; }

    Bytes bytes() { return m_bits.bytes(); }

private:
    BilevelImage(ByteBuffer, size_t width, size_t height, size_t pitch);

    template<CompositionType>
    void composite_onto(BilevelImage& out, IntPoint position) const;