HALICERY

free-time coding, hardware dev, articles

Top
Home 8042 Blogs About
Home Image Decoders JPEG JPEG81

Last modified: Sat Feb 9 15:09:56 UTC+0100 2019 © A. Tarpai


JPEG81 coefficient decoder

History

I've made a progressive JPEG decoder available many years ago (FireRainbow), but when I looked at my code after 5 years, well... it hit me by the classical programmer's saying: "Hm.. that's not my code". I've decided to re-write and extend a little bit. Back then, my motivation was to simply blit an uncomressed image into the frame buffer in my hobby OS. For others this might be not the case, although I tried to make the code as general as I could.

JPEG coefficient decoder

In JPEG81 I have focused on ITU T.81 decoder conformance. In the T.83 package there are several compressed test data streams (JPEG sample image files). For the DCT-based process, reference test data is in the form of 16-bit signed coefficients for each 8x8 block per image component in a separate file. During decoding, this is the stage right before de-quantization (then IDCT).

Therefore, JPEG81 is a 'coefficient decoder'.

It allowed me to test:

The following files were successfully decoded with no error against encoder reference data (files of EREF.DCT):

DATA     JPEG   Precision   Entropy    Code       Nf   Inter-    DRI
STREAM   mode    (bits)     Coder      Tables          leave
-----------------------------------------------------------------------
A1       S(B)       8       Huff       sample      4     yes     yes
C1       S(E)       8       Huff       custom      4     yes     yes
C2       S(E)       8       Huff       custom      4      no     yes
D1       S(E)       8       arith      custom      4     yes     yes
D2       S(E)       8       arith      custom      4      no     yes
E1       S(E)      12       Huff       custom      4     yes     yes
E2       S(E)      12       Huff       custom      4      no     yes
F1       S(E)      12       arith      custom      4     yes     yes
F2       S(E)      12       arith      custom      4      no     yes
G1       P(SS)      8       Huff       custom      4     yes     yes
H1       P(SS)      8       arith      custom      4     yes     yes
J1       P(SS)     12       arith      custom      4     yes     yes
K1       P(Full)    8       Huff       custom      4     yes     yes
L1       P(Full)    8       arith      custom      4     yes     yes
N1       P(Full)   12       arith      custom      4     yes     yes
O1       LL         8       Huff       sample      4     yes     yes
O2       LL        16       Huff       sample      4      no     yes
P1       LL         8       arith      default     4     yes     yes
P2       LL        16       arith      custom      4      no     yes

Those T.83 test images have 4 image components and a crazy sub-sampling (output from Analyzer):

0000021B: FFC2 SOF2 (Huffman Progressive DCT)
  P=8 Y=257 X=255
  Nf=4
    Ci=200 HV=1x1 Qi=0
    Ci=150 HV=1x2 Qi=1
    Ci=100 HV=3x1 Qi=2
    Ci= 50 HV=1x4 Qi=3

  0
    Sample: x=85+3 (1:3) y=65+7 (1:4)
    8x8 Data Unit: 99 (X=11 Y=9)
    MCU Data Unit: 99 (X=11 Y=9)
  1
    Sample: x=85+3 (1:3) y=129+7 (1:2)
    8x8 Data Unit: 187 (X=11 Y=17)
    MCU Data Unit: 198 (X=11 Y=18)
  2
    Sample: x=255+1 (1:1) y=65+7 (1:4)
    8x8 Data Unit: 288 (X=32 Y=9)
    MCU Data Unit: 297 (X=33 Y=9)
  3
    Sample: x=85+3 (1:3) y=257+7 (1:1)
    8x8 Data Unit: 363 (X=11 Y=33)
    MCU Data Unit: 396 (X=11 Y=36)

  99 MCU (11 x 9)

  Malloc for 990 Data Units (126720 bytes)

  MCU: 3 x 4 (24 x 32 pixels)
  DU: 0 1 1 2 2 2 3 3 3 3  (10 DU/MCU)
  Subsampling:
  +---------+---------+---------+---------+
  | 0  -  - | 1  -  - | 2  2  2 | 3  -  - |
  | -  -  - | 1  -  - | -  -  - | 3  -  - |
  | -  -  - | -  -  - | -  -  - | 3  -  - |
  | -  -  - | -  -  - | -  -  - | 3  -  - |
  +---------+---------+---------+---------+

During testing, no matter how hard I tried, I got +/- 1 decoded coefficient differences comparing my output with the Decoder reference test data. It made me crazy, at this stage there should be a match. Especially disturbing, because as in the last successive scan, when the lsb of the coefficient gets decoded, this error cannot detect decoding error. Then, I just tried the Encoder reference test data - and there were no errors, the two fully matched. The Encoder reference test data is different from the Decoder reference test data in +/- 1 at certain places.

Input

Through two statically linked functions by the moment:

This interface fits both common scenarios:

Output

For the DCT-based mode, memory structure is (almost) the same as defined in T.83. After reading the SOF header, the decoder allocates buffer for all Data Units of all components, preparing to receive partial MCU-s in one, big interleaved scan. This is the maximum number of DU-s for the image.

Here is the structure for one image component: 'X' are possible extensions in partial MCU-s.

for single scans, only DU-s marked by '-' are in encoded in the data stream
for interleaved scans, there is a possibility for 'dummy' DU-s, marked by 'X'

- - - - - - - X X
- - - - - - - X X
- - - - - - - X X
- - - - - - - X X
- - - - - - - X X
- - - - - - - X X
- - - - - - - X X
- - - - - - - X X
- - - - - - - X X
X X X X X X X X X

What is it good for?

So this version is a stripped-down decoder. It's a one-file-lib, with very simple I/O interface. I used it with modifications for a small jpeg-to-bmp decoder, a jpeg-analyzer console application, and a jpeg-analyzer Windows GUI application. As I mentioned, it really depends what we want from a JPEG decoder.

Source code

Can be found in RAINBOW on GitHub.