diff options
Diffstat (limited to 'include/ast_jpeg_decoder.hpp')
-rw-r--r-- | include/ast_jpeg_decoder.hpp | 2685 |
1 files changed, 1439 insertions, 1246 deletions
diff --git a/include/ast_jpeg_decoder.hpp b/include/ast_jpeg_decoder.hpp index e6e0f08efb..e8bdddbf59 100644 --- a/include/ast_jpeg_decoder.hpp +++ b/include/ast_jpeg_decoder.hpp @@ -1,345 +1,390 @@ #pragma once #include <aspeed/JTABLES.H> -#include <ast_video_types.hpp> + #include <array> +#include <ast_video_types.hpp> #include <cassert> #include <cstdint> #include <cstring> #include <iostream> #include <vector> -namespace ast_video { +namespace ast_video +{ -struct ColorCache { - ColorCache() - : color{0x008080, 0xFF8080, 0x808080, 0xC08080}, index{0, 1, 2, 3} {} +struct ColorCache +{ + ColorCache() : + color{0x008080, 0xFF8080, 0x808080, 0xC08080}, index{0, 1, 2, 3} + { + } - unsigned long color[4]; - unsigned char index[4]; - unsigned char bitMapBits{}; + unsigned long color[4]; + unsigned char index[4]; + unsigned char bitMapBits{}; }; -struct RGB { - unsigned char b; - unsigned char g; - unsigned char r; - unsigned char reserved; +struct RGB +{ + unsigned char b; + unsigned char g; + unsigned char r; + unsigned char reserved; }; -enum class JpgBlock { - JPEG_NO_SKIP_CODE = 0x00, - JPEG_SKIP_CODE = 0x08, +enum class JpgBlock +{ + JPEG_NO_SKIP_CODE = 0x00, + JPEG_SKIP_CODE = 0x08, - JPEG_PASS2_CODE = 0x02, - JPEG_SKIP_PASS2_CODE = 0x0A, + JPEG_PASS2_CODE = 0x02, + JPEG_SKIP_PASS2_CODE = 0x0A, - LOW_JPEG_NO_SKIP_CODE = 0x04, - LOW_JPEG_SKIP_CODE = 0x0C, + LOW_JPEG_NO_SKIP_CODE = 0x04, + LOW_JPEG_SKIP_CODE = 0x0C, - VQ_NO_SKIP_1_COLOR_CODE = 0x05, - VQ_SKIP_1_COLOR_CODE = 0x0D, + VQ_NO_SKIP_1_COLOR_CODE = 0x05, + VQ_SKIP_1_COLOR_CODE = 0x0D, - VQ_NO_SKIP_2_COLOR_CODE = 0x06, - VQ_SKIP_2_COLOR_CODE = 0x0E, + VQ_NO_SKIP_2_COLOR_CODE = 0x06, + VQ_SKIP_2_COLOR_CODE = 0x0E, - VQ_NO_SKIP_4_COLOR_CODE = 0x07, - VQ_SKIP_4_COLOR_CODE = 0x0F, + VQ_NO_SKIP_4_COLOR_CODE = 0x07, + VQ_SKIP_4_COLOR_CODE = 0x0F, - FRAME_END_CODE = 0x09, + FRAME_END_CODE = 0x09, }; -class AstJpegDecoder { - public: - AstJpegDecoder() { - // TODO(ed) figure out how to init this in the constructor - yuvBuffer.resize(1920 * 1200); - outBuffer.resize(1920 * 1200); - for (auto &r : outBuffer) { - r.r = 0x00; - r.g = 0x00; - r.b = 0x00; - r.reserved = 0xAA; - } +class AstJpegDecoder +{ + public: + AstJpegDecoder() + { + // TODO(ed) figure out how to init this in the constructor + yuvBuffer.resize(1920 * 1200); + outBuffer.resize(1920 * 1200); + for (auto &r : outBuffer) + { + r.r = 0x00; + r.g = 0x00; + r.b = 0x00; + r.reserved = 0xAA; + } - int qfactor = 16; - - scalefactor = qfactor; - scalefactoruv = qfactor; - advancescalefactor = 16; - advancescalefactoruv = 16; - initJpgTable(); - } - - void loadQuantTable(std::array<long, 64> &quant_table) { - float scalefactorF[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, - 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder - // from zig-zag order - switch (ySelector) { - case 0: - stdLuminanceQt = tbl000Y; - break; - case 1: - stdLuminanceQt = tbl014Y; - break; - case 2: - stdLuminanceQt = tbl029Y; - break; - case 3: - stdLuminanceQt = tbl043Y; - break; - case 4: - stdLuminanceQt = tbl057Y; - break; - case 5: - stdLuminanceQt = tbl071Y; - break; - case 6: - stdLuminanceQt = tbl086Y; - break; - case 7: - stdLuminanceQt = tbl100Y; - break; - } - setQuantTable(stdLuminanceQt, static_cast<uint8_t>(scalefactor), tempQT); + int qfactor = 16; - for (j = 0; j <= 63; j++) { - quant_table[j] = tempQT[zigzag[j]]; - } - j = 0; - for (row = 0; row <= 7; row++) { - for (col = 0; col <= 7; col++) { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactorF[row] * scalefactorF[col]) * 65536); - j++; - } - } - bytePos += 64; - } - - void loadQuantTableCb(std::array<long, 64> &quant_table) { - float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, - 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder from zig-zag order - if (mapping == 0) { - switch (uvSelector) { - case 0: - stdChrominanceQt = tbl000Y; - break; - case 1: - stdChrominanceQt = tbl014Y; - break; - case 2: - stdChrominanceQt = tbl029Y; - break; - case 3: - stdChrominanceQt = tbl043Y; - break; - case 4: - stdChrominanceQt = tbl057Y; - break; - case 5: - stdChrominanceQt = tbl071Y; - break; - case 6: - stdChrominanceQt = tbl086Y; - break; - case 7: - stdChrominanceQt = tbl100Y; - break; - } - } else { - switch (uvSelector) { - case 0: - stdChrominanceQt = tbl000Uv; - break; - case 1: - stdChrominanceQt = tbl014Uv; - break; - case 2: - stdChrominanceQt = tbl029Uv; - break; - case 3: - stdChrominanceQt = tbl043Uv; - break; - case 4: - stdChrominanceQt = tbl057Uv; - break; - case 5: - stdChrominanceQt = tbl071Uv; - break; - case 6: - stdChrominanceQt = tbl086Uv; - break; - case 7: - stdChrominanceQt = tbl100Uv; - break; - } + scalefactor = qfactor; + scalefactoruv = qfactor; + advancescalefactor = 16; + advancescalefactoruv = 16; + initJpgTable(); } - setQuantTable(stdChrominanceQt, static_cast<uint8_t>(scalefactoruv), - tempQT); - for (j = 0; j <= 63; j++) { - quant_table[j] = tempQT[zigzag[j]]; - } - j = 0; - for (row = 0; row <= 7; row++) { - for (col = 0; col <= 7; col++) { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536); - j++; - } - } - bytePos += 64; - } - // Note: Added for Dual_JPEG - void loadAdvanceQuantTable(std::array<long, 64> &quant_table) { - float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, - 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder - // from zig-zag order - switch (advanceSelector) { - case 0: - stdLuminanceQt = tbl000Y; - break; - case 1: - stdLuminanceQt = tbl014Y; - break; - case 2: - stdLuminanceQt = tbl029Y; - break; - case 3: - stdLuminanceQt = tbl043Y; - break; - case 4: - stdLuminanceQt = tbl057Y; - break; - case 5: - stdLuminanceQt = tbl071Y; - break; - case 6: - stdLuminanceQt = tbl086Y; - break; - case 7: - stdLuminanceQt = tbl100Y; - break; - } - // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG - setQuantTable(stdLuminanceQt, static_cast<uint8_t>(advancescalefactor), - tempQT); + void loadQuantTable(std::array<long, 64> &quant_table) + { + float scalefactorF[8] = {1.0f, 1.387039845f, 1.306562965f, + 1.175875602f, 1.0f, 0.785694958f, + 0.541196100f, 0.275899379f}; + uint8_t j, row, col; + std::array<uint8_t, 64> tempQT{}; + + // Load quantization coefficients from JPG file, scale them for DCT and + // reorder + // from zig-zag order + switch (ySelector) + { + case 0: + stdLuminanceQt = tbl000Y; + break; + case 1: + stdLuminanceQt = tbl014Y; + break; + case 2: + stdLuminanceQt = tbl029Y; + break; + case 3: + stdLuminanceQt = tbl043Y; + break; + case 4: + stdLuminanceQt = tbl057Y; + break; + case 5: + stdLuminanceQt = tbl071Y; + break; + case 6: + stdLuminanceQt = tbl086Y; + break; + case 7: + stdLuminanceQt = tbl100Y; + break; + } + setQuantTable(stdLuminanceQt, static_cast<uint8_t>(scalefactor), + tempQT); - for (j = 0; j <= 63; j++) { - quant_table[j] = tempQT[zigzag[j]]; - } - j = 0; - for (row = 0; row <= 7; row++) { - for (col = 0; col <= 7; col++) { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536); - j++; - } + for (j = 0; j <= 63; j++) + { + quant_table[j] = tempQT[zigzag[j]]; + } + j = 0; + for (row = 0; row <= 7; row++) + { + for (col = 0; col <= 7; col++) + { + quant_table[j] = static_cast<long>( + (quant_table[j] * scalefactorF[row] * scalefactorF[col]) * + 65536); + j++; + } + } + bytePos += 64; } - bytePos += 64; - } - - // Note: Added for Dual-JPEG - void loadAdvanceQuantTableCb(std::array<long, 64> &quant_table) { - float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, - 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder - // from zig-zag order - if (mapping == 1) { - switch (advanceSelector) { - case 0: - stdChrominanceQt = tbl000Y; - break; - case 1: - stdChrominanceQt = tbl014Y; - break; - case 2: - stdChrominanceQt = tbl029Y; - break; - case 3: - stdChrominanceQt = tbl043Y; - break; - case 4: - stdChrominanceQt = tbl057Y; - break; - case 5: - stdChrominanceQt = tbl071Y; - break; - case 6: - stdChrominanceQt = tbl086Y; - break; - case 7: - stdChrominanceQt = tbl100Y; - break; - } - } else { - switch (advanceSelector) { - case 0: - stdChrominanceQt = tbl000Uv; - break; - case 1: - stdChrominanceQt = tbl014Uv; - break; - case 2: - stdChrominanceQt = tbl029Uv; - break; - case 3: - stdChrominanceQt = tbl043Uv; - break; - case 4: - stdChrominanceQt = tbl057Uv; - break; - case 5: - stdChrominanceQt = tbl071Uv; - break; - case 6: - stdChrominanceQt = tbl086Uv; - break; - case 7: - stdChrominanceQt = tbl100Uv; - break; - } + + void loadQuantTableCb(std::array<long, 64> &quant_table) + { + float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, + 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; + uint8_t j, row, col; + std::array<uint8_t, 64> tempQT{}; + + // Load quantization coefficients from JPG file, scale them for DCT and + // reorder from zig-zag order + if (mapping == 0) + { + switch (uvSelector) + { + case 0: + stdChrominanceQt = tbl000Y; + break; + case 1: + stdChrominanceQt = tbl014Y; + break; + case 2: + stdChrominanceQt = tbl029Y; + break; + case 3: + stdChrominanceQt = tbl043Y; + break; + case 4: + stdChrominanceQt = tbl057Y; + break; + case 5: + stdChrominanceQt = tbl071Y; + break; + case 6: + stdChrominanceQt = tbl086Y; + break; + case 7: + stdChrominanceQt = tbl100Y; + break; + } + } + else + { + switch (uvSelector) + { + case 0: + stdChrominanceQt = tbl000Uv; + break; + case 1: + stdChrominanceQt = tbl014Uv; + break; + case 2: + stdChrominanceQt = tbl029Uv; + break; + case 3: + stdChrominanceQt = tbl043Uv; + break; + case 4: + stdChrominanceQt = tbl057Uv; + break; + case 5: + stdChrominanceQt = tbl071Uv; + break; + case 6: + stdChrominanceQt = tbl086Uv; + break; + case 7: + stdChrominanceQt = tbl100Uv; + break; + } + } + setQuantTable(stdChrominanceQt, static_cast<uint8_t>(scalefactoruv), + tempQT); + + for (j = 0; j <= 63; j++) + { + quant_table[j] = tempQT[zigzag[j]]; + } + j = 0; + for (row = 0; row <= 7; row++) + { + for (col = 0; col <= 7; col++) + { + quant_table[j] = static_cast<long>( + (quant_table[j] * scalefactor[row] * scalefactor[col]) * + 65536); + j++; + } + } + bytePos += 64; } - // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG - setQuantTable(stdChrominanceQt, static_cast<uint8_t>(advancescalefactoruv), - tempQT); + // Note: Added for Dual_JPEG + void loadAdvanceQuantTable(std::array<long, 64> &quant_table) + { + float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, + 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; + uint8_t j, row, col; + std::array<uint8_t, 64> tempQT{}; + + // Load quantization coefficients from JPG file, scale them for DCT and + // reorder + // from zig-zag order + switch (advanceSelector) + { + case 0: + stdLuminanceQt = tbl000Y; + break; + case 1: + stdLuminanceQt = tbl014Y; + break; + case 2: + stdLuminanceQt = tbl029Y; + break; + case 3: + stdLuminanceQt = tbl043Y; + break; + case 4: + stdLuminanceQt = tbl057Y; + break; + case 5: + stdLuminanceQt = tbl071Y; + break; + case 6: + stdLuminanceQt = tbl086Y; + break; + case 7: + stdLuminanceQt = tbl100Y; + break; + } + // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG + setQuantTable(stdLuminanceQt, static_cast<uint8_t>(advancescalefactor), + tempQT); - for (j = 0; j <= 63; j++) { - quant_table[j] = tempQT[zigzag[j]]; + for (j = 0; j <= 63; j++) + { + quant_table[j] = tempQT[zigzag[j]]; + } + j = 0; + for (row = 0; row <= 7; row++) + { + for (col = 0; col <= 7; col++) + { + quant_table[j] = static_cast<long>( + (quant_table[j] * scalefactor[row] * scalefactor[col]) * + 65536); + j++; + } + } + bytePos += 64; } - j = 0; - for (row = 0; row <= 7; row++) { - for (col = 0; col <= 7; col++) { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536); - j++; - } + + // Note: Added for Dual-JPEG + void loadAdvanceQuantTableCb(std::array<long, 64> &quant_table) + { + float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, + 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; + uint8_t j, row, col; + std::array<uint8_t, 64> tempQT{}; + + // Load quantization coefficients from JPG file, scale them for DCT and + // reorder + // from zig-zag order + if (mapping == 1) + { + switch (advanceSelector) + { + case 0: + stdChrominanceQt = tbl000Y; + break; + case 1: + stdChrominanceQt = tbl014Y; + break; + case 2: + stdChrominanceQt = tbl029Y; + break; + case 3: + stdChrominanceQt = tbl043Y; + break; + case 4: + stdChrominanceQt = tbl057Y; + break; + case 5: + stdChrominanceQt = tbl071Y; + break; + case 6: + stdChrominanceQt = tbl086Y; + break; + case 7: + stdChrominanceQt = tbl100Y; + break; + } + } + else + { + switch (advanceSelector) + { + case 0: + stdChrominanceQt = tbl000Uv; + break; + case 1: + stdChrominanceQt = tbl014Uv; + break; + case 2: + stdChrominanceQt = tbl029Uv; + break; + case 3: + stdChrominanceQt = tbl043Uv; + break; + case 4: + stdChrominanceQt = tbl057Uv; + break; + case 5: + stdChrominanceQt = tbl071Uv; + break; + case 6: + stdChrominanceQt = tbl086Uv; + break; + case 7: + stdChrominanceQt = tbl100Uv; + break; + } + } + // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG + setQuantTable(stdChrominanceQt, + static_cast<uint8_t>(advancescalefactoruv), tempQT); + + for (j = 0; j <= 63; j++) + { + quant_table[j] = tempQT[zigzag[j]]; + } + j = 0; + for (row = 0; row <= 7; row++) + { + for (col = 0; col <= 7; col++) + { + quant_table[j] = static_cast<long>( + (quant_table[j] * scalefactor[row] * scalefactor[col]) * + 65536); + j++; + } + } + bytePos += 64; } - bytePos += 64; - } - void idctTransform(short *coef, uint8_t *data, uint8_t nBlock) { + void idctTransform(short *coef, uint8_t *data, uint8_t nBlock) + { #define FIX_1_082392200 ((int)277) /* FIX(1.082392200) */ #define FIX_1_414213562 ((int)362) /* FIX(1.414213562) */ #define FIX_1_847759065 ((int)473) /* FIX(1.847759065) */ @@ -347,1008 +392,1156 @@ class AstJpegDecoder { #define MULTIPLY(var, cons) ((int)((var) * (cons)) >> 8) - int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - int tmp10, tmp11, tmp12, tmp13; - int z5, z10, z11, z12, z13; - int workspace[64]; /* buffers data between passes */ - - short *inptr = coef; - long *quantptr; - int *wsptr = workspace; - unsigned char *outptr; - unsigned char *rLimit = rlimitTable + 128; - int ctr, dcval, dctsize = 8; - - quantptr = &qt[nBlock][0]; - - // Pass 1: process columns from input (inptr), store into work array(wsptr) - - for (ctr = 8; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if ((inptr[dctsize * 1] | inptr[dctsize * 2] | inptr[dctsize * 3] | - inptr[dctsize * 4] | inptr[dctsize * 5] | inptr[dctsize * 6] | - inptr[dctsize * 7]) == 0) { - /* AC terms all zero */ - dcval = static_cast<int>((inptr[dctsize * 0] * quantptr[dctsize * 0]) >> - 16); - - wsptr[dctsize * 0] = dcval; - wsptr[dctsize * 1] = dcval; - wsptr[dctsize * 2] = dcval; - wsptr[dctsize * 3] = dcval; - wsptr[dctsize * 4] = dcval; - wsptr[dctsize * 5] = dcval; - wsptr[dctsize * 6] = dcval; - wsptr[dctsize * 7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16; - tmp1 = (inptr[dctsize * 2] * quantptr[dctsize * 2]) >> 16; - tmp2 = (inptr[dctsize * 4] * quantptr[dctsize * 4]) >> 16; - tmp3 = (inptr[dctsize * 6] * quantptr[dctsize * 6]) >> 16; - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = (inptr[dctsize * 1] * quantptr[dctsize * 1]) >> 16; - tmp5 = (inptr[dctsize * 3] * quantptr[dctsize * 3]) >> 16; - tmp6 = (inptr[dctsize * 5] * quantptr[dctsize * 5]) >> 16; - tmp7 = (inptr[dctsize * 7] * quantptr[dctsize * 7]) >> 16; - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[dctsize * 0] = (tmp0 + tmp7); - wsptr[dctsize * 7] = (tmp0 - tmp7); - wsptr[dctsize * 1] = (tmp1 + tmp6); - wsptr[dctsize * 6] = (tmp1 - tmp6); - wsptr[dctsize * 2] = (tmp2 + tmp5); - wsptr[dctsize * 5] = (tmp2 - tmp5); - wsptr[dctsize * 4] = (tmp3 + tmp4); - wsptr[dctsize * 3] = (tmp3 - tmp4); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z5, z10, z11, z12, z13; + int workspace[64]; /* buffers data between passes */ + + short *inptr = coef; + long *quantptr; + int *wsptr = workspace; + unsigned char *outptr; + unsigned char *rLimit = rlimitTable + 128; + int ctr, dcval, dctsize = 8; + + quantptr = &qt[nBlock][0]; + + // Pass 1: process columns from input (inptr), store into work + // array(wsptr) + + for (ctr = 8; ctr > 0; ctr--) + { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit + * this by short-circuiting the IDCT calculation for any column in + * which all the AC terms are zero. In that case each output is + * equal to the DC coefficient (with scale factor as needed). With + * typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if ((inptr[dctsize * 1] | inptr[dctsize * 2] | inptr[dctsize * 3] | + inptr[dctsize * 4] | inptr[dctsize * 5] | inptr[dctsize * 6] | + inptr[dctsize * 7]) == 0) + { + /* AC terms all zero */ + dcval = static_cast<int>( + (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16); + + wsptr[dctsize * 0] = dcval; + wsptr[dctsize * 1] = dcval; + wsptr[dctsize * 2] = dcval; + wsptr[dctsize * 3] = dcval; + wsptr[dctsize * 4] = dcval; + wsptr[dctsize * 5] = dcval; + wsptr[dctsize * 6] = dcval; + wsptr[dctsize * 7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } -/* Pass 2: process rows from work array, store into output array. */ -/* Note that we must descale the results by a factor of 8 == 2**3, */ -/* and also undo the PASS1_BITS scaling. */ + /* Even part */ -//#define RANGE_MASK 1023; //2 bits wider than legal samples -#define PASS1_BITS 0 -#define IDESCALE(x, n) ((int)((x) >> (n))) + tmp0 = (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16; + tmp1 = (inptr[dctsize * 2] * quantptr[dctsize * 2]) >> 16; + tmp2 = (inptr[dctsize * 4] * quantptr[dctsize * 4]) >> 16; + tmp3 = (inptr[dctsize * 6] * quantptr[dctsize * 6]) >> 16; - wsptr = workspace; - for (ctr = 0; ctr < dctsize; ctr++) { - outptr = data + ctr * 8; + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the - * time). On machines with very fast multiplication, it's possible that - * the test takes more time than it's worth. In that case this section - * may be commented out. - */ - /* Even part */ + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ - tmp10 = (wsptr[0] + wsptr[4]); - tmp11 = (wsptr[0] - wsptr[4]); + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; - tmp13 = (wsptr[2] + wsptr[6]); - tmp12 = MULTIPLY((int)wsptr[2] - (int)wsptr[6], FIX_1_414213562) - tmp13; + /* Odd part */ - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; + tmp4 = (inptr[dctsize * 1] * quantptr[dctsize * 1]) >> 16; + tmp5 = (inptr[dctsize * 3] * quantptr[dctsize * 3]) >> 16; + tmp6 = (inptr[dctsize * 5] * quantptr[dctsize * 5]) >> 16; + tmp7 = (inptr[dctsize * 7] * quantptr[dctsize * 7]) >> 16; - /* Odd part */ + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; - z13 = wsptr[5] + wsptr[3]; - z10 = wsptr[5] - wsptr[3]; - z11 = wsptr[1] + wsptr[7]; - z12 = wsptr[1] - wsptr[7]; + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + wsptr[dctsize * 0] = (tmp0 + tmp7); + wsptr[dctsize * 7] = (tmp0 - tmp7); + wsptr[dctsize * 1] = (tmp1 + tmp6); + wsptr[dctsize * 6] = (tmp1 - tmp6); + wsptr[dctsize * 2] = (tmp2 + tmp5); + wsptr[dctsize * 5] = (tmp2 - tmp5); + wsptr[dctsize * 4] = (tmp3 + tmp4); + wsptr[dctsize * 3] = (tmp3 - tmp4); - /* Final output stage: scale down by a factor of 8 and range-limit */ + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } - outptr[0] = rLimit[IDESCALE((tmp0 + tmp7), (PASS1_BITS + 3)) & 1023L]; - outptr[7] = rLimit[IDESCALE((tmp0 - tmp7), (PASS1_BITS + 3)) & 1023L]; - outptr[1] = rLimit[IDESCALE((tmp1 + tmp6), (PASS1_BITS + 3)) & 1023L]; - outptr[6] = rLimit[IDESCALE((tmp1 - tmp6), (PASS1_BITS + 3)) & 1023L]; - outptr[2] = rLimit[IDESCALE((tmp2 + tmp5), (PASS1_BITS + 3)) & 1023L]; - outptr[5] = rLimit[IDESCALE((tmp2 - tmp5), (PASS1_BITS + 3)) & 1023L]; - outptr[4] = rLimit[IDESCALE((tmp3 + tmp4), (PASS1_BITS + 3)) & 1023L]; - outptr[3] = rLimit[IDESCALE((tmp3 - tmp4), (PASS1_BITS + 3)) & 1023L]; +/* Pass 2: process rows from work array, store into output array. */ +/* Note that we must descale the results by a factor of 8 == 2**3, */ +/* and also undo the PASS1_BITS scaling. */ + +//#define RANGE_MASK 1023; //2 bits wider than legal samples +#define PASS1_BITS 0 +#define IDESCALE(x, n) ((int)((x) >> (n))) - wsptr += dctsize; /* advance pointer to next row */ + wsptr = workspace; + for (ctr = 0; ctr < dctsize; ctr++) + { + outptr = data + ctr * 8; + + /* Rows of zeroes can be exploited in the same way as we did with + * columns. However, the column calculation has created many nonzero + * AC terms, so the simplification applies less often (typically 5% + * to 10% of the time). On machines with very fast multiplication, + * it's possible that the test takes more time than it's worth. In + * that case this section may be commented out. + */ + /* Even part */ + + tmp10 = (wsptr[0] + wsptr[4]); + tmp11 = (wsptr[0] - wsptr[4]); + + tmp13 = (wsptr[2] + wsptr[6]); + tmp12 = MULTIPLY((int)wsptr[2] - (int)wsptr[6], FIX_1_414213562) - + tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit + */ + + outptr[0] = + rLimit[IDESCALE((tmp0 + tmp7), (PASS1_BITS + 3)) & 1023L]; + outptr[7] = + rLimit[IDESCALE((tmp0 - tmp7), (PASS1_BITS + 3)) & 1023L]; + outptr[1] = + rLimit[IDESCALE((tmp1 + tmp6), (PASS1_BITS + 3)) & 1023L]; + outptr[6] = + rLimit[IDESCALE((tmp1 - tmp6), (PASS1_BITS + 3)) & 1023L]; + outptr[2] = + rLimit[IDESCALE((tmp2 + tmp5), (PASS1_BITS + 3)) & 1023L]; + outptr[5] = + rLimit[IDESCALE((tmp2 - tmp5), (PASS1_BITS + 3)) & 1023L]; + outptr[4] = + rLimit[IDESCALE((tmp3 + tmp4), (PASS1_BITS + 3)) & 1023L]; + outptr[3] = + rLimit[IDESCALE((tmp3 - tmp4), (PASS1_BITS + 3)) & 1023L]; + + wsptr += dctsize; /* advance pointer to next row */ + } } - } - void yuvToRgb( - int txb, int tyb, - unsigned char - *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes - struct RGB *pYUV, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes - unsigned char - *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes - ) { - int i, j, pos, m, n; - unsigned char cb, cr, *py, *pcb, *pcr, *py420[4]; - int y; - struct RGB *pByte; - int nBlocksInMcu = 6; - unsigned int pixelX, pixelY; - - pByte = reinterpret_cast<struct RGB *>(pBgr); - if (yuvmode == YuvMode::YUV444) { - py = pYCbCr; - pcb = pYCbCr + 64; - pcr = pcb + 64; - - pixelX = txb * 8; - pixelY = tyb * 8; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 8; j++) { - for (i = 0; i < 8; i++) { - m = ((j << 3) + i); - y = py[m]; - cb = pcb[m]; - cr = pcr[m]; - n = pos + i; - // For 2Pass. Save the YUV value - pYUV[n].b = cb; - pYUV[n].g = y; - pYUV[n].r = cr; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + void yuvToRgb( + int txb, int tyb, + unsigned char + *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes + struct RGB *pYUV, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes + unsigned char + *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes + ) + { + int i, j, pos, m, n; + unsigned char cb, cr, *py, *pcb, *pcr, *py420[4]; + int y; + struct RGB *pByte; + int nBlocksInMcu = 6; + unsigned int pixelX, pixelY; + + pByte = reinterpret_cast<struct RGB *>(pBgr); + if (yuvmode == YuvMode::YUV444) + { + py = pYCbCr; + pcb = pYCbCr + 64; + pcr = pcb + 64; + + pixelX = txb * 8; + pixelY = tyb * 8; + pos = (pixelY * width) + pixelX; + + for (j = 0; j < 8; j++) + { + for (i = 0; i < 8; i++) + { + m = ((j << 3) + i); + y = py[m]; + cb = pcb[m]; + cr = pcr[m]; + n = pos + i; + // For 2Pass. Save the YUV value + pYUV[n].b = cb; + pYUV[n].g = y; + pYUV[n].r = cr; + pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; + pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; + pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + } + pos += width; + } } - pos += width; - } - } else { - for (i = 0; i < nBlocksInMcu - 2; i++) { - py420[i] = pYCbCr + i * 64; - } - pcb = pYCbCr + (nBlocksInMcu - 2) * 64; - pcr = pcb + 64; - - pixelX = txb * 16; - pixelY = tyb * 16; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 16; j++) { - for (i = 0; i < 16; i++) { - // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3} - y = *(py420[(j >> 3) * 2 + (i >> 3)]++); - m = ((j >> 1) << 3) + (i >> 1); - cb = pcb[m]; - cr = pcr[m]; - n = pos + i; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + else + { + for (i = 0; i < nBlocksInMcu - 2; i++) + { + py420[i] = pYCbCr + i * 64; + } + pcb = pYCbCr + (nBlocksInMcu - 2) * 64; + pcr = pcb + 64; + + pixelX = txb * 16; + pixelY = tyb * 16; + pos = (pixelY * width) + pixelX; + + for (j = 0; j < 16; j++) + { + for (i = 0; i < 16; i++) + { + // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3} + y = *(py420[(j >> 3) * 2 + (i >> 3)]++); + m = ((j >> 1) << 3) + (i >> 1); + cb = pcb[m]; + cr = pcr[m]; + n = pos + i; + pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; + pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; + pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + } + pos += width; + } } - pos += width; - } } - } - void yuvToBuffer( - int txb, int tyb, - unsigned char - *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes - struct RGB - *pYUV, // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes - unsigned char - *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes - ) { - int i, j, pos, m, n; - unsigned char cb, cr, *py, *pcb, *pcr, *py420[4]; - int y; - struct RGB *pByte; - int nBlocksInMcu = 6; - unsigned int pixelX, pixelY; - - pByte = reinterpret_cast<struct RGB *>(pBgr); - if (yuvmode == YuvMode::YUV444) { - py = pYCbCr; - pcb = pYCbCr + 64; - pcr = pcb + 64; - - pixelX = txb * 8; - pixelY = tyb * 8; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 8; j++) { - for (i = 0; i < 8; i++) { - m = ((j << 3) + i); - n = pos + i; - y = pYUV[n].g + (py[m] - 128); - cb = pYUV[n].b + (pcb[m] - 128); - cr = pYUV[n].r + (pcr[m] - 128); - pYUV[n].b = cb; - pYUV[n].g = y; - pYUV[n].r = cr; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + void yuvToBuffer( + int txb, int tyb, + unsigned char + *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes + struct RGB + *pYUV, // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes + unsigned char + *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes + ) + { + int i, j, pos, m, n; + unsigned char cb, cr, *py, *pcb, *pcr, *py420[4]; + int y; + struct RGB *pByte; + int nBlocksInMcu = 6; + unsigned int pixelX, pixelY; + + pByte = reinterpret_cast<struct RGB *>(pBgr); + if (yuvmode == YuvMode::YUV444) + { + py = pYCbCr; + pcb = pYCbCr + 64; + pcr = pcb + 64; + + pixelX = txb * 8; + pixelY = tyb * 8; + pos = (pixelY * width) + pixelX; + + for (j = 0; j < 8; j++) + { + for (i = 0; i < 8; i++) + { + m = ((j << 3) + i); + n = pos + i; + y = pYUV[n].g + (py[m] - 128); + cb = pYUV[n].b + (pcb[m] - 128); + cr = pYUV[n].r + (pcr[m] - 128); + pYUV[n].b = cb; + pYUV[n].g = y; + pYUV[n].r = cr; + pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; + pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; + pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + } + pos += width; + } } - pos += width; - } - } else { - for (i = 0; i < nBlocksInMcu - 2; i++) { - py420[i] = pYCbCr + i * 64; - } - pcb = pYCbCr + (nBlocksInMcu - 2) * 64; - pcr = pcb + 64; - - pixelX = txb * 16; - pixelY = tyb * 16; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 16; j++) { - for (i = 0; i < 16; i++) { - // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3} - y = *(py420[(j >> 3) * 2 + (i >> 3)]++); - m = ((j >> 1) << 3) + (i >> 1); - cb = pcb[m]; - cr = pcr[m]; - n = pos + i; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + else + { + for (i = 0; i < nBlocksInMcu - 2; i++) + { + py420[i] = pYCbCr + i * 64; + } + pcb = pYCbCr + (nBlocksInMcu - 2) * 64; + pcr = pcb + 64; + + pixelX = txb * 16; + pixelY = tyb * 16; + pos = (pixelY * width) + pixelX; + + for (j = 0; j < 16; j++) + { + for (i = 0; i < 16; i++) + { + // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3} + y = *(py420[(j >> 3) * 2 + (i >> 3)]++); + m = ((j >> 1) << 3) + (i >> 1); + cb = pcb[m]; + cr = pcr[m]; + n = pos + i; + pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; + pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; + pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; + } + pos += width; + } } - pos += width; - } } - } - void decompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection) { - unsigned char *ptr; - unsigned char byTileYuv[768] = {}; - - memset(dctCoeff, 0, 384 * 2); - ptr = byTileYuv; - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0); - idctTransform(dctCoeff, ptr, QT_TableSelection); - ptr += 64; - - if (yuvmode == YuvMode::YUV420) { - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 64); - idctTransform(dctCoeff + 64, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 128); - idctTransform(dctCoeff + 128, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 192); - idctTransform(dctCoeff + 192, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 256); - idctTransform(dctCoeff + 256, ptr, QT_TableSelection + 1); - ptr += 64; - - processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 320); - idctTransform(dctCoeff + 320, ptr, QT_TableSelection + 1); - } else { - processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64); - idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1); - ptr += 64; - - processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128); - idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1); - } - - // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); - // yuvBuffer for YUV record - yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(), - reinterpret_cast<unsigned char *>(outBuf)); - } - - void decompress2Pass(int txb, int tyb, char *outBuf, - uint8_t QT_TableSelection) { - unsigned char *ptr; - unsigned char byTileYuv[768]; - memset(dctCoeff, 0, 384 * 2); - - ptr = byTileYuv; - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0); - idctTransform(dctCoeff, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64); - idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1); - ptr += 64; - - processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128); - idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1); - - yuvToBuffer(txb, tyb, byTileYuv, yuvBuffer.data(), - reinterpret_cast<unsigned char *>(outBuf)); - // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); - } - - void vqDecompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection, - struct ColorCache *VQ) { - unsigned char *ptr, i; - unsigned char byTileYuv[192]; - int data; - - ptr = byTileYuv; - if (VQ->bitMapBits == 0) { - for (i = 0; i < 64; i++) { - ptr[0] = (VQ->color[VQ->index[0]] & 0xFF0000) >> 16; - ptr[64] = (VQ->color[VQ->index[0]] & 0x00FF00) >> 8; - ptr[128] = VQ->color[VQ->index[0]] & 0x0000FF; - ptr += 1; - } - } else { - for (i = 0; i < 64; i++) { - data = static_cast<int>(lookKbits(VQ->bitMapBits)); - ptr[0] = (VQ->color[VQ->index[data]] & 0xFF0000) >> 16; - ptr[64] = (VQ->color[VQ->index[data]] & 0x00FF00) >> 8; - ptr[128] = VQ->color[VQ->index[data]] & 0x0000FF; - ptr += 1; - skipKbits(VQ->bitMapBits); - } - } - // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); - yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(), - reinterpret_cast<unsigned char *>(outBuf)); - } - - void moveBlockIndex() { - if (yuvmode == YuvMode::YUV444) { - txb++; - if (txb >= static_cast<int>(width / 8)) { - tyb++; - if (tyb >= static_cast<int>(height / 8)) { - tyb = 0; + void decompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection) + { + unsigned char *ptr; + unsigned char byTileYuv[768] = {}; + + memset(dctCoeff, 0, 384 * 2); + ptr = byTileYuv; + processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0); + idctTransform(dctCoeff, ptr, QT_TableSelection); + ptr += 64; + + if (yuvmode == YuvMode::YUV420) + { + processHuffmanDataUnit(ydcNr, yacNr, &dcy, 64); + idctTransform(dctCoeff + 64, ptr, QT_TableSelection); + ptr += 64; + + processHuffmanDataUnit(ydcNr, yacNr, &dcy, 128); + idctTransform(dctCoeff + 128, ptr, QT_TableSelection); + ptr += 64; + + processHuffmanDataUnit(ydcNr, yacNr, &dcy, 192); + idctTransform(dctCoeff + 192, ptr, QT_TableSelection); + ptr += 64; + + processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 256); + idctTransform(dctCoeff + 256, ptr, QT_TableSelection + 1); + ptr += 64; + + processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 320); + idctTransform(dctCoeff + 320, ptr, QT_TableSelection + 1); } - txb = 0; - } - } else { - txb++; - if (txb >= static_cast<int>(width / 16)) { - tyb++; - if (tyb >= static_cast<int>(height / 16)) { - tyb = 0; + else + { + processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64); + idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1); + ptr += 64; + + processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128); + idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1); } - txb = 0; - } + + // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); + // yuvBuffer for YUV record + yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(), + reinterpret_cast<unsigned char *>(outBuf)); } - } - void initColorTable() { - int i, x; - int nScale = 1L << 16; // equal to power(2,16) - int nHalf = nScale >> 1; + void decompress2Pass(int txb, int tyb, char *outBuf, + uint8_t QT_TableSelection) + { + unsigned char *ptr; + unsigned char byTileYuv[768]; + memset(dctCoeff, 0, 384 * 2); -#define FIX(x) ((int)((x)*nScale + 0.5)) + ptr = byTileYuv; + processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0); + idctTransform(dctCoeff, ptr, QT_TableSelection); + ptr += 64; - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>r value is nearest int to 1.597656 * x */ - /* Cb=>b value is nearest int to 2.015625 * x */ - /* Cr=>g value is scaled-up -0.8125 * x */ - /* Cb=>g value is scaled-up -0.390625 * x */ - for (i = 0, x = -128; i < 256; i++, x++) { - mCrToR[i] = (FIX(1.597656) * x + nHalf) >> 16; - mCbToB[i] = (FIX(2.015625) * x + nHalf) >> 16; - mCrToG[i] = (-FIX(0.8125) * x + nHalf) >> 16; - mCbToG[i] = (-FIX(0.390625) * x + nHalf) >> 16; - } - for (i = 0, x = -16; i < 256; i++, x++) { - mY[i] = (FIX(1.164) * x + nHalf) >> 16; + processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64); + idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1); + ptr += 64; + + processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128); + idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1); + + yuvToBuffer(txb, tyb, byTileYuv, yuvBuffer.data(), + reinterpret_cast<unsigned char *>(outBuf)); + // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); } - // For color Text Enchance Y Re-map. Recommend to disable in default - /* - for (i = 0; i < (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); - i++) { - temp = (double)i / - VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate; - temp1 = 1.0 / VideoEngineInfo->INFData.Gamma1Parameter; - mY[i] = - (BYTE)(VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate * pow (temp, - temp1)); - if (mY[i] > 255) mY[i] = 255; + + void vqDecompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection, + struct ColorCache *VQ) + { + unsigned char *ptr, i; + unsigned char byTileYuv[192]; + int data; + + ptr = byTileYuv; + if (VQ->bitMapBits == 0) + { + for (i = 0; i < 64; i++) + { + ptr[0] = (VQ->color[VQ->index[0]] & 0xFF0000) >> 16; + ptr[64] = (VQ->color[VQ->index[0]] & 0x00FF00) >> 8; + ptr[128] = VQ->color[VQ->index[0]] & 0x0000FF; + ptr += 1; } - for (i = (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i < 256; - i++) { - mY[i] = - (BYTE)((VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) + (256 - - VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) * ( pow((double)((i - - VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) / (256 - - (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate))), (1.0 / - VideoEngineInfo->INFData.Gamma2Parameter)) )); - if (mY[i] > 255) mY[i] = 255; + } + else + { + for (i = 0; i < 64; i++) + { + data = static_cast<int>(lookKbits(VQ->bitMapBits)); + ptr[0] = (VQ->color[VQ->index[data]] & 0xFF0000) >> 16; + ptr[64] = (VQ->color[VQ->index[data]] & 0x00FF00) >> 8; + ptr[128] = VQ->color[VQ->index[data]] & 0x0000FF; + ptr += 1; + skipKbits(VQ->bitMapBits); } - */ - } - void loadHuffmanTable(HuffmanTable *HT, const unsigned char *nrcode, - const unsigned char *value, - const unsigned short int *Huff_code) { - unsigned char k, j, i; - unsigned int code, codeIndex; - - for (j = 1; j <= 16; j++) { - HT->length[j] = nrcode[j]; - } - for (i = 0, k = 1; k <= 16; k++) { - for (j = 0; j < HT->length[k]; j++) { - HT->v[wordHiLo(k, j)] = value[i]; - i++; - } + } + // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); + yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(), + reinterpret_cast<unsigned char *>(outBuf)); } - code = 0; - for (k = 1; k <= 16; k++) { - HT->minorCode[k] = static_cast<unsigned short int>(code); - for (j = 1; j <= HT->length[k]; j++) { - code++; - } - HT->majorCode[k] = static_cast<unsigned short int>(code - 1); - code *= 2; - if (HT->length[k] == 0) { - HT->minorCode[k] = 0xFFFF; - HT->majorCode[k] = 0; - } + void moveBlockIndex() + { + if (yuvmode == YuvMode::YUV444) + { + txb++; + if (txb >= static_cast<int>(width / 8)) + { + tyb++; + if (tyb >= static_cast<int>(height / 8)) + { + tyb = 0; + } + txb = 0; + } + } + else + { + txb++; + if (txb >= static_cast<int>(width / 16)) + { + tyb++; + if (tyb >= static_cast<int>(height / 16)) + { + tyb = 0; + } + txb = 0; + } + } } - HT->len[0] = 2; - i = 2; + void initColorTable() + { + int i, x; + int nScale = 1L << 16; // equal to power(2,16) + int nHalf = nScale >> 1; - for (codeIndex = 1; codeIndex < 65535; codeIndex++) { - if (codeIndex < Huff_code[i]) { - HT->len[codeIndex] = static_cast<unsigned char>(Huff_code[i + 1]); - } else { - i = i + 2; - HT->len[codeIndex] = static_cast<unsigned char>(Huff_code[i + 1]); - } - } - } - void initJpgTable() { - initColorTable(); - prepareRangeLimitTable(); - loadHuffmanTable(&htdc[0], stdDcLuminanceNrcodes, stdDcLuminanceValues, - dcLuminanceHuffmancode); - loadHuffmanTable(&htac[0], stdAcLuminanceNrcodes, stdAcLuminanceValues, - acLuminanceHuffmancode); - loadHuffmanTable(&htdc[1], stdDcChrominanceNrcodes, stdDcChrominanceValues, - dcChrominanceHuffmancode); - loadHuffmanTable(&htac[1], stdAcChrominanceNrcodes, stdAcChrominanceValues, - acChrominanceHuffmancode); - } - - void prepareRangeLimitTable() - /* Allocate and fill in the sample_range_limit table */ - { - int j; - rlimitTable = reinterpret_cast<unsigned char *>(malloc(5 * 256L + 128)); - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - memset((void *)rlimitTable, 0, 256); - rlimitTable += 256; /* allow negative subscripts of simple table */ - /* Main part of "simple" table: limit[x] = x */ - for (j = 0; j < 256; j++) { - rlimitTable[j] = j; - } - /* End of simple table, rest of first half of post-IDCT table */ - for (j = 256; j < 640; j++) { - rlimitTable[j] = 255; +#define FIX(x) ((int)((x)*nScale + 0.5)) + + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>r value is nearest int to 1.597656 * x */ + /* Cb=>b value is nearest int to 2.015625 * x */ + /* Cr=>g value is scaled-up -0.8125 * x */ + /* Cb=>g value is scaled-up -0.390625 * x */ + for (i = 0, x = -128; i < 256; i++, x++) + { + mCrToR[i] = (FIX(1.597656) * x + nHalf) >> 16; + mCbToB[i] = (FIX(2.015625) * x + nHalf) >> 16; + mCrToG[i] = (-FIX(0.8125) * x + nHalf) >> 16; + mCbToG[i] = (-FIX(0.390625) * x + nHalf) >> 16; + } + for (i = 0, x = -16; i < 256; i++, x++) + { + mY[i] = (FIX(1.164) * x + nHalf) >> 16; + } + // For color Text Enchance Y Re-map. Recommend to disable in default + /* + for (i = 0; i < + (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i++) { temp = + (double)i / VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate; temp1 + = 1.0 / VideoEngineInfo->INFData.Gamma1Parameter; mY[i] = + (BYTE)(VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate * pow (temp, + temp1)); + if (mY[i] > 255) mY[i] = 255; + } + for (i = (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i < + 256; i++) { mY[i] = + (BYTE)((VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) + (256 - + VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) * ( pow((double)((i + - VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) / (256 - + (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate))), (1.0 / + VideoEngineInfo->INFData.Gamma2Parameter)) )); + if (mY[i] > 255) mY[i] = 255; + } + */ } + void loadHuffmanTable(HuffmanTable *HT, const unsigned char *nrcode, + const unsigned char *value, + const unsigned short int *Huff_code) + { + unsigned char k, j, i; + unsigned int code, codeIndex; + + for (j = 1; j <= 16; j++) + { + HT->length[j] = nrcode[j]; + } + for (i = 0, k = 1; k <= 16; k++) + { + for (j = 0; j < HT->length[k]; j++) + { + HT->v[wordHiLo(k, j)] = value[i]; + i++; + } + } + + code = 0; + for (k = 1; k <= 16; k++) + { + HT->minorCode[k] = static_cast<unsigned short int>(code); + for (j = 1; j <= HT->length[k]; j++) + { + code++; + } + HT->majorCode[k] = static_cast<unsigned short int>(code - 1); + code *= 2; + if (HT->length[k] == 0) + { + HT->minorCode[k] = 0xFFFF; + HT->majorCode[k] = 0; + } + } + + HT->len[0] = 2; + i = 2; - /* Second half of post-IDCT table */ - memset((void *)(rlimitTable + 640), 0, 384); - for (j = 0; j < 128; j++) { - rlimitTable[j + 1024] = j; + for (codeIndex = 1; codeIndex < 65535; codeIndex++) + { + if (codeIndex < Huff_code[i]) + { + HT->len[codeIndex] = + static_cast<unsigned char>(Huff_code[i + 1]); + } + else + { + i = i + 2; + HT->len[codeIndex] = + static_cast<unsigned char>(Huff_code[i + 1]); + } + } } - } - - inline unsigned short int wordHiLo(uint8_t byte_high, uint8_t byte_low) { - return (byte_high << 8) + byte_low; - } - - // river - void processHuffmanDataUnit(uint8_t DC_nr, uint8_t AC_nr, - signed short int *previous_DC, - unsigned short int position) { - uint8_t nr = 0; - uint8_t k; - unsigned short int tmpHcode; - uint8_t sizeVal, count0; - unsigned short int *minCode; - uint8_t *huffValues; - uint8_t byteTemp; - - minCode = htdc[DC_nr].minorCode; - // maj_code=htdc[DC_nr].majorCode; - huffValues = htdc[DC_nr].v; - - // DC - k = htdc[DC_nr].len[static_cast<unsigned short int>(codebuf >> 16)]; - // river - // tmp_Hcode=lookKbits(k); - tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k)); - skipKbits(k); - sizeVal = - huffValues[wordHiLo(k, static_cast<uint8_t>(tmpHcode - minCode[k]))]; - if (sizeVal == 0) { - dctCoeff[position + 0] = *previous_DC; - } else { - dctCoeff[position + 0] = *previous_DC + getKbits(sizeVal); - *previous_DC = dctCoeff[position + 0]; + void initJpgTable() + { + initColorTable(); + prepareRangeLimitTable(); + loadHuffmanTable(&htdc[0], stdDcLuminanceNrcodes, stdDcLuminanceValues, + dcLuminanceHuffmancode); + loadHuffmanTable(&htac[0], stdAcLuminanceNrcodes, stdAcLuminanceValues, + acLuminanceHuffmancode); + loadHuffmanTable(&htdc[1], stdDcChrominanceNrcodes, + stdDcChrominanceValues, dcChrominanceHuffmancode); + loadHuffmanTable(&htac[1], stdAcChrominanceNrcodes, + stdAcChrominanceValues, acChrominanceHuffmancode); } - // Second, AC coefficient decoding - minCode = htac[AC_nr].minorCode; - // maj_code=htac[AC_nr].majorCode; - huffValues = htac[AC_nr].v; - - nr = 1; // AC coefficient - do { - k = htac[AC_nr].len[static_cast<unsigned short int>(codebuf >> 16)]; - tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k)); - skipKbits(k); - - byteTemp = - huffValues[wordHiLo(k, static_cast<uint8_t>(tmpHcode - minCode[k]))]; - sizeVal = byteTemp & 0xF; - count0 = byteTemp >> 4; - if (sizeVal == 0) { - if (count0 != 0xF) { - break; + void prepareRangeLimitTable() + /* Allocate and fill in the sample_range_limit table */ + { + int j; + rlimitTable = reinterpret_cast<unsigned char *>(malloc(5 * 256L + 128)); + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset((void *)rlimitTable, 0, 256); + rlimitTable += 256; /* allow negative subscripts of simple table */ + /* Main part of "simple" table: limit[x] = x */ + for (j = 0; j < 256; j++) + { + rlimitTable[j] = j; + } + /* End of simple table, rest of first half of post-IDCT table */ + for (j = 256; j < 640; j++) + { + rlimitTable[j] = 255; + } + + /* Second half of post-IDCT table */ + memset((void *)(rlimitTable + 640), 0, 384); + for (j = 0; j < 128; j++) + { + rlimitTable[j + 1024] = j; } - nr += 16; - } else { - nr += count0; // skip count_0 zeroes - dctCoeff[position + dezigzag[nr++]] = getKbits(sizeVal); - } - } while (nr < 64); - } - - unsigned short int lookKbits(uint8_t k) { - unsigned short int revcode; - - revcode = static_cast<unsigned short int>(codebuf >> (32 - k)); - - return (revcode); - } - - void skipKbits(uint8_t k) { - unsigned long readbuf; - - if ((newbits - k) <= 0) { - readbuf = buffer[bufferIndex]; - bufferIndex++; - codebuf = - (codebuf << k) | ((newbuf | (readbuf >> (newbits))) >> (32 - k)); - newbuf = readbuf << (k - newbits); - newbits = 32 + newbits - k; - } else { - codebuf = (codebuf << k) | (newbuf >> (32 - k)); - newbuf = newbuf << k; - newbits -= k; } - } - signed short int getKbits(uint8_t k) { - signed short int signedWordvalue; + inline unsigned short int wordHiLo(uint8_t byte_high, uint8_t byte_low) + { + return (byte_high << 8) + byte_low; + } // river - // signed_wordvalue=lookKbits(k); - signedWordvalue = static_cast<unsigned short int>(codebuf >> (32 - k)); - if (((1L << (k - 1)) & signedWordvalue) == 0) { - // neg_pow2 was previously defined as the below. It seemed silly to keep - // a table of values around for something - // THat's relatively easy to compute, so it was replaced with the - // appropriate math - // signed_wordvalue = signed_wordvalue - (0xFFFF >> (16 - k)); - std::array<signed short int, 17> negPow2 = { - 0, -1, -3, -7, -15, -31, -63, -127, - -255, -511, -1023, -2047, -4095, -8191, -16383, -32767}; - - signedWordvalue = signedWordvalue + negPow2[k]; - } - skipKbits(k); - return signedWordvalue; - } - int initJpgDecoding() { - bytePos = 0; - loadQuantTable(qt[0]); - loadQuantTableCb(qt[1]); - // Note: Added for Dual-JPEG - loadAdvanceQuantTable(qt[2]); - loadAdvanceQuantTableCb(qt[3]); - return 1; - } - - void setQuantTable(const uint8_t *basic_table, uint8_t scale_factor, - std::array<uint8_t, 64> &newtable) - // Set quantization table and zigzag reorder it - { - uint8_t i; - long temp; - for (i = 0; i < 64; i++) { - temp = (static_cast<long>(basic_table[i] * 16) / scale_factor); - /* limit the values to the valid range */ - if (temp <= 0L) { - temp = 1L; - } - if (temp > 255L) { - temp = 255L; /* limit to baseline range if requested */ - } - newtable[zigzag[i]] = static_cast<uint8_t>(temp); - } - } - - void updatereadbuf(uint32_t *codebuf, uint32_t *newbuf, int walks, - int *newbits, std::vector<uint32_t> &buffer) { - unsigned long readbuf; - - if ((*newbits - walks) <= 0) { - readbuf = buffer[bufferIndex]; - bufferIndex++; - *codebuf = (*codebuf << walks) | - ((*newbuf | (readbuf >> (*newbits))) >> (32 - walks)); - *newbuf = readbuf << (walks - *newbits); - *newbits = 32 + *newbits - walks; - } else { - *codebuf = (*codebuf << walks) | (*newbuf >> (32 - walks)); - *newbuf = *newbuf << walks; - *newbits -= walks; - } - } - - uint32_t decode(std::vector<uint32_t> &bufferVector, unsigned long width, - unsigned long height, YuvMode yuvmode_in, int ySelector, - int uvSelector) { - ColorCache decodeColor; - if (width != userWidth || height != userHeight || yuvmode_in != yuvmode || - ySelector != ySelector || uvSelector != uvSelector) { - yuvmode = yuvmode_in; - ySelector = ySelector; // 0-7 - uvSelector = uvSelector; // 0-7 - userHeight = height; - userWidth = width; - width = width; - height = height; - - // TODO(ed) Magic number section. Document appropriately - advanceSelector = 0; // 0-7 - mapping = 0; // 0 or 1 - - if (yuvmode == YuvMode::YUV420) { - if ((width % 16) != 0u) { - width = width + 16 - (width % 16); + void processHuffmanDataUnit(uint8_t DC_nr, uint8_t AC_nr, + signed short int *previous_DC, + unsigned short int position) + { + uint8_t nr = 0; + uint8_t k; + unsigned short int tmpHcode; + uint8_t sizeVal, count0; + unsigned short int *minCode; + uint8_t *huffValues; + uint8_t byteTemp; + + minCode = htdc[DC_nr].minorCode; + // maj_code=htdc[DC_nr].majorCode; + huffValues = htdc[DC_nr].v; + + // DC + k = htdc[DC_nr].len[static_cast<unsigned short int>(codebuf >> 16)]; + // river + // tmp_Hcode=lookKbits(k); + tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k)); + skipKbits(k); + sizeVal = huffValues[wordHiLo( + k, static_cast<uint8_t>(tmpHcode - minCode[k]))]; + if (sizeVal == 0) + { + dctCoeff[position + 0] = *previous_DC; } - if ((height % 16) != 0u) { - height = height + 16 - (height % 16); + else + { + dctCoeff[position + 0] = *previous_DC + getKbits(sizeVal); + *previous_DC = dctCoeff[position + 0]; } - } else { - if ((width % 8) != 0u) { - width = width + 8 - (width % 8); + + // Second, AC coefficient decoding + minCode = htac[AC_nr].minorCode; + // maj_code=htac[AC_nr].majorCode; + huffValues = htac[AC_nr].v; + + nr = 1; // AC coefficient + do + { + k = htac[AC_nr].len[static_cast<unsigned short int>(codebuf >> 16)]; + tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k)); + skipKbits(k); + + byteTemp = huffValues[wordHiLo( + k, static_cast<uint8_t>(tmpHcode - minCode[k]))]; + sizeVal = byteTemp & 0xF; + count0 = byteTemp >> 4; + if (sizeVal == 0) + { + if (count0 != 0xF) + { + break; + } + nr += 16; + } + else + { + nr += count0; // skip count_0 zeroes + dctCoeff[position + dezigzag[nr++]] = getKbits(sizeVal); + } + } while (nr < 64); + } + + unsigned short int lookKbits(uint8_t k) + { + unsigned short int revcode; + + revcode = static_cast<unsigned short int>(codebuf >> (32 - k)); + + return (revcode); + } + + void skipKbits(uint8_t k) + { + unsigned long readbuf; + + if ((newbits - k) <= 0) + { + readbuf = buffer[bufferIndex]; + bufferIndex++; + codebuf = (codebuf << k) | + ((newbuf | (readbuf >> (newbits))) >> (32 - k)); + newbuf = readbuf << (k - newbits); + newbits = 32 + newbits - k; } - if ((height % 8) != 0u) { - height = height + 8 - (height % 8); + else + { + codebuf = (codebuf << k) | (newbuf >> (32 - k)); + newbuf = newbuf << k; + newbits -= k; } - } + } - initJpgDecoding(); + signed short int getKbits(uint8_t k) + { + signed short int signedWordvalue; + + // river + // signed_wordvalue=lookKbits(k); + signedWordvalue = static_cast<unsigned short int>(codebuf >> (32 - k)); + if (((1L << (k - 1)) & signedWordvalue) == 0) + { + // neg_pow2 was previously defined as the below. It seemed silly to + // keep a table of values around for something THat's relatively + // easy to compute, so it was replaced with the appropriate math + // signed_wordvalue = signed_wordvalue - (0xFFFF >> (16 - k)); + std::array<signed short int, 17> negPow2 = { + 0, -1, -3, -7, -15, -31, -63, -127, + -255, -511, -1023, -2047, -4095, -8191, -16383, -32767}; + + signedWordvalue = signedWordvalue + negPow2[k]; + } + skipKbits(k); + return signedWordvalue; } - // TODO(ed) cleanup cruft - buffer = bufferVector.data(); - - codebuf = bufferVector[0]; - newbuf = bufferVector[1]; - bufferIndex = 2; - - txb = tyb = 0; - newbits = 32; - dcy = dcCb = dcCr = 0; - - static const uint32_t vqHeaderMask = 0x01; - static const uint32_t vqNoUpdateHeader = 0x00; - static const uint32_t vqUpdateHeader = 0x01; - static const int vqNoUpdateLength = 0x03; - static const int vqUpdateLength = 0x1B; - static const uint32_t vqIndexMask = 0x03; - static const uint32_t vqColorMask = 0xFFFFFF; - - static const int blockAsT2100StartLength = 0x04; - static const int blockAsT2100SkipLength = 20; // S:1 H:3 X:8 Y:8 - - do { - auto blockHeader = static_cast<JpgBlock>((codebuf >> 28) & 0xFF); - switch (blockHeader) { - case JpgBlock::JPEG_NO_SKIP_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits, - bufferVector); - decompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0); - break; - case JpgBlock::FRAME_END_CODE: - return 0; - break; - case JpgBlock::JPEG_SKIP_CODE: - - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits, - bufferVector); - decompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0); - break; - case JpgBlock::VQ_NO_SKIP_1_COLOR_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits, - bufferVector); - decodeColor.bitMapBits = 0; - - for (int i = 0; i < 1; i++) { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits, - bufferVector); - } else { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits, - bufferVector); - } - } - vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - break; - case JpgBlock::VQ_SKIP_1_COLOR_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits, - bufferVector); - decodeColor.bitMapBits = 0; - - for (int i = 0; i < 1; i++) { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits, - bufferVector); - } else { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits, - bufferVector); - } - } - vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - break; - - case JpgBlock::VQ_NO_SKIP_2_COLOR_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits, - bufferVector); - decodeColor.bitMapBits = 1; - - for (int i = 0; i < 2; i++) { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits, - bufferVector); - } else { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits, - bufferVector); - } - } - vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - break; - case JpgBlock::VQ_SKIP_2_COLOR_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits, - bufferVector); - decodeColor.bitMapBits = 1; - - for (int i = 0; i < 2; i++) { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits, - bufferVector); - } else { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits, - bufferVector); - } - } - vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - - break; - case JpgBlock::VQ_NO_SKIP_4_COLOR_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits, - bufferVector); - decodeColor.bitMapBits = 2; - - for (unsigned char &i : decodeColor.index) { - i = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits, - bufferVector); - } else { - decodeColor.color[i] = ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits, - bufferVector); + int initJpgDecoding() + { + bytePos = 0; + loadQuantTable(qt[0]); + loadQuantTableCb(qt[1]); + // Note: Added for Dual-JPEG + loadAdvanceQuantTable(qt[2]); + loadAdvanceQuantTableCb(qt[3]); + return 1; + } + + void setQuantTable(const uint8_t *basic_table, uint8_t scale_factor, + std::array<uint8_t, 64> &newtable) + // Set quantization table and zigzag reorder it + { + uint8_t i; + long temp; + for (i = 0; i < 64; i++) + { + temp = (static_cast<long>(basic_table[i] * 16) / scale_factor); + /* limit the values to the valid range */ + if (temp <= 0L) + { + temp = 1L; } - } - vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - - break; - - case JpgBlock::VQ_SKIP_4_COLOR_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits, - bufferVector); - decodeColor.bitMapBits = 2; - - for (unsigned char &i : decodeColor.index) { - i = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits, - bufferVector); - } else { - decodeColor.color[i] = ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits, - bufferVector); + if (temp > 255L) + { + temp = 255L; /* limit to baseline range if requested */ } - } - vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); + newtable[zigzag[i]] = static_cast<uint8_t>(temp); + } + } - break; - case JpgBlock::JPEG_SKIP_PASS2_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; + void updatereadbuf(uint32_t *codebuf, uint32_t *newbuf, int walks, + int *newbits, std::vector<uint32_t> &buffer) + { + unsigned long readbuf; + + if ((*newbits - walks) <= 0) + { + readbuf = buffer[bufferIndex]; + bufferIndex++; + *codebuf = (*codebuf << walks) | + ((*newbuf | (readbuf >> (*newbits))) >> (32 - walks)); + *newbuf = readbuf << (walks - *newbits); + *newbits = 32 + *newbits - walks; + } + else + { + *codebuf = (*codebuf << walks) | (*newbuf >> (32 - walks)); + *newbuf = *newbuf << walks; + *newbits -= walks; + } + } - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits, - bufferVector); - decompress2Pass(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), - 2); + uint32_t decode(std::vector<uint32_t> &bufferVector, unsigned long width, + unsigned long height, YuvMode yuvmode_in, int ySelector, + int uvSelector) + { + ColorCache decodeColor; + if (width != userWidth || height != userHeight || + yuvmode_in != yuvmode || ySelector != ySelector || + uvSelector != uvSelector) + { + yuvmode = yuvmode_in; + ySelector = ySelector; // 0-7 + uvSelector = uvSelector; // 0-7 + userHeight = height; + userWidth = width; + width = width; + height = height; + + // TODO(ed) Magic number section. Document appropriately + advanceSelector = 0; // 0-7 + mapping = 0; // 0 or 1 + + if (yuvmode == YuvMode::YUV420) + { + if ((width % 16) != 0u) + { + width = width + 16 - (width % 16); + } + if ((height % 16) != 0u) + { + height = height + 16 - (height % 16); + } + } + else + { + if ((width % 8) != 0u) + { + width = width + 8 - (width % 8); + } + if ((height % 8) != 0u) + { + height = height + 8 - (height % 8); + } + } - break; - default: - // TODO(ed) propogate errors upstream - return -1; - break; - } - moveBlockIndex(); + initJpgDecoding(); + } + // TODO(ed) cleanup cruft + buffer = bufferVector.data(); + + codebuf = bufferVector[0]; + newbuf = bufferVector[1]; + bufferIndex = 2; + + txb = tyb = 0; + newbits = 32; + dcy = dcCb = dcCr = 0; + + static const uint32_t vqHeaderMask = 0x01; + static const uint32_t vqNoUpdateHeader = 0x00; + static const uint32_t vqUpdateHeader = 0x01; + static const int vqNoUpdateLength = 0x03; + static const int vqUpdateLength = 0x1B; + static const uint32_t vqIndexMask = 0x03; + static const uint32_t vqColorMask = 0xFFFFFF; + + static const int blockAsT2100StartLength = 0x04; + static const int blockAsT2100SkipLength = 20; // S:1 H:3 X:8 Y:8 + + do + { + auto blockHeader = static_cast<JpgBlock>((codebuf >> 28) & 0xFF); + switch (blockHeader) + { + case JpgBlock::JPEG_NO_SKIP_CODE: + updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, + &newbits, bufferVector); + decompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0); + break; + case JpgBlock::FRAME_END_CODE: + return 0; + break; + case JpgBlock::JPEG_SKIP_CODE: + + txb = (codebuf & 0x0FF00000) >> 20; + tyb = (codebuf & 0x0FF000) >> 12; + + updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, + &newbits, bufferVector); + decompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0); + break; + case JpgBlock::VQ_NO_SKIP_1_COLOR_CODE: + updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, + &newbits, bufferVector); + decodeColor.bitMapBits = 0; + + for (int i = 0; i < 1; i++) + { + decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); + if (((codebuf >> 31) & vqHeaderMask) == + vqNoUpdateHeader) + { + updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, + &newbits, bufferVector); + } + else + { + decodeColor.color[decodeColor.index[i]] = + ((codebuf >> 5) & vqColorMask); + updatereadbuf(&codebuf, &newbuf, vqUpdateLength, + &newbits, bufferVector); + } + } + vqDecompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0, + &decodeColor); + break; + case JpgBlock::VQ_SKIP_1_COLOR_CODE: + txb = (codebuf & 0x0FF00000) >> 20; + tyb = (codebuf & 0x0FF000) >> 12; + + updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, + &newbits, bufferVector); + decodeColor.bitMapBits = 0; + + for (int i = 0; i < 1; i++) + { + decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); + if (((codebuf >> 31) & vqHeaderMask) == + vqNoUpdateHeader) + { + updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, + &newbits, bufferVector); + } + else + { + decodeColor.color[decodeColor.index[i]] = + ((codebuf >> 5) & vqColorMask); + updatereadbuf(&codebuf, &newbuf, vqUpdateLength, + &newbits, bufferVector); + } + } + vqDecompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0, + &decodeColor); + break; + + case JpgBlock::VQ_NO_SKIP_2_COLOR_CODE: + updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, + &newbits, bufferVector); + decodeColor.bitMapBits = 1; + + for (int i = 0; i < 2; i++) + { + decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); + if (((codebuf >> 31) & vqHeaderMask) == + vqNoUpdateHeader) + { + updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, + &newbits, bufferVector); + } + else + { + decodeColor.color[decodeColor.index[i]] = + ((codebuf >> 5) & vqColorMask); + updatereadbuf(&codebuf, &newbuf, vqUpdateLength, + &newbits, bufferVector); + } + } + vqDecompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0, + &decodeColor); + break; + case JpgBlock::VQ_SKIP_2_COLOR_CODE: + txb = (codebuf & 0x0FF00000) >> 20; + tyb = (codebuf & 0x0FF000) >> 12; + + updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, + &newbits, bufferVector); + decodeColor.bitMapBits = 1; + + for (int i = 0; i < 2; i++) + { + decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); + if (((codebuf >> 31) & vqHeaderMask) == + vqNoUpdateHeader) + { + updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, + &newbits, bufferVector); + } + else + { + decodeColor.color[decodeColor.index[i]] = + ((codebuf >> 5) & vqColorMask); + updatereadbuf(&codebuf, &newbuf, vqUpdateLength, + &newbits, bufferVector); + } + } + vqDecompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0, + &decodeColor); + + break; + case JpgBlock::VQ_NO_SKIP_4_COLOR_CODE: + updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, + &newbits, bufferVector); + decodeColor.bitMapBits = 2; + + for (unsigned char &i : decodeColor.index) + { + i = ((codebuf >> 29) & vqIndexMask); + if (((codebuf >> 31) & vqHeaderMask) == + vqNoUpdateHeader) + { + updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, + &newbits, bufferVector); + } + else + { + decodeColor.color[i] = + ((codebuf >> 5) & vqColorMask); + updatereadbuf(&codebuf, &newbuf, vqUpdateLength, + &newbits, bufferVector); + } + } + vqDecompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0, + &decodeColor); + + break; + + case JpgBlock::VQ_SKIP_4_COLOR_CODE: + txb = (codebuf & 0x0FF00000) >> 20; + tyb = (codebuf & 0x0FF000) >> 12; + + updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, + &newbits, bufferVector); + decodeColor.bitMapBits = 2; + + for (unsigned char &i : decodeColor.index) + { + i = ((codebuf >> 29) & vqIndexMask); + if (((codebuf >> 31) & vqHeaderMask) == + vqNoUpdateHeader) + { + updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, + &newbits, bufferVector); + } + else + { + decodeColor.color[i] = + ((codebuf >> 5) & vqColorMask); + updatereadbuf(&codebuf, &newbuf, vqUpdateLength, + &newbits, bufferVector); + } + } + vqDecompress(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), 0, + &decodeColor); + + break; + case JpgBlock::JPEG_SKIP_PASS2_CODE: + txb = (codebuf & 0x0FF00000) >> 20; + tyb = (codebuf & 0x0FF000) >> 12; + + updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, + &newbits, bufferVector); + decompress2Pass(txb, tyb, + reinterpret_cast<char *>(outBuffer.data()), + 2); + + break; + default: + // TODO(ed) propogate errors upstream + return -1; + break; + } + moveBlockIndex(); - } while (bufferIndex <= bufferVector.size()); + } while (bufferIndex <= bufferVector.size()); - return -1; - } + return -1; + } #ifdef cimg_version - void dump_to_bitmap_file() { - cimg_library::CImg<unsigned char> image(width, height, 1, 3); - for (int y = 0; y < width; y++) { - for (int x = 0; x < height; x++) { - auto pixel = outBuffer[x + (y * width)]; - image(x, y, 0) = pixel.r; - image(x, y, 1) = pixel.g; - image(x, y, 2) = pixel.b; - } + void dump_to_bitmap_file() + { + cimg_library::CImg<unsigned char> image(width, height, 1, 3); + for (int y = 0; y < width; y++) + { + for (int x = 0; x < height; x++) + { + auto pixel = outBuffer[x + (y * width)]; + image(x, y, 0) = pixel.r; + image(x, y, 1) = pixel.g; + image(x, y, 2) = pixel.b; + } + } + image.save("/tmp/file2.bmp"); } - image.save("/tmp/file2.bmp"); - } #endif - private: - YuvMode yuvmode{}; - // width and height are the modes your display used - unsigned long width{}; - unsigned long height{}; - unsigned long userWidth{}; - unsigned long userHeight{}; - unsigned char ySelector{}; - int scalefactor; - int scalefactoruv; - int advancescalefactor; - int advancescalefactoruv; - int mapping{}; - unsigned char uvSelector{}; - unsigned char advanceSelector{}; - int bytePos{}; // current byte position - - // quantization tables, no more than 4 quantization tables - std::array<std::array<long, 64>, 4> qt{}; - - // DC huffman tables , no more than 4 (0..3) - std::array<HuffmanTable, 4> htdc{}; - // AC huffman tables (0..3) - std::array<HuffmanTable, 4> htac{}; - std::array<int, 256> mCrToR{}; - std::array<int, 256> mCbToB{}; - std::array<int, 256> mCrToG{}; - std::array<int, 256> mCbToG{}; - std::array<int, 256> mY{}; - unsigned long bufferIndex{}; - uint32_t codebuf{}, newbuf{}, readbuf{}; - const unsigned char *stdLuminanceQt{}; - const uint8_t *stdChrominanceQt{}; - - signed short int dcy{}, dcCb{}, dcCr{}; // Coeficientii DC pentru Y,Cb,Cr - signed short int dctCoeff[384]{}; - // std::vector<signed short int> dctCoeff; // Current DCT_coefficients - // quantization table number for Y, Cb, Cr - uint8_t yqNr = 0, cbQNr = 1, crQNr = 1; - // DC Huffman table number for Y,Cb, Cr - uint8_t ydcNr = 0, cbDcNr = 1, crDcNr = 1; - // AC Huffman table number for Y,Cb, Cr - uint8_t yacNr = 0, cbAcNr = 1, crAcNr = 1; - int txb = 0; - int tyb = 0; - int newbits{}; - uint8_t *rlimitTable{}; - std::vector<RGB> yuvBuffer; - // TODO(ed) this shouldn't exist. It is cruft that needs cleaning up - uint32_t *buffer{}; - - public: - std::vector<RGB> outBuffer; + private: + YuvMode yuvmode{}; + // width and height are the modes your display used + unsigned long width{}; + unsigned long height{}; + unsigned long userWidth{}; + unsigned long userHeight{}; + unsigned char ySelector{}; + int scalefactor; + int scalefactoruv; + int advancescalefactor; + int advancescalefactoruv; + int mapping{}; + unsigned char uvSelector{}; + unsigned char advanceSelector{}; + int bytePos{}; // current byte position + + // quantization tables, no more than 4 quantization tables + std::array<std::array<long, 64>, 4> qt{}; + + // DC huffman tables , no more than 4 (0..3) + std::array<HuffmanTable, 4> htdc{}; + // AC huffman tables (0..3) + std::array<HuffmanTable, 4> htac{}; + std::array<int, 256> mCrToR{}; + std::array<int, 256> mCbToB{}; + std::array<int, 256> mCrToG{}; + std::array<int, 256> mCbToG{}; + std::array<int, 256> mY{}; + unsigned long bufferIndex{}; + uint32_t codebuf{}, newbuf{}, readbuf{}; + const unsigned char *stdLuminanceQt{}; + const uint8_t *stdChrominanceQt{}; + + signed short int dcy{}, dcCb{}, dcCr{}; // Coeficientii DC pentru Y,Cb,Cr + signed short int dctCoeff[384]{}; + // std::vector<signed short int> dctCoeff; // Current DCT_coefficients + // quantization table number for Y, Cb, Cr + uint8_t yqNr = 0, cbQNr = 1, crQNr = 1; + // DC Huffman table number for Y,Cb, Cr + uint8_t ydcNr = 0, cbDcNr = 1, crDcNr = 1; + // AC Huffman table number for Y,Cb, Cr + uint8_t yacNr = 0, cbAcNr = 1, crAcNr = 1; + int txb = 0; + int tyb = 0; + int newbits{}; + uint8_t *rlimitTable{}; + std::vector<RGB> yuvBuffer; + // TODO(ed) this shouldn't exist. It is cruft that needs cleaning up + uint32_t *buffer{}; + + public: + std::vector<RGB> outBuffer; }; -} // namespace ast_video
\ No newline at end of file +} // namespace ast_video
\ No newline at end of file |