mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-21 00:38:56 +00:00
LibGfx/JBIG2: Add arithmetic integer decoder
The existing ArithmeticEncoder (from Annex E) reads one bit at a time. ArithmeticIntegerDecoder (from Annex A) builds on top of that to read integer values. This will be used by both the symbol segment and the text segment readers. (This does not yet implement the IAID decoding procedure in A.3. We only need that one in the text segment decoder at the moment, and it's pretty small, so I'll put it inline there for now.) Not used yet, so no behavior change yet.
This commit is contained in:
parent
c99506da7d
commit
8e82c2b932
Notes:
sideshowbarker
2024-07-18 00:54:03 +09:00
Author: https://github.com/nico
Commit: 8e82c2b932
Pull-request: https://github.com/SerenityOS/serenity/pull/23661
Reviewed-by: https://github.com/trflynn89
1 changed files with 75 additions and 0 deletions
|
@ -215,6 +215,81 @@ void ArithmeticDecoder::BYTEIN()
|
|||
}
|
||||
}
|
||||
|
||||
// Annex A, Arithmetic integer decoding procedure
|
||||
class ArithmeticIntegerDecoder {
|
||||
public:
|
||||
ArithmeticIntegerDecoder(ArithmeticDecoder&);
|
||||
|
||||
// A.2 Procedure for decoding values (except IAID)
|
||||
// Returns OptionalNone for OOB.
|
||||
Optional<i32> decode();
|
||||
|
||||
private:
|
||||
ArithmeticDecoder& m_decoder;
|
||||
u16 PREV { 0 };
|
||||
Vector<ArithmeticDecoder::Context> contexts;
|
||||
};
|
||||
|
||||
ArithmeticIntegerDecoder::ArithmeticIntegerDecoder(ArithmeticDecoder& decoder)
|
||||
: m_decoder(decoder)
|
||||
{
|
||||
contexts.resize(1 << 9);
|
||||
}
|
||||
|
||||
Optional<int> ArithmeticIntegerDecoder::decode()
|
||||
{
|
||||
// A.2 Procedure for decoding values (except IAID)
|
||||
// "1) Set:
|
||||
// PREV = 1"
|
||||
u16 PREV = 1;
|
||||
|
||||
// "2) Follow the flowchart in Figure A.1. Decode each bit with CX equal to "IAx + PREV" where "IAx" represents the identifier
|
||||
// of the current arithmetic integer decoding procedure, "+" represents concatenation, and the rightmost 9 bits of PREV are used."
|
||||
auto decode_bit = [&]() {
|
||||
bool D = m_decoder.get_next_bit(contexts[PREV & 0x1FF]);
|
||||
// "3) After each bit is decoded:
|
||||
// If PREV < 256 set:
|
||||
// PREV = (PREV << 1) OR D
|
||||
// Otherwise set:
|
||||
// PREV = (((PREV << 1) OR D) AND 511) OR 256
|
||||
// where D represents the value of the just-decoded bit.
|
||||
if (PREV < 256)
|
||||
PREV = (PREV << 1) | (u16)D;
|
||||
else
|
||||
PREV = (((PREV << 1) | (u16)D) & 511) | 256;
|
||||
return D;
|
||||
};
|
||||
|
||||
auto decode_bits = [&](int n) {
|
||||
u32 result = 0;
|
||||
for (int i = 0; i < n; ++i)
|
||||
result = (result << 1) | decode_bit();
|
||||
return result;
|
||||
};
|
||||
|
||||
// Figure A.1 – Flowchart for the integer arithmetic decoding procedures (except IAID)
|
||||
u8 S = decode_bit();
|
||||
u32 V;
|
||||
if (!decode_bit())
|
||||
V = decode_bits(2);
|
||||
else if (!decode_bit())
|
||||
V = decode_bits(4) + 4;
|
||||
else if (!decode_bit())
|
||||
V = decode_bits(6) + 20;
|
||||
else if (!decode_bit())
|
||||
V = decode_bits(8) + 84;
|
||||
else if (!decode_bit())
|
||||
V = decode_bits(12) + 340;
|
||||
else
|
||||
V = decode_bits(32) + 4436;
|
||||
|
||||
// "4) The sequence of bits decoded, interpreted according to Table A.1, gives the value that is the result of this invocation
|
||||
// of the integer arithmetic decoding procedure."
|
||||
if (S == 1 && V == 0)
|
||||
return {};
|
||||
return S ? -V : V;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// JBIG2 spec, Annex D, D.4.1 ID string
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue