<commit_before>#include <boost/test/unit_test.hpp>

#include "Image.hpp"
#include "BitstreamGeneric.hpp"
#include "JpegSegments.hpp"

int add(int i, int j) { return i+j; }

#define CHECK_CLOSE(left, right) BOOST_CHECK_CLOSE(left, right, 0.1)

BOOST_AUTO_TEST_CASE(test_add) {
    // seven ways to detect and report the same error:
    BOOST_CHECK(add(2, 2) == 4);        // #1 continues on error

    BOOST_REQUIRE(add(2, 2) == 4);      // #2 throws on error

    if (add(2, 2) != 4)
        BOOST_ERROR("Ouch...");            // #3 continues on error

    if (add(2, 2) != 4)
        BOOST_FAIL("Ouch...");             // #4 throws on error

    if (add(2, 2) != 4) throw "Ouch..."; // #5 throws on error

    BOOST_CHECK_MESSAGE(add(2, 2) == 4,  // #6 continues on error
                        "add(..) result: " << add(2, 2));

    BOOST_CHECK_EQUAL(add(2, 2), 4);	  // #7 continues on error
}

BOOST_AUTO_TEST_CASE(image_loading_test) {
    auto image = loadPPM("res/tester_p3.ppm");
    BOOST_CHECK(image.R(0, 0) == 0);
    BOOST_CHECK(image.G(0, 0) == 0);
    BOOST_CHECK(image.B(0, 0) == 0);

    BOOST_CHECK(image.R(0, 3) == 15);
    BOOST_CHECK(image.G(0, 3) == 0);
    BOOST_CHECK(image.B(0, 3) == 15);

    BOOST_CHECK(image.R(2, 2) == 0);
    BOOST_CHECK(image.G(2, 2) == 15);
    BOOST_CHECK(image.B(2, 2) == 7);

    BOOST_CHECK(image.R(0, 0) == 0);
    BOOST_CHECK(image.G(0, 0) == 0);
    BOOST_CHECK(image.B(0, 0) == 0);

    // out of bounds indexing
    BOOST_CHECK(image.R(7, 0) == 15);
    BOOST_CHECK(image.G(7, 0) == 0);
    BOOST_CHECK(image.B(7, 0) == 15);

    BOOST_CHECK(image.R(0, 7) == 15);
    BOOST_CHECK(image.G(0, 7) == 0);
    BOOST_CHECK(image.B(0, 7) == 15);

    BOOST_CHECK(image.R(1, 7) == 0);
    BOOST_CHECK(image.G(1, 7) == 0);
    BOOST_CHECK(image.B(1, 7) == 0);

    BOOST_CHECK(image.R(7, 1) == 0);
    BOOST_CHECK(image.G(7, 1) == 0);
    BOOST_CHECK(image.B(7, 1) == 0);

    BOOST_CHECK(image.R(7, 7) == 0);
    BOOST_CHECK(image.G(7, 7) == 0);
    BOOST_CHECK(image.B(7, 7) == 0);
}

BOOST_AUTO_TEST_CASE(image_color_conv_test) {
    auto image = loadPPM("res/tester_p3.ppm");

    auto YCbCr_image = image.convertToColorSpace(Image::YCbCr);
    CHECK_CLOSE(YCbCr_image.Y(0, 3), 6.1949);
    CHECK_CLOSE(YCbCr_image.Cb(0, 3), 132.9695);
    CHECK_CLOSE(YCbCr_image.Cr(0, 3), 134.2805);

    CHECK_CLOSE(YCbCr_image. Y(1, 1), 9.6030);
    CHECK_CLOSE(YCbCr_image.Cb(1, 1), 126.5319);
    CHECK_CLOSE(YCbCr_image.Cr(1, 1), 121.1519);

    // converting from YCbCr to YCbCr doesn't do a thing!
    YCbCr_image = image.convertToColorSpace(Image::YCbCr);
    CHECK_CLOSE(YCbCr_image.Y(0, 3), 6.1949);
    CHECK_CLOSE(YCbCr_image.Cb(0, 3), 132.9695);
    CHECK_CLOSE(YCbCr_image.Cr(0, 3), 134.2805);

    auto rgb_image = image.convertToColorSpace(Image::RGB);
    CHECK_CLOSE(rgb_image.R(0, 3), 15);
    CHECK_CLOSE(rgb_image.G(0, 3), 0);
    CHECK_CLOSE(rgb_image.B(0, 3), 15);

    CHECK_CLOSE(rgb_image.R(1, 1), 0);
    CHECK_CLOSE(rgb_image.G(1, 1), 15);
    CHECK_CLOSE(rgb_image.B(1, 1), 7);
}

