satdump/plugins/xrit_support/DecompWT/T4Coder.cpp

157 lines
4.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.
*/
#include <iostream>
#include "ErrorHandling.h"
#include "CDataField.h"
#include "RMAErrorHandling.h"
#include "T4Codes.h"
#include "T4Coder.h"
namespace COMP
{
void CT4Coder::CodeRunLength(EColor i_isWhite, short i_count)
{
COMP_TRYTHIS
do
{
short codeIdx;
oneCode code;
// first, put a markup code if i_count > 63
if (i_count > 63)
{
if (i_count < 1792) // first type of marker
{
codeIdx = (i_count >> 6) - 1; // = i_count/64-1
if (i_isWhite)
code = m_AllCodes.GetMarkUpWhiteCode(codeIdx);
else
code = m_AllCodes.GetMarkUpBlackCode(codeIdx);
}
else // we will have to use the extended set of markers
{
codeIdx = (i_count >> 6) - 28; // (i_count - 1792 ) /64
if (codeIdx > 12) // the max length of an aditional code = (1792 + 12*64 =) 2560
codeIdx = 12;
code = m_AllCodes.GetMarkUpAddCode(codeIdx);
}
i_count -= code.GetCount(); // take into account what was really coded
m_obuf.WriteLSb(code.GetCode(), (unsigned char)code.GetLength());
}
// now, put a terminating code,
codeIdx = i_count;
if (codeIdx > 63)
codeIdx = 63;
if (i_isWhite)
code = m_AllCodes.GetTermWhiteCode(codeIdx);
else
code = m_AllCodes.GetTermBlackCode(codeIdx);
i_count -= code.GetCount();
m_obuf.WriteLSb(code.GetCode(), (unsigned char)code.GetLength());
// and if i_count still > 0, loop, but since Black and White
// run must alternate, put a dummy 0-length run.
if (i_count > 0)
{
if (i_isWhite)
CodeRunLength(e_Black, 0);
else
CodeRunLength(e_White, 0);
}
} while (i_count > 0);
COMP_CATCHTHIS
}
// Code one line of the image, including the corresponding EOL
void CT4Coder::CodeNextLine()
{
COMP_TRYTHIS
unsigned long maxRun = m_width; // so we stop counting at the end of a line
unsigned long count = 0;
while (maxRun > 0)
{
count = m_ibuf.CountNextResetRun(maxRun); // count white run
CodeRunLength(e_White, (short)count); // code it
maxRun -= count;
if (maxRun > 0)
{
count = m_ibuf.CountNextSetRun(maxRun); // count black run
CodeRunLength(e_Black, (short)count); // code it
maxRun -= count;
}
}
CodeEOL(); // we promised to code the EOL so here it is
COMP_CATCHTHIS
}
void CT4Coder::CodeBuffer()
{
COMP_TRYTHIS
CodeEOL();
unsigned __int64 idxi = 0;
unsigned __int64 idxo = 0;
for (short i = 0; i < m_height; i++)
{
try
{
idxo = m_obuf.GetBitIndex();
idxi = m_ibuf.GetBitIndex();
CodeNextLine();
}
catch (COutOfBufferException&)
{
m_obuf.SetLength(2 * idxo);
// and get ready to redo the current line
m_obuf.SetBitIndex((unsigned long)idxo);
m_ibuf.SetBitIndex((unsigned long)idxi);
i--;
}
}
// now, make sure there remains enough place in the buffer for the data
// we still have to put 60 bits in the buffer.
idxo = m_obuf.GetBitIndex();
m_obuf.SetLength(idxo + 70); //(5*12 + 10 (10=security margin)
CodeEOL(); // notice only 5 EOL since there is already on EOL from the last line
CodeEOL();
CodeEOL();
CodeEOL();
CodeEOL();
m_compressedlength = m_obuf.GetBitIndex();
COMP_CATCHTHIS
}
Util::CDataFieldCompressedImage CT4Coder::GetCompressedImage()
{
COMP_TRYTHIS
Assert(m_compressedlength > 0, Util::CParamException());
// create a new CDataField with the one of m_obuf. Notice
// that no bytecopy of the buffer takes place and that
// the CDataField creator is (a bit) fooled since we don't tell
// him the real length of the buffer, but the length we want
// him to consider.
Util::CDataFieldCompressedImage cd(m_obuf,
1,
m_width,
m_height);
m_compressedlength = 0; // invalidate buffer.
return cd;
COMP_CATCHTHIS
}
} // end namespace COMP