This topic has not yet been rated - Rate this topic

3.1.8.1.7.3.2 RLGR1/RLGR3 Encode

The following pseudocode sample shows how to encode a stream of input symbols using the RLGR1/RLGR3 algorithm.

// Constants used within the RLGR1/RLGR3 algorithm

#define KPMAX   (80)   // max value for kp or krp
#define LSGR    (3)    // shift count to convert kp to k
#define UP_GR   (4)    // increase in kp after a zero run in RL mode
#define DN_GR   (6)    // decrease in kp after a nonzero symbol in RL mode
#define UQ_GR   (3)    // increase in kp after nonzero symbol in GR mode
#define DQ_GR   (3)    // decrease in kp after zero symbol in GR mode


//
// Returns the next coefficient (a signed int) to encode, from the input stream
//
INT 
GetNextInput();


//
// Emit bitPattern to the output bitstream.
// The bitPattern value represents a bit sequence that is generated by shifting 
// new bits in from the right. If we take the binary representation of bitPattern, 
// with N(numBits-1) being the leftmost bit position and 0 being the rightmost bit position, 
// the mapping of bitPattern to the output bytes is as follows:
//
//     bitPattern[N..0] -> byte[MSB..LSB] .. byte[MSB..LSB]
//
VOID 
OutputBits(
    INT numBits,      // number of bits in bitPattern
    INT  bitPattern   // bit pattern
    );

//
// Emit a bit (0 or 1), count number of times, to the output bitstream
//
VOID 
OutputBit(
    INT count,     // number of times to emit the bit
    INT bit        // 0 or 1
    );

//
// Returns the least number of bits required to represent a given value
// 
UINT 
GetMinBits(
    INT val      // returns ceil(log2(val))
    );

// 
// Converts the input value to (2 * abs(input) - sign(input)), 
// where sign(input) = (input < 0 ? 1 : 0) and returns it
//
UINT
Get2MagSign(
    INT input    // input value
    );


//
// Update the passed parameter and clamp it to the range [0,KPMAX]
// Return the value of parameter right-shifted by LSGR
//
INT 
UpdateParam(
    INT*  param,    // parameter to update
    INT   deltaP    // update delta
    )
{
    *param += deltaP;
    if (*param > KPMAX) *param = KPMAX;
    if (*param < 0) *param = 0;
    return (*param >> LSGR);
}


//
// Outputs the Golomb/Rice encoding of a non-negative integer
//
VOID
CodeGR(
    INT*   krp,   // GR parameter, used and updated based on the input value
    UINT  val     // input non-negative value to be encoded
    )
{
    INT kr = *krp >> LSGR;

    // unary part of GR code

    UINT vk = val >> kr;
    OuputBit(vk, 1);
    OutputBit(1, 0);

    // remainder part of GR code, if needed
    if (kr) {
        OutputBits(kr, val & ((1 << kr) - 1));
    }

    // update krp, only if it is not equal to 1
    if (vk == 0) {
        UpdateParam(krp, -2);
    } 
    else if (vk > 1) {
        UpdateParam(krp, vk);
    }
}


//
// Routine that outputs a stream of RLGR1/RLGR3-encoded bits
//
VOID 
RLGR_Encode(
    RLGR_MODE rlgrMode    // RLGR1 || RLGR3
    )
{
    // initialize the parameters
    INT k = 1;
    INT kp = 1 << LSGR;
    INT kr = 1;
    INT krp = 1 << LSGR;

    // process all the input coefficients
    while (1)
    {
        INT input;

        if (k)
        {
            // RUN-LENGTH MODE

            // collect the run of zeros in the input stream
            INT numZeros = 0;
            while ((input = GetNextInput()) == 0) {
                ++ numZeros;
            }

            // emit output zeros
            INT runmax = 1 << k;
            while (numZeros >= runmax)
            {
                OutputBit(1, 0);             // output a zero bit
                numZeros -= runmax;
                k = UpdateParam(&kp, UpGR);  // update kp, k 
                runmax = 1 << k;
            }

            // output a 1 to terminate runs
            OuputBit(1, 1);

            // output the remaining run length using k bits
            OutputBits(k, numZeros);

            // encode the nonzero value using GR coding

            INT mag = abs(input);            // absolute value of input coefficient
            INT sign = (input < 0 ? 1 : 0);  // sign of input coefficient

            OutputBit(1, sign);      // output the sign bit
            CodeGR(&krp, mag - 1);   // output GR code for (mag - 1)

            k = UpdateParam(&kp, -DnGR);
        }
        else 
        {
            // GOLOMB-RICE MODE

            if (rlgrMode == RLGR1)
            {
                // RLGR1 variant

                // convert input to (2*magnitude - sign), encode using GR code
                UINT twoMs = Get2MagSign(GetNextInput());
                CodeGR(&krp, twoMs); 

                // update k, kp
                if (twoMs) {
                    k = UpdateParam(&kp, UqGR);
                } 
                else {
                    k = UpdateParam(&kp, -DqGR);
                }
            }
            else // rlgrMode == RLGR3
            {
                // RLGR3 variant

                // convert the next two input values to (2*magnitude - sign) and
                // encode their sum using GR code

                UINT twoMs1 = Get2MagSign(GetNextInput());
                UINT twoMs2 = Get2MagSign(GetNextInput());
                UINT sum2Ms = twoMs1 + twoMs2;
                
                CodeGR(&krp, sum2Ms);

                // encode binary representation of the first input (twoMs1).  
                OutputBits(GetMinBits(sum2Ms), twoMs1);

                // update k,kp for the two input values

                if (twoMs1 && twoMs2) {
                    k = UpdateParam(&kp, -2*DqGR);
                } 
                else if (!twoMs1 && !twoMs2) {
                    k = UpdateParam(&kp, 2*UqGR);
                }

            }
        }
    }
}
 
Did you find this helpful?
(1500 characters remaining)