BOOST_AUTO_TEST_CASE(image_subsampling_test)
{
    auto image_orig = loadPPM("res/tester_p3.ppm");

    {
        auto image = image_orig;
        image.applySubsampling(Image::S444);
        BOOST_CHECK_EQUAL(image.B.size2(), 8);
        BOOST_CHECK_EQUAL(image.B.size1(), 8);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S422);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 8);

        // B channel:
        // 0 0 
        // 0 0
        // 0 7
        // 15 0
        BOOST_CHECK_EQUAL(image.B(2, 0), 0);
        BOOST_CHECK_EQUAL(image.B(2, 1), 7);
        BOOST_CHECK_EQUAL(image.B(3, 0), 15);
        BOOST_CHECK_EQUAL(image.B(3, 1), 0);

        // G channel:
        // 0 0 
        // 0 0
        // 0 15
        // 0 0
        BOOST_CHECK_EQUAL(image.G(2, 0), 0);
        BOOST_CHECK_EQUAL(image.G(2, 1), 15);
        BOOST_CHECK_EQUAL(image.G(3, 0), 0);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S411);
        BOOST_CHECK_EQUAL(image.B.size2(), 2);
        BOOST_CHECK_EQUAL(image.B.size1(), 8);

        // B channel:
        // 0
        // 0
        // 0
        // 15
        BOOST_CHECK_EQUAL(image.B(2, 0), 0);
        BOOST_CHECK_EQUAL(image.B(3, 0), 15);

        // G channel:
        // 0
        // 0
        // 0
        // 0
        BOOST_CHECK_EQUAL(image.G(2, 0), 0);
        BOOST_CHECK_EQUAL(image.G(3, 0), 0);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S420);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 4);
        
        // B channel:
        // 0 0
        // 0 7
        BOOST_CHECK_EQUAL(image.B(1, 0), 0);
        BOOST_CHECK_EQUAL(image.B(1, 1), 7);

        // G channel:
        // 0 0
        // 0 15
        BOOST_CHECK_EQUAL(image.G(1, 0), 0);
        BOOST_CHECK_EQUAL(image.G(1, 1), 15);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S420_m);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 4);
        
        // B channel:
        // 1 3
        // 3 1
        BOOST_CHECK_EQUAL(image.B(0, 0), 1);
        BOOST_CHECK_EQUAL(image.B(1, 0), 3);
        BOOST_CHECK_EQUAL(image.B(0, 1), 3);
        BOOST_CHECK_EQUAL(image.B(1, 1), 1);

        // G channel:
        // 3 0
        // 0 3
        BOOST_CHECK_EQUAL(image.G(0, 0), 3);
        BOOST_CHECK_EQUAL(image.G(1, 0), 0);
        BOOST_CHECK_EQUAL(image.G(0, 1), 0);
        BOOST_CHECK_EQUAL(image.G(1, 1), 3);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S420_lm);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 4);
        
        // B channel:
        // 0 0
        // 7 3
        BOOST_CHECK_EQUAL(image.B(0, 0), 0);
        BOOST_CHECK_EQUAL(image.B(0, 1), 0);
        BOOST_CHECK_EQUAL(image.B(1, 0), 7);
        BOOST_CHECK_EQUAL(image.B(1, 1), 3);

        // G channel:
        // 0 0
        // 0 7
        BOOST_CHECK_EQUAL(image.G(0, 0), 0);
        BOOST_CHECK_EQUAL(image.G(1, 0), 0);
        BOOST_CHECK_EQUAL(image.G(0, 1), 0);
        BOOST_CHECK_EQUAL(image.G(1, 1), 7);
    }
}

