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