mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
178 lines
5.4 KiB
C++
178 lines
5.4 KiB
C++
/*
|
|
* 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
|