BOOST_AUTO_TEST_CASE(jpeg_segments_test)
{
    // playing with byte memory
    {
        Segment::Bytes<5> bytes{ { 0 } };
        Segment::set(bytes, { 1, 2, 3, 4, 255 });

        BOOST_CHECK_EQUAL(5, sizeof(bytes));

        BOOST_CHECK_EQUAL(bytes[0], 1);
        BOOST_CHECK_EQUAL(bytes[1], 2);
        BOOST_CHECK_EQUAL(bytes[2], 3);
        BOOST_CHECK_EQUAL(bytes[3], 4);
        BOOST_CHECK_EQUAL(bytes[4], 255);

        Byte copy[] = { 'J', 'F', 'I', 'F', '\0' };
        memcpy(bytes.data(), copy, 5);<commit_msg>fixed some subsampling tests<commit_after>#include <boost/test/unit_test.hpp>

#include "Image.hpp"
#include "BitstreamGeneric.hpp"
#include "JpegSegments.hpp"

int add(int i, int j) { return i+j; }

#define CHECK_CLOSE(left, right) BOOST_CHECK_CLOSE(left, right, 0.1)

BOOST_AUTO_TEST_CASE(test_add) {
    // seven ways to detect and report the same error:
    BOOST_CHECK(add(2, 2) == 4);        // #1 continues on error

    BOOST_REQUIRE(add(2, 2) == 4);      // #2 throws on error

    if (add(2, 2) != 4)
        BOOST_ERROR("Ouch...");            // #3 continues on error

    if (add(2, 2) != 4)
        BOOST_FAIL("Ouch...");             // #4 throws on error

    if (add(2, 2) != 4) throw "Ouch..."; // #5 throws on error

    BOOST_CHECK_MESSAGE(add(2, 2) == 4,  // #6 continues on error
                        "add(..) result: " << add(2, 2));

    BOOST_CHECK_EQUAL(add(2, 2), 4);	  // #7 continues on error
}

BOOST_AUTO_TEST_CASE(image_loading_test) {
    auto image = loadPPM("res/tester_p3.ppm");
    BOOST_CHECK(image.R(0, 0) == 0);
    BOOST_CHECK(image.G(0, 0) == 0);
    BOOST_CHECK(image.B(0, 0) == 0);

    BOOST_CHECK(image.R(0, 3) == 15);
    BOOST_CHECK(image.G(0, 3) == 0);
    BOOST_CHECK(image.B(0, 3) == 15);

    BOOST_CHECK(image.R(2, 2) == 0);
    BOOST_CHECK(image.G(2, 2) == 15);
    BOOST_CHECK(image.B(2, 2) == 7);

    BOOST_CHECK(image.R(0, 0) == 0);
    BOOST_CHECK(image.G(0, 0) == 0);
    BOOST_CHECK(image.B(0, 0) == 0);

    // out of bounds indexing
    BOOST_CHECK(image.R(7, 0) == 15);
    BOOST_CHECK(image.G(7, 0) == 0);
    BOOST_CHECK(image.B(7, 0) == 15);

    BOOST_CHECK(image.R(0, 7) == 15);
    BOOST_CHECK(image.G(0, 7) == 0);
    BOOST_CHECK(image.B(0, 7) == 15);

    BOOST_CHECK(image.R(1, 7) == 0);
    BOOST_CHECK(image.G(1, 7) == 0);
    BOOST_CHECK(image.B(1, 7) == 0);

    BOOST_CHECK(image.R(7, 1) == 0);
    BOOST_CHECK(image.G(7, 1) == 0);
    BOOST_CHECK(image.B(7, 1) == 0);

    BOOST_CHECK(image.R(7, 7) == 0);
    BOOST_CHECK(image.G(7, 7) == 0);
    BOOST_CHECK(image.B(7, 7) == 0);
}

BOOST_AUTO_TEST_CASE(image_color_conv_test) {
    auto image = loadPPM("res/tester_p3.ppm");

    auto YCbCr_image = image.convertToColorSpace(Image::YCbCr);
    CHECK_CLOSE(YCbCr_image.Y(0, 3), 6.1949);
    CHECK_CLOSE(YCbCr_image.Cb(0, 3), 132.9695);
    CHECK_CLOSE(YCbCr_image.Cr(0, 3), 134.2805);

    CHECK_CLOSE(YCbCr_image. Y(1, 1), 9.6030);
    CHECK_CLOSE(YCbCr_image.Cb(1, 1), 126.5319);
    CHECK_CLOSE(YCbCr_image.Cr(1, 1), 121.1519);

    // converting from YCbCr to YCbCr doesn't do a thing!
    YCbCr_image = image.convertToColorSpace(Image::YCbCr);
    CHECK_CLOSE(YCbCr_image.Y(0, 3), 6.1949);
    CHECK_CLOSE(YCbCr_image.Cb(0, 3), 132.9695);
    CHECK_CLOSE(YCbCr_image.Cr(0, 3), 134.2805);

    auto rgb_image = image.convertToColorSpace(Image::RGB);
    CHECK_CLOSE(rgb_image.R(0, 3), 15);
    CHECK_CLOSE(rgb_image.G(0, 3), 0);
    CHECK_CLOSE(rgb_image.B(0, 3), 15);

    CHECK_CLOSE(rgb_image.R(1, 1), 0);
    CHECK_CLOSE(rgb_image.G(1, 1), 15);
    CHECK_CLOSE(rgb_image.B(1, 1), 7);
}

BOOST_AUTO_TEST_CASE(image_subsampling_test)
{
    auto image_orig = loadPPM("res/tester_p3.ppm");

    {
        auto image = image_orig;
        image.applySubsampling(Image::S444);
        BOOST_CHECK_EQUAL(image.B.size2(), 8);
        BOOST_CHECK_EQUAL(image.B.size1(), 8);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S422);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 8);

        // B channel:
        // 0 0 
        // 0 0
        // 0 7
        // 15 0
        BOOST_CHECK_EQUAL(image.B(2, 0), 0);
        BOOST_CHECK_EQUAL(image.B(2, 1), 7);
        BOOST_CHECK_EQUAL(image.B(3, 0), 15);
        BOOST_CHECK_EQUAL(image.B(3, 1), 0);

        // G channel:
        // 0 0 
        // 0 0
        // 0 15
        // 0 0
        BOOST_CHECK_EQUAL(image.G(2, 0), 0);
        BOOST_CHECK_EQUAL(image.G(2, 1), 15);
        BOOST_CHECK_EQUAL(image.G(3, 0), 0);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S411);
        BOOST_CHECK_EQUAL(image.B.size2(), 2);
        BOOST_CHECK_EQUAL(image.B.size1(), 8);

        // B channel:
        // 0
        // 0
        // 0
        // 15
        BOOST_CHECK_EQUAL(image.B(2, 0), 0);
        BOOST_CHECK_EQUAL(image.B(3, 0), 15);

        // G channel:
        // 0
        // 0
        // 0
        // 0
        BOOST_CHECK_EQUAL(image.G(2, 0), 0);
        BOOST_CHECK_EQUAL(image.G(3, 0), 0);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S420);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 4);
        
        // B channel:
        // 0 0
        // 0 7
        BOOST_CHECK_EQUAL(image.B(1, 0), 0);
        BOOST_CHECK_EQUAL(image.B(1, 1), 7);

        // G channel:
        // 0 0
        // 0 15
        BOOST_CHECK_EQUAL(image.G(1, 0), 0);
        BOOST_CHECK_EQUAL(image.G(1, 1), 15);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S420_m);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 4);
        
        // B channel:
        // 1.75 3.75
        // 3.75 1.75
        BOOST_CHECK_EQUAL(image.B(0, 0), 1.75);
        BOOST_CHECK_EQUAL(image.B(1, 0), 3.75);
        BOOST_CHECK_EQUAL(image.B(0, 1), 3.75);
        BOOST_CHECK_EQUAL(image.B(1, 1), 1.75);

        // G channel:
        // 3.75 0
        // 0    3.75
        BOOST_CHECK_EQUAL(image.G(0, 0), 3.75);
        BOOST_CHECK_EQUAL(image.G(1, 0), 0);
        BOOST_CHECK_EQUAL(image.G(0, 1), 0);
        BOOST_CHECK_EQUAL(image.G(1, 1), 3.75);
    }

    {
        auto image = image_orig;
        image.applySubsampling(Image::S420_lm);
        BOOST_CHECK_EQUAL(image.B.size2(), 4);
        BOOST_CHECK_EQUAL(image.B.size1(), 4);
        
        // B channel:
        // 0   0
        // 7.5 3.5
        BOOST_CHECK_EQUAL(image.B(0, 0), 0);
        BOOST_CHECK_EQUAL(image.B(0, 1), 0);
        BOOST_CHECK_EQUAL(image.B(1, 0), 7.5);
        BOOST_CHECK_EQUAL(image.B(1, 1), 3.5);

        // G channel:
        // 0 0
        // 0 7.5
        BOOST_CHECK_EQUAL(image.G(0, 0), 0);
        BOOST_CHECK_EQUAL(image.G(1, 0), 0);
        BOOST_CHECK_EQUAL(image.G(0, 1), 0);
        BOOST_CHECK_EQUAL(image.G(1, 1), 7.5);
    }
}

BOOST_AUTO_TEST_CASE(jpeg_segments_test)
{
    // playing with byte memory
    {
        Segment::Bytes<5> bytes{ { 0 } };
        Segment::set(bytes, { 1, 2, 3, 4, 255 });

        BOOST_CHECK_EQUAL(5, sizeof(bytes));

        BOOST_CHECK_EQUAL(bytes[0], 1);
        BOOST_CHECK_EQUAL(bytes[1], 2);
        BOOST_CHECK_EQUAL(bytes[2], 3);
        BOOST_CHECK_EQUAL(bytes[3], 4);
        BOOST_CHECK_EQUAL(bytes[4], 255);

        Byte copy[] = { 'J', 'F', 'I', 'F', '\0' };
        memcpy(bytes.data(), copy, 5);
{'fraction_non_alphanumeric': 0.17104689995643968, 'fraction_numerical': 0.06519529548424569, 'mean_word_length': 2.2222222222222223, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4702462', 'n_tokens_mistral': 6232, 'n_tokens_neox': 5347, 'n_words': 994}