satdump/plugins/xrit_support/DecompWT/CVLCCoder.cpp

179 lines
5.4 KiB
C++
Raw Permalink Normal View History

/*
* Copyright 2011-2019, European Organisation for the Exploitation of Meteorological Satellites (EUMETSAT)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//:Ignore
//////////////////////////////////////////////////////////////////////////
//
// FileName: CVLCCoder.cpp
//
// Date Created: 15/01/1999
//
// Author: Youssef Ouaghli
//
// Description: CVLCCoder class definition.
//
// Last Modified: $Dmae: 1999/08/26 15:41:07 $
//
// RCS Id: $Id: CVLCCoder.cpp,v 1.45 1999/08/26 15:41:07 youag Exp $
//
//////////////////////////////////////////////////////////////////////////
//:End Ignore
#include "CVLCCoder.h"
namespace COMP
{
void CVLCCoder::CodeQuadrantDC(CWBlock &i_Wblk,
const unsigned int i_W, const unsigned int i_H,
const unsigned int /*i_Quadrant*/)
{
COMP_TRYTHIS
// Get the number of bits needed to code the block coefs
unsigned int nbBit = speed_csize(i_Wblk.GetQuadrantMaxCoef(0, 0, i_W, i_H));
m_Ac.CodeBits(nbBit, m_NbBitNbBitCoef);
if (nbBit)
{
m_Mod = m_Models[nbBit++];
if (!m_Mod[0].IsInitialized())
for (unsigned int i = 0; i <= nbBit; i++)
m_Mod[i].Initialize(nbBit + 1);
int oldCoef = 1UL << (nbBit - 2);
unsigned int context = nbBit;
const int *p = i_Wblk.GetData()[0];
const unsigned int w = i_Wblk.GetW();
for (int i = i_H; i > 0; i--, p += w)
{
for (unsigned int j = i_W; j; j--)
{
const int c = *p++;
context = (context + CodeCoef(context, c - oldCoef)) >> 1;
oldCoef = c;
}
if (--i)
{
p += w;
for (unsigned int j = i_W; j; j--)
{
const int c = *--p;
context = (context + CodeCoef(context, c - oldCoef)) >> 1;
oldCoef = c;
}
}
}
}
COMP_CATCHTHIS
}
void CVLCCoder::CodeQuadrant(CWBlock &i_Wblk,
const unsigned int i_X, const unsigned int i_Y,
const unsigned int i_W, const unsigned int i_H,
const unsigned int i_Level, const unsigned int i_Quadrant)
{
COMP_TRYTHIS
// Get the number of bits needed to code the block coefs
unsigned int nbBit = speed_csize(i_Wblk.GetQuadrantMaxCoef(i_X, i_Y, i_W, i_H));
m_Ac.CodeBits(nbBit, m_NbBitNbBitCoef);
const unsigned int coefShift = i_Level >= m_NbLossyBitPlane
? 0
: m_NbLossyBitPlane - i_Level - (i_Quadrant > m_NbLossyQuadrant ? 1 : 0);
if (nbBit > coefShift)
{
nbBit -= coefShift;
m_Mod = m_Models[nbBit - 1];
if (!m_Mod[0].IsInitialized())
for (unsigned int i = 0; i <= nbBit; i++)
m_Mod[i].Initialize(nbBit + 1);
unsigned int context = nbBit;
const int *p = i_Wblk.GetData()[i_Y] + i_X;
const unsigned int w = i_Wblk.GetW();
if (!coefShift)
for (int i = i_H; i > 0; i--, p += w)
{
for (unsigned int j = i_W; j; j--)
context = (context + CodeCoef(context, *p++)) >> 1;
if (--i)
{
p += w;
for (unsigned int j = i_W; j; j--)
context = (context + CodeCoef(context, *--p)) >> 1;
}
}
else
for (int i = i_H; i > 0; i--, p += w)
{
for (unsigned int j = i_W; j; j--)
{
int cV = *p++;
cV = cV >= 0 ? cV >> coefShift : -(-cV >> coefShift);
context = (context + CodeCoef(context, cV)) >> 1;
}
if (--i)
{
p += w;
for (unsigned int j = i_W; j; j--)
{
int cV = *--p;
cV = cV >= 0 ? cV >> coefShift : -(-cV >> coefShift);
context = (context + CodeCoef(context, cV)) >> 1;
}
}
}
}
COMP_CATCHTHIS
}
void CVLCCoder::Code(CWBlock &i_Wblk, const unsigned int i_NbIteWt, const unsigned int i_NbLossyBp)
{
COMP_TRYTHIS
// Get the number of bits needed to code the block coefs
const unsigned int nbBit = speed_csize(i_Wblk.GetMaxCoef());
// To make sure CACCoder::CodeBits() will not fail
Assert(nbBit <= (c_ACNbBits - 2), Util::CParamException());
m_Ac.CodeBits(nbBit, 5);
if (nbBit)
{
static const unsigned int bitPlanes[16] = {0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4};
static const unsigned int quadrants[16] = {0, 0, 0, 2, 3, 0, 2, 3, 5, 6, 0, 2, 3, 5, 6, 9};
Assert(i_NbLossyBp < 16, Util::CParamException());
unsigned int w = i_Wblk.GetW() >> i_NbIteWt;
unsigned int h = i_Wblk.GetH() >> i_NbIteWt;
// Check the block dimension against the number of wavelet transform iteration
Assert((w << i_NbIteWt) == i_Wblk.GetW() || (h << i_NbIteWt) == i_Wblk.GetH(), Util::CParamException());
unsigned int m = i_NbIteWt;
unsigned int q = i_NbIteWt * 3;
m_NbBitCoef = nbBit;
m_NbBitNbBitCoef = speed_csize(nbBit);
m_NbIteWt = i_NbIteWt;
m_NbLossyBitPlane = bitPlanes[i_NbLossyBp];
m_NbLossyQuadrant = quadrants[i_NbLossyBp];
CodeQuadrantDC(i_Wblk, w, h, q--);
for (unsigned int k = 0; k < i_NbIteWt; k++, w <<= 1, h <<= 1, m--)
{
CodeQuadrant(i_Wblk, w, 0, w, h, m, q--);
CodeQuadrant(i_Wblk, 0, h, w, h, m, q--);
CodeQuadrant(i_Wblk, w, h, w, h, m - 1, q--);
}
}
COMP_CATCHTHIS
}
} // namespace COMP