In the two for loops below, I want the checksum variable to hold the same value for both even though one loop starts at row 12 and another at row 0.

Any ideas how I can combine these loops so that I don't have to iterate the same buffer twice?

std::uint32_t Checksum = 0;
std::uint32_t CheckSum2 = 0;
std::uint8_t* Ptr = Pixels;

int K = Width < 12 ? 1 : 12;

for (int I = K; I < Height; ++I) //Start at row K offset.
{
    for (int J = 0; J < Width; ++J)
    {
        R += *(Ptr++);
        G += *(Ptr++);
        B += *(Ptr++);

        CheckSum += *(Ptr++);
    }
}



Ptr = Pixels;

for (int I = 0; I < Height; ++I) //Start at 0 offset
{
    for (int J = 0; J < Width; ++J)
    {
        CR += *(Ptr++);
        CG += *(Ptr++);
        CB += *(Ptr++);

        if (I >= K) //if we are at row K?
            CheckSum2 += *(Ptr++);
    }
}

However, CheckSum != Checksum2 so I'm not sure how I can combine them :S

Edited 3 Years Ago by triumphost

Does something like this do what you want?

std::uint32_t Checksum = 0;
std::uint32_t CheckSum2 = 0;
std::uint8_t* Ptr = Pixels;

int K = Width < 12 ? 1 : 12;

for (int I = 0; I < K; ++I) //Start at 0 offset
{
    for (int J = 0; J < Width; ++J)
    {
        CR += *(Ptr++);
        CG += *(Ptr++);
        CB += *(Ptr++);
    }
}

std::unint_8 temp;

for (int I = K; I < Height; ++I) //Start at row K offset.
{
    for (int J = 0; J < Width; ++J)
    {
        temp = *(Ptr++);
        R +=  temp;
        CR += temp;

        temp = *(Ptr++);
        G +=  temp;
        CG += temp;

        temp = *(Ptr++);
        B +=  temp;
        CB += temp;

        CheckSum += *(Ptr++);
    }
}

Close to that yeah. I came up with:

std::uint32_t CheckSum(const void* Data, std::uint32_t &MeanColour, std::uint32_t &ClippedID, std::size_t Width, std::size_t Height)
{
    std::uint32_t CheckSum = 0;
    int R = 0, G = 0, B = 0, K = 0;
    const std::uint8_t* BuffPos = static_cast<const std::uint8_t*>(Data);

    for (std::size_t I = Height < 12 ? 1 : 12; I < Height; ++I)
    {
        for (std::size_t J = 0; J < Width; ++J)
        {
            int b = *(BuffPos++);
            int g = *(BuffPos++);
            int r = *(BuffPos++);
            CheckSum += *(BuffPos++);

            if (r != 0 && g != 0 && b != 0)
            {
                R += r;
                G += g;
                B += b;
                ++K;
            }
        }
    }

    ClippedID = (K != 0 ? RGB(R / K, G / K, B / K) : RGB(R, G, B));
    BuffPos = static_cast<const std::uint8_t*>(Data);
    R = G = B = K = 0;

    for (std::size_t I = 0; I < Height; ++I)
    {
        for (std::size_t J = 0; J < Width; ++J, ++K)
        {
            R += *(BuffPos++);
            G += *(BuffPos++);
            B += *(BuffPos++);
            ++BuffPos;
        }
    }

    MeanColour = (K != 0 ? RGB(R / K, G / K, B / K) : RGB(R, G, B));
    return CheckSum;
}

Where:
Checksum is the count of alpha pixels starting at height 12.
ClippedID is the average of all RGB pixels starting at height 12.
MeanColour is the average of all RGB pixels starting at height 0.

What I really was trying to do was use 2 for-loops to do this instead of 4.
However, as you notice, first I iterate the buffer at height 12 all the way to the end. Then I start over and iterate from zero to the end.

I was trying to avoid doing that.

With your solution, I put it together like so:

std::uint32_t Math::ColourCheckSum(const void* Data, std::uint32_t &MeanColour, std::uint32_t &ClippedID, std::size_t Width, std::size_t Height)
{
    std::uint32_t CheckSum = 0;
    int R = 0, G = 0, B = 0, K = 0;
    int CR = 0, CG = 0, CB = 0, CK = 0;
    std::size_t Offset = Height < 12 ? 1 : 12;
    const std::uint8_t* BuffPos = static_cast<const std::uint8_t*>(Data);

    for (std::size_t I = 0; I < Offset; ++I)
    {
        for (std::size_t J = 0; J < Width; ++J)
        {
            std::uint8_t b = *(BuffPos++);
            std::uint8_t g = *(BuffPos++);
            std::uint8_t r = *(BuffPos++);
            ++BuffPos;

            if (r != 0 && g != 0 && b != 0)
            {
                R += r;
                G += g;
                B += b;
                ++K;
            }
        }
    }

    for (std::size_t I = Offset; I < Height; ++I)
    {
        for (std::size_t J = 0; J < Width; ++J)
        {
            std::uint8_t b = *(BuffPos++);
            std::uint8_t g = *(BuffPos++);
            std::uint8_t r = *(BuffPos++);
            CheckSum += *(BuffPos++);

            if (r != 0 && g != 0 && b != 0)
            {
                R += r;
                G += g;
                B += b;
                CR += r;
                CG += g;
                CB += b;
                ++CK;
                ++K;
            }
        }
    }

    MeanColour = (K != 0 ? RGB(R / K, G / K, B / K) : RGB(R, G, B));
    ClippedID = (CK != 0 ? RGB(CR / CK, CG / CK, CB / CK) : RGB(CR, CG, CB));

    return CheckSum;
}

Your solution essentially iterates the buffer once. It starts at 0, stops at 12. Starts at 12, goes to the end. Which is nice because I want that. Would be even nicer if it was only 2 for-loops instead of 4.

However, it does not print the same result as mine so something is missing
:(

This article has been dead for over six months. Start a new discussion instead.